diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-04-19 13:38:25 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-04-19 13:38:25 -0300 |
commit | 973d81efb37d6d001cb10c987e0171e5500b9688 (patch) | |
tree | 4075a860158f7668de8f49f2a8d31e76d7ea1eb4 | |
parent | 26d4a7396248623985b59d7e027cfecee561f446 (diff) | |
download | lua-973d81efb37d6d001cb10c987e0171e5500b9688.tar.gz lua-973d81efb37d6d001cb10c987e0171e5500b9688.tar.bz2 lua-973d81efb37d6d001cb10c987e0171e5500b9688.zip |
complete control over number of each kind of object allocated
-rw-r--r-- | ltests.c | 99 |
1 files changed, 53 insertions, 46 deletions
@@ -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 | ||
77 | typedef 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 | |||
95 | Memcontrol l_memcontrol = | 101 | Memcontrol 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 | ||
99 | static void *checkblock (void *block, size_t size) { | 105 | static 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 | |||
108 | static 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 | ||
120 | void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) { | 120 | void *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 | ||