aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-04-19 13:38:25 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-04-19 13:38:25 -0300
commit973d81efb37d6d001cb10c987e0171e5500b9688 (patch)
tree4075a860158f7668de8f49f2a8d31e76d7ea1eb4
parent26d4a7396248623985b59d7e027cfecee561f446 (diff)
downloadlua-973d81efb37d6d001cb10c987e0171e5500b9688.tar.gz
lua-973d81efb37d6d001cb10c987e0171e5500b9688.tar.bz2
lua-973d81efb37d6d001cb10c987e0171e5500b9688.zip
complete control over number of each kind of object allocated
-rw-r--r--ltests.c99
1 files changed, 53 insertions, 46 deletions
diff --git a/ltests.c b/ltests.c
index da3aec94..ff0086a8 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.94 2010/04/13 20:48:12 roberto Exp roberto $ 2** $Id: ltests.c,v 2.95 2010/04/16 17:42:49 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -74,90 +74,97 @@ static int tpanic (lua_State *L) {
74 74
75#define MARK 0x55 /* 01010101 (a nice pattern) */ 75#define MARK 0x55 /* 01010101 (a nice pattern) */
76 76
77typedef union Header {
78 L_Umaxalign a; /* ensures maximum alignment for Header */
79 struct {
80 size_t size;
81 int type;
82 } d;
83} Header;
84
85
77#ifndef EXTERNMEMCHECK 86#ifndef EXTERNMEMCHECK
87
78/* full memory check */ 88/* full memory check */
79#define HEADER (sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */
80#define MARKSIZE 16 /* size of marks after each block */ 89#define MARKSIZE 16 /* size of marks after each block */
81#define blockhead(b) (cast(char *, b) - HEADER)
82#define setsize(newblock, size) (*cast(size_t *, newblock) = size)
83#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b))))
84#define fillmem(mem,size) memset(mem, -MARK, size) 90#define fillmem(mem,size) memset(mem, -MARK, size)
91
85#else 92#else
93
86/* external memory check: don't do it twice */ 94/* external memory check: don't do it twice */
87#define HEADER 0
88#define MARKSIZE 0 95#define MARKSIZE 0
89#define blockhead(b) (b)
90#define setsize(newblock, size) /* empty */
91#define checkblocksize(b,size) (1)
92#define fillmem(mem,size) /* empty */ 96#define fillmem(mem,size) /* empty */
97
93#endif 98#endif
94 99
100
95Memcontrol l_memcontrol = 101Memcontrol l_memcontrol =
96 {0L, 0L, 0L, 0L, {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L}}; 102 {0L, 0L, 0L, 0L, {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L}};
97 103
98 104
99static void *checkblock (void *block, size_t size) { 105static void freeblock (Memcontrol *mc, Header *block) {
100 void *b = blockhead(block);
101 int i;
102 for (i=0;i<MARKSIZE;i++)
103 lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */
104 return b;
105}
106
107
108static void freeblock (Memcontrol *mc, void *block, size_t size) {
109 if (block) { 106 if (block) {
110 lua_assert(checkblocksize(block, size)); 107 size_t size = block->d.size;
111 block = checkblock(block, size); 108 int i;
112 fillmem(block, size+HEADER+MARKSIZE); /* erase block */ 109 for (i = 0; i < MARKSIZE; i++) /* check marks after block */
113 free(block); /* free original block */ 110 lua_assert(*(cast(char *, block + 1) + size + i) == MARK);
114 mc->numblocks--; 111 mc->objcount[block->d.type]--;
112 fillmem(block, sizeof(Header) + size + MARKSIZE); /* erase block */
113 free(block); /* actually free block */
114 mc->numblocks--; /* update counts */
115 mc->total -= size; 115 mc->total -= size;
116 } 116 }
117} 117}
118 118
119 119
120void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) { 120void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) {
121 Memcontrol *mc = cast(Memcontrol *, ud); 121 Memcontrol *mc = cast(Memcontrol *, ud);
122 if (block == NULL) { 122 Header *block = cast(Header *, b);
123 if (oldsize < LUA_NUMTAGS) 123 int type;
124 mc->objcount[oldsize]++;
125 oldsize = 0;
126 }
127 lua_assert((oldsize == 0) ? block == NULL :
128 block && checkblocksize(block, oldsize));
129 if (mc->memlimit == 0) { /* first time? */ 124 if (mc->memlimit == 0) { /* first time? */
130 char *limit = getenv("MEMLIMIT"); /* initialize memory limit */ 125 char *limit = getenv("MEMLIMIT"); /* initialize memory limit */
131 mc->memlimit = limit ? strtoul(limit, NULL, 10) : ULONG_MAX; 126 mc->memlimit = limit ? strtoul(limit, NULL, 10) : ULONG_MAX;
132 } 127 }
128 if (block == NULL) {
129 type = (oldsize < LUA_NUMTAGS) ? oldsize : 0;
130 oldsize = 0;
131 }
132 else {
133 block--; /* go to real header */
134 type = block->d.type;
135 lua_assert(oldsize == block->d.size);
136 }
133 if (size == 0) { 137 if (size == 0) {
134 freeblock(mc, block, oldsize); 138 freeblock(mc, block);
135 return NULL; 139 return NULL;
136 } 140 }
137 else if (size > oldsize && mc->total+size-oldsize > mc->memlimit) 141 else if (size > oldsize && mc->total+size-oldsize > mc->memlimit)
138 return NULL; /* to test memory allocation errors */ 142 return NULL; /* fake a memory allocation error */
139 else { 143 else {
140 void *newblock; 144 Header *newblock;
141 int i; 145 int i;
142 size_t realsize = HEADER+size+MARKSIZE;
143 size_t commonsize = (oldsize < size) ? oldsize : size; 146 size_t commonsize = (oldsize < size) ? oldsize : size;
144 if (realsize < size) return NULL; /* overflow! */ 147 size_t realsize = sizeof(Header) + size + MARKSIZE;
145 newblock = malloc(realsize); /* alloc a new block */ 148 if (realsize < size) return NULL; /* arithmetic overflow! */
146 if (newblock == NULL) return NULL; 149 newblock = cast(Header *, malloc(realsize)); /* alloc a new block */
150 if (newblock == NULL) return NULL; /* really out of memory? */
147 if (block) { 151 if (block) {
148 memcpy(cast(char *, newblock)+HEADER, block, commonsize); 152 memcpy(newblock + 1, block + 1, commonsize); /* copy old contents */
149 freeblock(mc, block, oldsize); /* erase (and check) old copy */ 153 freeblock(mc, block); /* erase (and check) old copy */
150 } 154 }
151 /* initialize new part of the block with something `weird' */ 155 /* initialize new part of the block with something `weird' */
152 fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize); 156 fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize);
157 /* initialize marks after block */
158 for (i = 0; i < MARKSIZE; i++)
159 *(cast(char *, newblock + 1) + size + i) = MARK;
160 newblock->d.size = size;
161 newblock->d.type = type;
153 mc->total += size; 162 mc->total += size;
154 if (mc->total > mc->maxmem) 163 if (mc->total > mc->maxmem)
155 mc->maxmem = mc->total; 164 mc->maxmem = mc->total;
156 mc->numblocks++; 165 mc->numblocks++;
157 setsize(newblock, size); 166 mc->objcount[type]++;
158 for (i=0;i<MARKSIZE;i++) 167 return newblock + 1;
159 *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
160 return cast(char *, newblock)+HEADER;
161 } 168 }
162} 169}
163 170