source: golgotha/src/i4/memory/malloc.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 8.9 KB
Line 
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
34static i4_critical_section_class mem_lock;
35
36
37#ifndef __MAC__
38
39static i4_profile_class pf_malloc("i4_malloc");
40static 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
45int i4_m_instance=0;
46int i4_mem_break=-1;
47
48#if (__linux && i4_NEW_CHECK)
49
50void *operator new( size_t size, char *file, w32 line)
51
52  return i4_malloc(size, file, line);
53}
54
55
56void *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
67void *operator new( size_t size)
68
69  return i4_malloc(size,"unknown",0);
70}
71
72void 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
87extern 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
91long break_mem_point=0;     
92void 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
99w32 i4_check_min=0, i4_check_max=0;
100
101extern "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
113i4_block_manager_class bmanage[5];
114int bmanage_total=0;
115
116
117void 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
126void 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
152void 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
169void i4_mem_cleanup(int ret, void *arg)
170{
171  i4_malloc_uninit();
172}
173
174 
175int i4_malloc_max_size=20000000;
176int i4_malloc_min_size=0x1000;
177
178char *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
183void i4_set_min_memory_required(int bytes)
184{
185  i4_malloc_min_size=bytes;
186}
187
188void 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
196void 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
224class i4_memory_init_class : public i4_init_class
225{
226public:
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
236long 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
246long 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
260long 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
273void *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
330void 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
367void *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
417void dmem_report()
418{
419  i4_mem_report("debug.mem");
420}
421
422static i4_static_file_class mem_report;
423
424void 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
438long small_ptr_size(void *ptr)
439{
440  return ((small_block *)(((long *)ptr)[-1]))->size;
441}
442
443
444int 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
463int 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}
Note: See TracBrowser for help on using the repository browser.