Commit | Line | Data |
---|---|---|
02d1d628 AMH |
1 | #include "io.h" |
2 | #include <stdlib.h> | |
3 | #ifndef _MSC_VER | |
4 | #include <unistd.h> | |
5 | #endif | |
6 | ||
7 | ||
8 | /* FIXME: make allocation dynamic */ | |
9 | ||
10 | ||
11 | #ifdef IMAGER_DEBUG_MALLOC | |
12 | ||
2ff8ed30 | 13 | #define MAXMAL 102400 |
02d1d628 AMH |
14 | #define MAXDESC 65 |
15 | ||
a743c0a6 AMH |
16 | #define UNDRRNVAL 10 |
17 | #define OVERRNVAL 10 | |
02d1d628 AMH |
18 | |
19 | #define PADBYTE 0xaa | |
20 | ||
21 | ||
22 | static int malloc_need_init = 1; | |
23 | ||
24 | typedef struct { | |
fe6163bf | 25 | void* ptr; |
02d1d628 | 26 | size_t size; |
fe6163bf | 27 | char comm[MAXDESC]; |
02d1d628 AMH |
28 | } malloc_entry; |
29 | ||
30 | malloc_entry malloc_pointers[MAXMAL]; | |
31 | ||
fe6163bf AMH |
32 | |
33 | ||
34 | ||
35 | /* Utility functions */ | |
36 | ||
37 | ||
38 | static | |
39 | void | |
aea697ad | 40 | malloc_init(void) { |
fe6163bf AMH |
41 | int i; |
42 | for(i=0; i<MAXMAL; i++) malloc_pointers[i].ptr = NULL; | |
43 | malloc_need_init = 0; | |
44 | atexit(malloc_state); | |
45 | } | |
46 | ||
47 | ||
48 | static | |
49 | int | |
50 | find_ptr(void *p) { | |
51 | int i; | |
52 | for(i=0;i<MAXMAL;i++) | |
53 | if (malloc_pointers[i].ptr == p) | |
54 | return i; | |
55 | return -1; | |
56 | } | |
57 | ||
58 | ||
59 | /* Takes a pointer to real start of array, | |
60 | * sets the entries in the table, returns | |
61 | * the offset corrected pointer */ | |
62 | ||
63 | static | |
64 | void * | |
65 | set_entry(int i, char *buf, size_t size, char *file, int line) { | |
66 | memset( buf, PADBYTE, UNDRRNVAL ); | |
67 | memset( &buf[UNDRRNVAL+size], PADBYTE, OVERRNVAL ); | |
68 | buf += UNDRRNVAL; | |
69 | malloc_pointers[i].ptr = buf; | |
70 | malloc_pointers[i].size = size; | |
71 | sprintf(malloc_pointers[i].comm,"%s (%d)", file, line); | |
72 | return buf; | |
73 | } | |
74 | ||
75 | ||
02d1d628 AMH |
76 | |
77 | ||
78 | void | |
aea697ad | 79 | malloc_state(void) { |
fe6163bf AMH |
80 | int i, total = 0; |
81 | ||
02d1d628 AMH |
82 | mm_log((0,"malloc_state()\n")); |
83 | bndcheck_all(); | |
fe6163bf AMH |
84 | for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr != NULL) { |
85 | mm_log((0,"%d: %d (0x%x) : %s\n", i, malloc_pointers[i].size, malloc_pointers[i].ptr, malloc_pointers[i].comm)); | |
86 | total += malloc_pointers[i].size; | |
02d1d628 | 87 | } |
fe6163bf AMH |
88 | if (total == 0) mm_log((0,"No memory currently used!\n")) |
89 | else mm_log((0,"total: %d\n",total)); | |
02d1d628 AMH |
90 | } |
91 | ||
92 | ||
fe6163bf | 93 | |
02d1d628 | 94 | void* |
fe6163bf | 95 | mymalloc_file_line(size_t size, char* file, int line) { |
02d1d628 AMH |
96 | char *buf; |
97 | int i; | |
fe6163bf AMH |
98 | if (malloc_need_init) malloc_init(); |
99 | ||
100 | /* bndcheck_all(); Uncomment for LOTS OF THRASHING */ | |
101 | ||
102 | if ( (i = find_ptr(NULL)) < 0 ) { | |
103 | mm_log((0,"more than %d segments allocated at %s (%d)\n", MAXMAL, file, line)); | |
104 | exit(3); | |
02d1d628 AMH |
105 | } |
106 | ||
fe6163bf AMH |
107 | if ( (buf = malloc(size+UNDRRNVAL+OVERRNVAL)) == NULL ) { |
108 | mm_log((1,"Unable to allocate %i for %s (%i)\n", size, file, line)); | |
109 | exit(3); | |
02d1d628 AMH |
110 | } |
111 | ||
fe6163bf AMH |
112 | buf = set_entry(i, buf, size, file, line); |
113 | mm_log((1,"mymalloc_file_line: slot <%d> %d bytes allocated at %p for %s (%d)\n", i, size, buf, file, line)); | |
114 | return buf; | |
02d1d628 AMH |
115 | } |
116 | ||
117 | ||
118 | ||
119 | ||
02d1d628 | 120 | |
fe6163bf AMH |
121 | |
122 | ||
02d1d628 | 123 | void* |
fe6163bf AMH |
124 | myrealloc_file_line(void *ptr, size_t newsize, char* file, int line) { |
125 | char *buf; | |
02d1d628 | 126 | int i; |
fe6163bf AMH |
127 | |
128 | if (malloc_need_init) malloc_init(); | |
129 | /* bndcheck_all(); ACTIVATE FOR LOTS OF THRASHING */ | |
130 | ||
131 | if (!ptr) { | |
132 | mm_log((1, "realloc called with ptr = NULL, sending request to malloc\n")); | |
133 | return mymalloc_file_line(newsize, file, line); | |
02d1d628 AMH |
134 | } |
135 | ||
fe6163bf AMH |
136 | if (!newsize) { |
137 | mm_log((1, "newsize = 0, sending request to free\n")); | |
138 | myfree_file_line(ptr, file, line); | |
139 | return NULL; | |
140 | } | |
02d1d628 | 141 | |
fe6163bf AMH |
142 | if ( (i = find_ptr(ptr)) == -1) { |
143 | mm_log((0, "Unable to find %p in realloc for %s (%i)\n", ptr, file, line)); | |
144 | exit(3); | |
145 | } | |
146 | ||
aea697ad | 147 | if ( (buf = realloc(((char *)ptr)-UNDRRNVAL, UNDRRNVAL+OVERRNVAL+newsize)) == NULL ) { |
fe6163bf AMH |
148 | mm_log((1,"Unable to reallocate %i bytes at %p for %s (%i)\n", newsize, ptr, file, line)); |
149 | exit(3); | |
02d1d628 | 150 | } |
fe6163bf AMH |
151 | |
152 | buf = set_entry(i, buf, newsize, file, line); | |
153 | mm_log((1,"realloc_file_line: slot <%d> %d bytes allocated at %p for %s (%d)\n", i, newsize, buf, file, line)); | |
154 | return buf; | |
02d1d628 | 155 | } |
fe6163bf AMH |
156 | |
157 | ||
158 | ||
02d1d628 AMH |
159 | |
160 | static | |
161 | void | |
162 | bndcheck(int idx) { | |
163 | int i; | |
164 | size_t s = malloc_pointers[idx].size; | |
fe6163bf | 165 | unsigned char *pp = malloc_pointers[idx].ptr; |
02d1d628 AMH |
166 | if (!pp) { |
167 | mm_log((1, "bndcheck: No pointer in slot %d\n", idx)); | |
168 | return; | |
169 | } | |
170 | ||
171 | for(i=0;i<UNDRRNVAL;i++) | |
fe6163bf AMH |
172 | if (pp[-(1+i)] != PADBYTE) |
173 | mm_log((1,"bndcheck: UNDERRUN OF %d bytes detected: slot = %d, point = %p, size = %d\n", i+1, idx, pp, s )); | |
02d1d628 | 174 | |
fe6163bf | 175 | for(i=0;i<OVERRNVAL;i++) |
02d1d628 AMH |
176 | if (pp[s+i] != PADBYTE) |
177 | mm_log((1,"bndcheck: OVERRUN OF %d bytes detected: slot = %d, point = %p, size = %d\n", i+1, idx, pp, s )); | |
178 | } | |
179 | ||
180 | void | |
181 | bndcheck_all() { | |
182 | int idx; | |
183 | mm_log((1, "bndcheck_all()\n")); | |
76ff75b8 | 184 | for(idx=0; idx<MAXMAL; idx++) |
fe6163bf | 185 | if (malloc_pointers[idx].ptr) |
02d1d628 AMH |
186 | bndcheck(idx); |
187 | } | |
188 | ||
189 | ||
190 | ||
191 | ||
192 | ||
193 | void | |
194 | myfree_file_line(void *p, char *file, int line) { | |
195 | char *pp = p; | |
196 | int match = 0; | |
197 | int i; | |
198 | ||
fe6163bf | 199 | for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr == p) { |
02d1d628 AMH |
200 | mm_log((1,"myfree_file_line: pointer %i (%s) freed at %s (%i)\n", i, malloc_pointers[i].comm, file, line)); |
201 | bndcheck(i); | |
fe6163bf | 202 | malloc_pointers[i].ptr = NULL; |
02d1d628 AMH |
203 | match++; |
204 | } | |
205 | ||
206 | if (match != 1) { | |
f1ac5027 | 207 | mm_log((1, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line)); |
aea697ad | 208 | fprintf(stderr, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line); |
a73aeb5f | 209 | exit(255); |
02d1d628 AMH |
210 | } |
211 | ||
a73aeb5f | 212 | mm_log((1, "myfree_file_line: freeing address %p (real %p)\n", pp, pp-UNDRRNVAL)); |
02d1d628 AMH |
213 | |
214 | free(pp-UNDRRNVAL); | |
215 | } | |
216 | ||
217 | #else | |
218 | ||
219 | #define malloc_comm(a,b) (mymalloc(a)) | |
220 | ||
221 | void | |
222 | malloc_state() { | |
223 | printf("malloc_state: not in debug mode\n"); | |
224 | } | |
225 | ||
226 | void* | |
227 | mymalloc(int size) { | |
228 | void *buf; | |
229 | ||
a743c0a6 | 230 | if ( (buf = malloc(size)) == NULL ) { |
faa9b3e7 | 231 | mm_log((1, "mymalloc: unable to malloc %d\n", size)); |
cc6483e0 | 232 | fprintf(stderr,"Unable to malloc %d.\n", size); exit(3); |
02d1d628 | 233 | } |
f1ac5027 | 234 | mm_log((1, "mymalloc(size %d) -> %p\n", size, buf)); |
02d1d628 AMH |
235 | return buf; |
236 | } | |
237 | ||
238 | void | |
239 | myfree(void *p) { | |
dd55acc8 | 240 | mm_log((1, "myfree(p %p)\n", p)); |
02d1d628 AMH |
241 | free(p); |
242 | } | |
243 | ||
faa9b3e7 TC |
244 | void * |
245 | myrealloc(void *block, size_t size) { | |
246 | void *result; | |
247 | ||
248 | mm_log((1, "myrealloc(block %p, size %u)\n", block, size)); | |
249 | if ((result = realloc(block, size)) == NULL) { | |
250 | mm_log((1, "myrealloc: out of memory\n")); | |
251 | fprintf(stderr, "Out of memory.\n"); | |
252 | exit(3); | |
253 | } | |
254 | return result; | |
255 | } | |
256 | ||
02d1d628 AMH |
257 | #endif /* IMAGER_MALLOC_DEBUG */ |
258 | ||
259 | ||
260 | ||
261 | ||
262 | ||
263 | ||
5473b91d | 264 | /* Should these really be here? */ |
02d1d628 AMH |
265 | |
266 | #undef min | |
267 | #undef max | |
268 | ||
269 | int | |
270 | min(int a,int b) { | |
271 | if (a<b) return a; else return b; | |
272 | } | |
273 | ||
274 | int | |
275 | max(int a,int b) { | |
276 | if (a>b) return a; else return b; | |
277 | } | |
278 |