1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | #include <stdlib.h>
|
---|
10 | #include <string.h>
|
---|
11 | #include <stdio.h>
|
---|
12 | #include "arch.hh"
|
---|
13 |
|
---|
14 | #include "memory/malloc.hh"
|
---|
15 | #include "error/error.hh"
|
---|
16 | #include "threads/threads.hh"
|
---|
17 | #include "time/profile.hh"
|
---|
18 | #include "init/init.hh"
|
---|
19 | #include "file/file.hh"
|
---|
20 | #include "file/static_file.hh"
|
---|
21 | #include "string/string.hh"
|
---|
22 |
|
---|
23 | // define this to override the native memcpy to check for overwriting memory leaks
|
---|
24 | //#define i4_MEMCPY_CHECK
|
---|
25 | #define i4_FREE_CHECK
|
---|
26 |
|
---|
27 | #ifdef i4_NEW_CHECK
|
---|
28 | #undef new
|
---|
29 | #endif
|
---|
30 |
|
---|
31 | #undef i4_malloc
|
---|
32 | #undef i4_realloc
|
---|
33 |
|
---|
34 | static i4_critical_section_class mem_lock;
|
---|
35 |
|
---|
36 |
|
---|
37 | #ifndef __MAC__
|
---|
38 |
|
---|
39 | static i4_profile_class pf_malloc("i4_malloc");
|
---|
40 | static i4_profile_class pf_free("i4_free");
|
---|
41 |
|
---|
42 |
|
---|
43 | // declare the new()s before we include malloc.hh so that the new
|
---|
44 | // macro doesn't mess up their definition
|
---|
45 | int i4_m_instance=0;
|
---|
46 | int i4_mem_break=-1;
|
---|
47 |
|
---|
48 | #if (__linux && i4_NEW_CHECK)
|
---|
49 |
|
---|
50 | void *operator new( size_t size, char *file, w32 line)
|
---|
51 | {
|
---|
52 | return i4_malloc(size, file, line);
|
---|
53 | }
|
---|
54 |
|
---|
55 |
|
---|
56 | void *operator new [](size_t size, char *file, w32 line)
|
---|
57 | {
|
---|
58 | return i4_malloc(size, file, line);
|
---|
59 | }
|
---|
60 | #endif
|
---|
61 |
|
---|
62 | #include <new.h>
|
---|
63 |
|
---|
64 | #undef new
|
---|
65 |
|
---|
66 |
|
---|
67 | void *operator new( size_t size)
|
---|
68 | {
|
---|
69 | return i4_malloc(size,"unknown",0);
|
---|
70 | }
|
---|
71 |
|
---|
72 | void operator delete(void *ptr)
|
---|
73 | {
|
---|
74 | i4_free(ptr);
|
---|
75 | }
|
---|
76 |
|
---|
77 |
|
---|
78 | #endif
|
---|
79 |
|
---|
80 | #ifdef i4_MEM_CHECK
|
---|
81 | #define i4_MEM_CLEAR
|
---|
82 | #endif
|
---|
83 |
|
---|
84 |
|
---|
85 | #include "memory/bmanage.hh"
|
---|
86 |
|
---|
87 | extern void free_up_memory();
|
---|
88 |
|
---|
89 | #ifdef i4_MEM_CHECK
|
---|
90 | // can be set in debugger, break mem fun will be called when this address is allocated
|
---|
91 | long break_mem_point=0;
|
---|
92 | void break_mem_fun()
|
---|
93 | {
|
---|
94 | printf("memory breakpoint\n");
|
---|
95 | }
|
---|
96 |
|
---|
97 | #ifdef i4_MEMCPY_CHECK
|
---|
98 | // can set this memory range to check for mem copies over memory
|
---|
99 | w32 i4_check_min=0, i4_check_max=0;
|
---|
100 |
|
---|
101 | extern "C" void *memcpy(void* dest, const void *src,size_t n)
|
---|
102 | {
|
---|
103 | if (((w32)dest)<i4_check_max && ((w32)dest)+n>i4_check_min)
|
---|
104 | break_mem_fun();
|
---|
105 |
|
---|
106 | bcopy(src,dest,n);
|
---|
107 | }
|
---|
108 | #endif
|
---|
109 |
|
---|
110 | #endif
|
---|
111 |
|
---|
112 |
|
---|
113 | i4_block_manager_class bmanage[5];
|
---|
114 | int bmanage_total=0;
|
---|
115 |
|
---|
116 |
|
---|
117 | void inspect_memory()
|
---|
118 | {
|
---|
119 | mem_lock.lock();
|
---|
120 | for (int i=0;i<bmanage_total;i++)
|
---|
121 | bmanage[i].inspect();
|
---|
122 | mem_lock.unlock();
|
---|
123 | }
|
---|
124 |
|
---|
125 |
|
---|
126 | void small_allocation_summary(int &total, int *&list)
|
---|
127 | {
|
---|
128 | int size=1;
|
---|
129 | total=JM_SMALL_SIZE/4;
|
---|
130 | list=(int *)i4_malloc(total*sizeof(int), __FILE__, __LINE__);
|
---|
131 |
|
---|
132 | for (;size<total;size++)
|
---|
133 | {
|
---|
134 | list[size]=0;
|
---|
135 | int i,x;
|
---|
136 | for (i=0;i<bmanage_total;i++)
|
---|
137 | {
|
---|
138 | small_block *s=bmanage[i].sblocks[size];
|
---|
139 | while (s)
|
---|
140 | {
|
---|
141 | for (x=0;x<32;x++)
|
---|
142 | if (s->alloc_list&(1<<x))
|
---|
143 | list[size]++;
|
---|
144 |
|
---|
145 | s=s->next;
|
---|
146 | }
|
---|
147 | }
|
---|
148 | }
|
---|
149 | }
|
---|
150 |
|
---|
151 |
|
---|
152 | void i4_malloc_uninit()
|
---|
153 | {
|
---|
154 | #ifdef i4_MEM_CHECK
|
---|
155 | i4_mem_report("end.mem");
|
---|
156 | #endif
|
---|
157 |
|
---|
158 | mem_lock.lock();
|
---|
159 |
|
---|
160 | for (int i=0;i<bmanage_total;i++)
|
---|
161 | {
|
---|
162 | free(bmanage[i].addr);
|
---|
163 | }
|
---|
164 | bmanage_total=0;
|
---|
165 | mem_lock.unlock();
|
---|
166 | }
|
---|
167 |
|
---|
168 |
|
---|
169 | void i4_mem_cleanup(int ret, void *arg)
|
---|
170 | {
|
---|
171 | i4_malloc_uninit();
|
---|
172 | }
|
---|
173 |
|
---|
174 |
|
---|
175 | int i4_malloc_max_size=20000000;
|
---|
176 | int i4_malloc_min_size=0x1000;
|
---|
177 |
|
---|
178 | char *not_enough_total_memory_message=
|
---|
179 | "Memory manager : Sorry you do not have enough memory available to\n"
|
---|
180 | " run this program.\n";
|
---|
181 |
|
---|
182 |
|
---|
183 | void i4_set_min_memory_required(int bytes)
|
---|
184 | {
|
---|
185 | i4_malloc_min_size=bytes;
|
---|
186 | }
|
---|
187 |
|
---|
188 | void i4_set_max_memory_used(int bytes)
|
---|
189 | {
|
---|
190 | i4_malloc_max_size=bytes;
|
---|
191 | if (i4_malloc_min_size< i4_malloc_max_size)
|
---|
192 | i4_malloc_min_size=i4_malloc_max_size;
|
---|
193 | }
|
---|
194 |
|
---|
195 |
|
---|
196 | void i4_malloc_init()
|
---|
197 | {
|
---|
198 | if (bmanage_total)
|
---|
199 | i4_warning("warning : jmalloc_init called twice\n");
|
---|
200 | else
|
---|
201 | {
|
---|
202 | void *mem;
|
---|
203 |
|
---|
204 | sw32 size=i4_malloc_max_size;
|
---|
205 | for (mem=NULL;!mem && size>=i4_malloc_min_size;)
|
---|
206 | {
|
---|
207 | mem=malloc(size);
|
---|
208 | if (!mem) size-=0x100;
|
---|
209 | }
|
---|
210 |
|
---|
211 | if (mem)
|
---|
212 | {
|
---|
213 | bmanage[bmanage_total].init(mem,size);
|
---|
214 | bmanage_total++;
|
---|
215 | size-=0x1000;
|
---|
216 | }
|
---|
217 | else
|
---|
218 | i4_error(not_enough_total_memory_message);
|
---|
219 | }
|
---|
220 | }
|
---|
221 |
|
---|
222 |
|
---|
223 |
|
---|
224 | class i4_memory_init_class : public i4_init_class
|
---|
225 | {
|
---|
226 | public:
|
---|
227 | int init_type() { return I4_INIT_TYPE_MEMORY_MANAGER; }
|
---|
228 |
|
---|
229 | void init() { i4_malloc_init(); }
|
---|
230 |
|
---|
231 | void uninit() { i4_malloc_uninit(); }
|
---|
232 |
|
---|
233 | } i4_memory_init_instance;
|
---|
234 |
|
---|
235 |
|
---|
236 | long i4_available()
|
---|
237 | {
|
---|
238 | mem_lock.lock();
|
---|
239 | long size=0;
|
---|
240 | for (int i=0;i<bmanage_total;i++)
|
---|
241 | size+=bmanage[i].available();
|
---|
242 | mem_lock.unlock();
|
---|
243 | return size;
|
---|
244 | }
|
---|
245 |
|
---|
246 | long i4_largest_free_block()
|
---|
247 | {
|
---|
248 | mem_lock.lock();
|
---|
249 | long l=0;
|
---|
250 | for (int i=0;i<bmanage_total;i++)
|
---|
251 | {
|
---|
252 | long t=bmanage[i].largest_free_block();
|
---|
253 | if (t>l)
|
---|
254 | l=t;
|
---|
255 | }
|
---|
256 | mem_lock.unlock();
|
---|
257 | return l;
|
---|
258 | }
|
---|
259 |
|
---|
260 | long i4_allocated()
|
---|
261 | {
|
---|
262 | mem_lock.lock();
|
---|
263 |
|
---|
264 | long size=0;
|
---|
265 | for (int i=0;i<bmanage_total;i++)
|
---|
266 | size+=bmanage[i].allocated();
|
---|
267 |
|
---|
268 | mem_lock.unlock();
|
---|
269 | return size;
|
---|
270 | }
|
---|
271 |
|
---|
272 |
|
---|
273 | void *i4_malloc(w32 size, char *file, int line)
|
---|
274 | {
|
---|
275 | pf_malloc.start();
|
---|
276 |
|
---|
277 | if (size==0)
|
---|
278 | i4_warning("tried to malloc 0 bytes");
|
---|
279 |
|
---|
280 | i4_m_instance++;
|
---|
281 | if (i4_m_instance == i4_mem_break)
|
---|
282 | i4_warning("i4 mem break");
|
---|
283 |
|
---|
284 | #ifdef i4_MEM_CHECK
|
---|
285 | char reason[200];
|
---|
286 |
|
---|
287 | sprintf(reason, "%s:%d (inst=%d)", file, line, i4_m_instance);
|
---|
288 | #else
|
---|
289 | char *reason="unknown";
|
---|
290 | #endif
|
---|
291 |
|
---|
292 | // printf("Instance %d: %s\n", i4_m_instance, reason);
|
---|
293 |
|
---|
294 | // I4_TEST(i4_is_initialized(), "i4_malloc called before i4_init");
|
---|
295 |
|
---|
296 | if (!bmanage_total)
|
---|
297 | {
|
---|
298 | void *ret=malloc(size);
|
---|
299 | return ret;
|
---|
300 | }
|
---|
301 |
|
---|
302 | size=(size+3)&(0xffffffff-3);
|
---|
303 | mem_lock.lock();
|
---|
304 |
|
---|
305 | do
|
---|
306 | {
|
---|
307 | for (int i=0;i<bmanage_total;i++)
|
---|
308 | {
|
---|
309 | void *a=bmanage[i].alloc(size, reason);
|
---|
310 | if (a)
|
---|
311 | {
|
---|
312 | mem_lock.unlock();
|
---|
313 | pf_malloc.stop();
|
---|
314 | return a;
|
---|
315 | }
|
---|
316 | }
|
---|
317 |
|
---|
318 | #if 1//def i4_MEM_CHECK
|
---|
319 | mem_lock.unlock();
|
---|
320 | i4_mem_report("no_mem");
|
---|
321 | #endif
|
---|
322 |
|
---|
323 | mem_lock.unlock();
|
---|
324 | i4_error("Out of memory!");
|
---|
325 | // free_up_memory();
|
---|
326 | } while (1);
|
---|
327 | }
|
---|
328 |
|
---|
329 |
|
---|
330 | void i4_free(void *ptr)
|
---|
331 | {
|
---|
332 | pf_free.start();
|
---|
333 |
|
---|
334 | I4_TEST(i4_is_initialized(), "i4_free called after i4_uninit()");
|
---|
335 |
|
---|
336 | if (!bmanage_total)
|
---|
337 | {
|
---|
338 | free(ptr);
|
---|
339 | pf_free.stop();
|
---|
340 | return ;
|
---|
341 | }
|
---|
342 |
|
---|
343 | #ifdef i4_FREE_CHECK
|
---|
344 | I4_ASSERT(valid_ptr(ptr), "invalid free!");
|
---|
345 | #endif
|
---|
346 |
|
---|
347 | mem_lock.lock();
|
---|
348 | for (int i=0;i<bmanage_total;i++)
|
---|
349 | if (ptr>=(void *)bmanage[i].sfirst) // is the pointer in this block?
|
---|
350 | {
|
---|
351 | if (ptr<=(void *)bmanage[i].slast) // is it in static space?
|
---|
352 | {
|
---|
353 | bmanage[i].free(ptr);
|
---|
354 | mem_lock.unlock();
|
---|
355 | pf_free.stop();
|
---|
356 | return ;
|
---|
357 | }
|
---|
358 | }
|
---|
359 |
|
---|
360 | mem_lock.unlock();
|
---|
361 |
|
---|
362 | i4_error("i4_free : bad pointer\n");
|
---|
363 | pf_free.stop();
|
---|
364 | }
|
---|
365 |
|
---|
366 |
|
---|
367 | void *i4_realloc(void *ptr, w32 size, char *file, int line)
|
---|
368 | {
|
---|
369 | if (!ptr)
|
---|
370 | {
|
---|
371 | // malloc is already lock protected
|
---|
372 | return i4_malloc(size, file, line);
|
---|
373 | }
|
---|
374 |
|
---|
375 |
|
---|
376 | if (!bmanage_total)
|
---|
377 | {
|
---|
378 | // thread protect the c library realloc
|
---|
379 | mem_lock.lock();
|
---|
380 | void *ret=realloc(ptr,size);
|
---|
381 | mem_lock.unlock();
|
---|
382 | return ret;
|
---|
383 | }
|
---|
384 |
|
---|
385 | if (size==0)
|
---|
386 | {
|
---|
387 | // free is already lock protected
|
---|
388 | i4_free(ptr);
|
---|
389 | return NULL;
|
---|
390 | }
|
---|
391 |
|
---|
392 | sw32 old_size=0;
|
---|
393 | for (int i=0;i<bmanage_total;i++)
|
---|
394 | if (ptr>=(void *)bmanage[i].sfirst &&
|
---|
395 | ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))
|
---|
396 | {
|
---|
397 | old_size=bmanage[i].pointer_size(ptr);
|
---|
398 | if (ptr<=(void *)bmanage[i].slast)
|
---|
399 | {
|
---|
400 | void *nptr=i4_malloc(size, file, line);
|
---|
401 | if ((sw32)size>old_size)
|
---|
402 | memcpy(nptr,ptr,old_size);
|
---|
403 | else memcpy(nptr,ptr,size);
|
---|
404 |
|
---|
405 | bmanage[i].free(ptr);
|
---|
406 |
|
---|
407 |
|
---|
408 | return nptr;
|
---|
409 | }
|
---|
410 | }
|
---|
411 |
|
---|
412 | i4_error("jrealloc : bad pointer\n");
|
---|
413 | return NULL;
|
---|
414 | }
|
---|
415 |
|
---|
416 |
|
---|
417 | void dmem_report()
|
---|
418 | {
|
---|
419 | i4_mem_report("debug.mem");
|
---|
420 | }
|
---|
421 |
|
---|
422 | static i4_static_file_class mem_report;
|
---|
423 |
|
---|
424 | void i4_mem_report(char *filename)
|
---|
425 | {
|
---|
426 | i4_file_class *fp=mem_report.open(filename);
|
---|
427 |
|
---|
428 | if (fp)
|
---|
429 | {
|
---|
430 | for (int i=0;i<bmanage_total;i++)
|
---|
431 | bmanage[i].report(fp);
|
---|
432 |
|
---|
433 | fp->printf("Total available=%d, allocated=%d\n", i4_available(), i4_allocated());
|
---|
434 | }
|
---|
435 | }
|
---|
436 |
|
---|
437 |
|
---|
438 | long small_ptr_size(void *ptr)
|
---|
439 | {
|
---|
440 | return ((small_block *)(((long *)ptr)[-1]))->size;
|
---|
441 | }
|
---|
442 |
|
---|
443 |
|
---|
444 | int valid_ptr(void *ptr)
|
---|
445 | {
|
---|
446 | if (!bmanage_total) { return 0; }
|
---|
447 | for (int i=0;i<bmanage_total;i++)
|
---|
448 | if (ptr>=(void *)bmanage[i].sfirst) // is the pointer in this block?
|
---|
449 | {
|
---|
450 | if (ptr<=(void *)bmanage[i].slast)
|
---|
451 | {
|
---|
452 | int ret=bmanage[i].valid_ptr(ptr);
|
---|
453 | return ret;
|
---|
454 | }
|
---|
455 | }
|
---|
456 |
|
---|
457 | return 0;
|
---|
458 | }
|
---|
459 |
|
---|
460 |
|
---|
461 |
|
---|
462 |
|
---|
463 | int valid_memory(void *ptr)
|
---|
464 | {
|
---|
465 | for (int i=0; i<bmanage_total; i++)
|
---|
466 | if (ptr>=(void *)bmanage[i].sfirst) // is the pointer in this block?
|
---|
467 | if (ptr<=(void *)bmanage[i].slast)
|
---|
468 | return 1;
|
---|
469 |
|
---|
470 | return 0;
|
---|
471 | }
|
---|