1 /*
2 ** $Id: lmem.c,v 1.1 2002/02/14 10:46:59 jcatki Exp $
3 ** Interface to Memory Manager
4 ** See Copyright Notice in lua.h
5 */
6
7
8 #include <stdlib.h>
9
10 #include "lua.h"
11
12 #include "ldo.h"
13 #include "lmem.h"
14 #include "lobject.h"
15 #include "lstate.h"
16
17
18
19
20 #ifdef LUA_DEBUG
21 /*
22 ** {======================================================================
23 ** Controlled version for realloc.
24 ** =======================================================================
25 */
26
27
28 #include <assert.h>
29 #include <limits.h>
30 #include <string.h>
31
32 #define realloc(b, s) debug_realloc(b, s)
33 #define malloc(b) debug_realloc(NULL, b)
34 #define free(b) debug_realloc(b, 0)
35
36
37 /* ensures maximum alignment for HEADER */
38 #define HEADER (sizeof(union L_Umaxalign))
39
40 #define MARKSIZE 16
41 #define MARK 0x55 /* 01010101 (a nice pattern) */
42
43
44 #define blocksize(b) ((unsigned long *)((char *)(b) - HEADER))
45
46 unsigned long memdebug_numblocks = 0;
47 unsigned long memdebug_total = 0;
48 unsigned long memdebug_maxmem = 0;
49 unsigned long memdebug_memlimit = LONG_MAX;
50
51
checkblock(void * block)52 static void *checkblock (void *block) {
53 unsigned long *b = blocksize(block);
54 unsigned long size = *b;
55 int i;
56 for (i=0;i<MARKSIZE;i++)
57 assert(*(((char *)b)+HEADER+size+i) == MARK+i); /* corrupted block? */
58 memdebug_numblocks--;
59 memdebug_total -= size;
60 return b;
61 }
62
63
freeblock(void * block)64 static void freeblock (void *block) {
65 if (block) {
66 size_t size = *blocksize(block);
67 block = checkblock(block);
68 memset(block, -1, size+HEADER+MARKSIZE); /* erase block */
69 (free)(block); /* free original block */
70 }
71 }
72
73
debug_realloc(void * block,size_t size)74 static void *debug_realloc (void *block, size_t size) {
75 if (size == 0) {
76 freeblock(block);
77 return NULL;
78 }
79 else if (memdebug_total+size > memdebug_memlimit)
80 return NULL; /* to test memory allocation errors */
81 else {
82 size_t realsize = HEADER+size+MARKSIZE;
83 char *newblock = (char *)(malloc)(realsize); /* alloc a new block */
84 int i;
85 if (realsize < size) return NULL; /* overflow! */
86 if (newblock == NULL) return NULL;
87 if (block) {
88 size_t oldsize = *blocksize(block);
89 if (oldsize > size) oldsize = size;
90 memcpy(newblock+HEADER, block, oldsize);
91 freeblock(block); /* erase (and check) old copy */
92 }
93 memdebug_total += size;
94 if (memdebug_total > memdebug_maxmem) memdebug_maxmem = memdebug_total;
95 memdebug_numblocks++;
96 *(unsigned long *)newblock = size;
97 for (i=0;i<MARKSIZE;i++)
98 *(newblock+HEADER+size+i) = (char)(MARK+i);
99 return newblock+HEADER;
100 }
101 }
102
103
104 /* }====================================================================== */
105 #endif
106
107
108
109 /*
110 ** Real ISO (ANSI) systems do not need these tests;
111 ** but some systems (Sun OS) are not that ISO...
112 */
113 #ifdef OLD_ANSI
114 #define realloc(b,s) ((b) == NULL ? malloc(s) : (realloc)(b, s))
115 #define free(b) if (b) (free)(b)
116 #endif
117
118
luaM_growaux(lua_State * L,void * block,size_t nelems,int inc,size_t size,const char * errormsg,size_t limit)119 void *luaM_growaux (lua_State *L, void *block, size_t nelems,
120 int inc, size_t size, const char *errormsg, size_t limit) {
121 size_t newn = nelems+inc;
122 if (nelems >= limit-inc) lua_error(L, errormsg);
123 if ((newn ^ nelems) <= nelems || /* still the same power-of-2 limit? */
124 (nelems > 0 && newn < MINPOWER2)) /* or block already is MINPOWER2? */
125 return block; /* do not need to reallocate */
126 else /* it crossed a power-of-2 boundary; grow to next power */
127 return luaM_realloc(L, block, luaO_power2(newn)*size);
128 }
129
130
131 /*
132 ** generic allocation routine.
133 */
luaM_realloc(lua_State * L,void * block,lint32 size)134 void *luaM_realloc (lua_State *L, void *block, lint32 size) {
135 if (size == 0) {
136 free(block); /* block may be NULL; that is OK for free */
137 return NULL;
138 }
139 else if (size >= MAX_SIZET)
140 lua_error(L, "memory allocation error: block too big");
141 block = realloc(block, size);
142 if (block == NULL) {
143 if (L)
144 luaD_breakrun(L, LUA_ERRMEM); /* break run without error message */
145 else return NULL; /* error before creating state! */
146 }
147 return block;
148 }
149
150
151