diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-12-28 10:55:41 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-12-28 10:55:41 -0200 |
commit | 0183b8030c80f57b87874ff7867ccdb172d9d3dc (patch) | |
tree | 1033b5a84489a2f1f1bd210b1b120155cd7aeed7 /lmem.c | |
parent | 8c49e198654567f770a7d5081b886a7c35201d81 (diff) | |
download | lua-0183b8030c80f57b87874ff7867ccdb172d9d3dc.tar.gz lua-0183b8030c80f57b87874ff7867ccdb172d9d3dc.tar.bz2 lua-0183b8030c80f57b87874ff7867ccdb172d9d3dc.zip |
`free' gets size of the block: complete control over memory use
Diffstat (limited to 'lmem.c')
-rw-r--r-- | lmem.c | 71 |
1 files changed, 43 insertions, 28 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lmem.c,v 1.40 2000/11/24 17:39:56 roberto Exp roberto $ | 2 | ** $Id: lmem.c,v 1.41 2000/12/26 18:46:09 roberto Exp roberto $ |
3 | ** Interface to Memory Manager | 3 | ** Interface to Memory Manager |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -29,15 +29,14 @@ | |||
29 | #include <limits.h> | 29 | #include <limits.h> |
30 | #include <string.h> | 30 | #include <string.h> |
31 | 31 | ||
32 | #define realloc(b, s) debug_realloc(b, s) | 32 | #define basicrealloc(b, os, s) debug_realloc(b, os, s) |
33 | #define malloc(b) debug_realloc(NULL, b) | 33 | #define basicfree(b, s) debug_realloc(b, s, 0) |
34 | #define free(b) debug_realloc(b, 0) | ||
35 | 34 | ||
36 | 35 | ||
37 | /* ensures maximum alignment for HEADER */ | 36 | /* ensures maximum alignment for HEADER */ |
38 | #define HEADER (sizeof(union L_Umaxalign)) | 37 | #define HEADER (sizeof(union L_Umaxalign)) |
39 | 38 | ||
40 | #define MARKSIZE 16 | 39 | #define MARKSIZE 32 |
41 | #define MARK 0x55 /* 01010101 (a nice pattern) */ | 40 | #define MARK 0x55 /* 01010101 (a nice pattern) */ |
42 | 41 | ||
43 | 42 | ||
@@ -55,8 +54,6 @@ static void *checkblock (void *block) { | |||
55 | int i; | 54 | int i; |
56 | for (i=0;i<MARKSIZE;i++) | 55 | for (i=0;i<MARKSIZE;i++) |
57 | assert(*(((char *)b)+HEADER+size+i) == MARK+i); /* corrupted block? */ | 56 | assert(*(((char *)b)+HEADER+size+i) == MARK+i); /* corrupted block? */ |
58 | memdebug_numblocks--; | ||
59 | memdebug_total -= size; | ||
60 | return b; | 57 | return b; |
61 | } | 58 | } |
62 | 59 | ||
@@ -66,12 +63,15 @@ static void freeblock (void *block) { | |||
66 | size_t size = *blocksize(block); | 63 | size_t size = *blocksize(block); |
67 | block = checkblock(block); | 64 | block = checkblock(block); |
68 | memset(block, -1, size+HEADER+MARKSIZE); /* erase block */ | 65 | memset(block, -1, size+HEADER+MARKSIZE); /* erase block */ |
69 | (free)(block); /* free original block */ | 66 | free(block); /* free original block */ |
67 | memdebug_numblocks--; | ||
68 | memdebug_total -= size; | ||
70 | } | 69 | } |
71 | } | 70 | } |
72 | 71 | ||
73 | 72 | ||
74 | static void *debug_realloc (void *block, size_t size) { | 73 | static void *debug_realloc (void *block, size_t oldsize, size_t size) { |
74 | assert((oldsize == 0) ? block == NULL : oldsize == *blocksize(block)); | ||
75 | if (size == 0) { | 75 | if (size == 0) { |
76 | freeblock(block); | 76 | freeblock(block); |
77 | return NULL; | 77 | return NULL; |
@@ -79,19 +79,22 @@ static void *debug_realloc (void *block, size_t size) { | |||
79 | else if (memdebug_total+size > memdebug_memlimit) | 79 | else if (memdebug_total+size > memdebug_memlimit) |
80 | return NULL; /* to test memory allocation errors */ | 80 | return NULL; /* to test memory allocation errors */ |
81 | else { | 81 | else { |
82 | size_t realsize = HEADER+size+MARKSIZE; | 82 | char *newblock; |
83 | char *newblock = (char *)(malloc)(realsize); /* alloc a new block */ | ||
84 | int i; | 83 | int i; |
84 | size_t realsize = HEADER+size+MARKSIZE; | ||
85 | if (realsize < size) return NULL; /* overflow! */ | 85 | if (realsize < size) return NULL; /* overflow! */ |
86 | newblock = (char *)malloc(realsize); /* alloc a new block */ | ||
86 | if (newblock == NULL) return NULL; | 87 | if (newblock == NULL) return NULL; |
88 | if (oldsize > size) oldsize = size; | ||
87 | if (block) { | 89 | if (block) { |
88 | size_t oldsize = *blocksize(block); | ||
89 | if (oldsize > size) oldsize = size; | ||
90 | memcpy(newblock+HEADER, block, oldsize); | 90 | memcpy(newblock+HEADER, block, oldsize); |
91 | freeblock(block); /* erase (and check) old copy */ | 91 | freeblock(block); /* erase (and check) old copy */ |
92 | } | 92 | } |
93 | /* initialize new part of the block with something `weird' */ | ||
94 | memset(newblock+HEADER+oldsize, -MARK, size-oldsize); | ||
93 | memdebug_total += size; | 95 | memdebug_total += size; |
94 | if (memdebug_total > memdebug_maxmem) memdebug_maxmem = memdebug_total; | 96 | if (memdebug_total > memdebug_maxmem) |
97 | memdebug_maxmem = memdebug_total; | ||
95 | memdebug_numblocks++; | 98 | memdebug_numblocks++; |
96 | *(size_t *)newblock = size; | 99 | *(size_t *)newblock = size; |
97 | for (i=0;i<MARKSIZE;i++) | 100 | for (i=0;i<MARKSIZE;i++) |
@@ -102,20 +105,26 @@ static void *debug_realloc (void *block, size_t size) { | |||
102 | 105 | ||
103 | 106 | ||
104 | /* }====================================================================== */ | 107 | /* }====================================================================== */ |
105 | #endif | ||
106 | |||
107 | 108 | ||
109 | #else | ||
110 | /* no debug */ | ||
108 | 111 | ||
109 | /* | 112 | /* |
110 | ** Real ISO (ANSI) systems do not need these tests; | 113 | ** Real ISO (ANSI) systems do not need these tests; |
111 | ** but some systems (Sun OS) are not that ISO... | 114 | ** but some systems (Sun OS) are not that ISO... |
112 | */ | 115 | */ |
113 | #ifdef OLD_ANSI | 116 | #ifdef OLD_ANSI |
114 | #define realloc(b,s) ((b) == NULL ? malloc(s) : (realloc)(b, s)) | 117 | #define basicrealloc(b,os,s) ((b) == NULL ? malloc(s) : realloc(b, s)) |
115 | #define free(b) if (b) (free)(b) | 118 | #define basicfree(b,s) if (b) free(b) |
119 | #else | ||
120 | #define basicrealloc(b,os,s) realloc(b,s) | ||
121 | #define basicfree(b,s) free(b) | ||
122 | |||
116 | #endif | 123 | #endif |
117 | 124 | ||
118 | 125 | ||
126 | #endif | ||
127 | |||
119 | void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems, | 128 | void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems, |
120 | int limit, const char *errormsg) { | 129 | int limit, const char *errormsg) { |
121 | void *newblock; | 130 | void *newblock; |
@@ -127,7 +136,8 @@ void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems, | |||
127 | newsize = limit; /* still have at least MINPOWER2 free places */ | 136 | newsize = limit; /* still have at least MINPOWER2 free places */ |
128 | else lua_error(L, errormsg); | 137 | else lua_error(L, errormsg); |
129 | } | 138 | } |
130 | newblock = luaM_realloc(L, block, (luint32)newsize*(luint32)size_elems); | 139 | newblock = luaM_realloc(L, block, (luint32)(*size)*(luint32)size_elems, |
140 | (luint32)newsize*(luint32)size_elems); | ||
131 | *size = newsize; /* update only when everything else is OK */ | 141 | *size = newsize; /* update only when everything else is OK */ |
132 | return newblock; | 142 | return newblock; |
133 | } | 143 | } |
@@ -136,20 +146,25 @@ void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems, | |||
136 | /* | 146 | /* |
137 | ** generic allocation routine. | 147 | ** generic allocation routine. |
138 | */ | 148 | */ |
139 | void *luaM_realloc (lua_State *L, void *block, luint32 size) { | 149 | void *luaM_realloc (lua_State *L, void *block, luint32 oldsize, luint32 size) { |
140 | if (size == 0) { | 150 | if (size == 0) { |
141 | free(block); /* block may be NULL; that is OK for free */ | 151 | basicfree(block, oldsize); /* block may be NULL; that is OK for free */ |
142 | return NULL; | 152 | block = NULL; |
143 | } | 153 | } |
144 | else if (size >= MAX_SIZET) | 154 | else if (size >= MAX_SIZET) |
145 | lua_error(L, "memory allocation error: block too big"); | 155 | lua_error(L, "memory allocation error: block too big"); |
146 | block = realloc(block, size); | 156 | else { |
147 | if (block == NULL) { | 157 | block = basicrealloc(block, oldsize, size); |
148 | if (L) | 158 | if (block == NULL) { |
149 | luaD_breakrun(L, LUA_ERRMEM); /* break run without error message */ | 159 | if (L) |
150 | else return NULL; /* error before creating state! */ | 160 | luaD_breakrun(L, LUA_ERRMEM); /* break run without error message */ |
161 | else return NULL; /* error before creating state! */ | ||
162 | } | ||
163 | } | ||
164 | if (L) { | ||
165 | L->nblocks -= oldsize; | ||
166 | L->nblocks += size; | ||
151 | } | 167 | } |
152 | return block; | 168 | return block; |
153 | } | 169 | } |
154 | 170 | ||
155 | |||