source: abuse/trunk/src/imlib/jmalloc.cpp @ 15

Last change on this file since 15 was 8, checked in by Sam Hocevar, 17 years ago
  • fixed buffer overflows.
File size: 22.3 KB
Line 
1#include <stdlib.h>
2#include <string.h>
3#include <stdio.h>
4#include <stdint.h>
5
6#include <specs.hpp>
7//#include <new.h>
8
9#define MEM_CHECK
10//#ifdef MEM_CHECK
11//#define MEM_CLEAR
12//#endif
13
14#include "jmalloc.hpp"
15#define uchar unsigned char
16#define JM_SMALL_SIZE 128      // above 128 bytes is considered to be a big block and no hashing is done
17int alloc_space=ALLOC_SPACE_STATIC;
18
19extern void free_up_memory();
20
21#ifdef MEM_CHECK
22intptr_t break_mem_point=0;       // can be set in debugger, break mem fun will be called when this address is allocated
23void break_mem_fun()
24{
25  printf("memory breakpoint\n");
26}
27#endif
28
29struct memory_node
30{
31  long size;
32#ifdef MEM_CHECK
33  char *name;                     // name is allocated on regular heap
34#endif                            // because it is used for debugging purposes
35                                  // and will probably be run on my linux box with VMM
36  memory_node *next;
37};
38
39
40struct small_block
41
42  unsigned long size;             // size of blocks...
43  uint32_t alloc_list;            // bit field saying weither each block is allocated or not.
44  small_block *next;              // next small block of same size
45#ifdef MEM_CHECK
46  char *name[32];
47#endif
48} ;
49
50enum { HI_BLOCK, LOW_BLOCK };
51
52class block_manager
53{
54  public :
55
56  long block_size;                             // size of this memory_block
57  small_block *sblocks[JM_SMALL_SIZE];
58  small_block *cblocks[JM_SMALL_SIZE];
59  void *addr;
60
61  memory_node *sfirst,*slast,
62              *cfirst;
63  unsigned char block_type;
64
65  void init(void *block, long Block_size, uchar type);
66  void *static_alloc(long size, char *name);
67  void *cache_alloc(long size, char *name);
68  void static_free(void *ptr);
69  void cache_free(void *ptr);
70  long available();
71  long allocated();
72  long pointer_size(void *ptr);
73  void report(FILE *fp);
74  void inspect();
75
76  int valid_static_ptr(void *ptr);     // only called from within debugger
77  int valid_cache_ptr(void *ptr);
78} bmanage[5];
79
80int bmanage_total=0;
81
82
83void inspect_memory()
84{
85  for (int i=0;i<bmanage_total;i++)
86    bmanage[i].inspect();
87}
88
89
90int block_manager::valid_static_ptr(void *ptr)
91{
92  void *next=(void *)(*(((long *)ptr)-1));
93  if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
94  {
95    small_block *s=(small_block *)next;
96    if (s->size<=0) return 0;
97
98    small_block *c=sblocks[s->size];
99    while (c && c!=s) c=c->next;
100    if (!c) return 0;
101  }
102
103  memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node));
104  memory_node *f=sfirst;
105  while (f && f!=o) f=f->next;
106  if (f) return 1;
107  else return 0;
108}
109
110
111int block_manager::valid_cache_ptr(void *ptr)
112{
113  void *next=(void *)(*(((long *)ptr)-1));
114  if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
115  {
116    small_block *s=(small_block *)next;
117    if (s->size<=0) return 0;
118
119    small_block *c=cblocks[s->size];
120    while (c && c!=s) c=c->next;
121    if (!c) return 0;
122  }
123
124  memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node));
125  memory_node *f=cfirst;
126  while (f && f!=o) f=f->next;
127  if (f) return 1;
128  else return 0;
129}
130
131void small_static_allocation_summary(int &total, int *&static_list, int *&cache_list)
132{
133  int size=1;
134  total=JM_SMALL_SIZE/4;
135  static_list=(int *)jmalloc(total*sizeof(int),"small static report");
136  cache_list=(int *)jmalloc(total*sizeof(int),"small cache report");
137 
138  for (;size<total;size++)
139  {
140    static_list[size]=0;
141    cache_list[size]=0;
142    int i,x;
143    for (i=0;i<bmanage_total;i++)
144    {
145      small_block *s=bmanage[i].sblocks[size];
146      while (s)
147      {
148        for (x=0;x<32;x++)
149          if (s->alloc_list&(1<<x))
150            static_list[size]++;
151
152        s=s->next;
153      }
154
155      s=bmanage[i].cblocks[size];
156      while (s)
157      {
158        for (x=0;x<32;x++)
159          if (s->alloc_list&(1<<x))
160            cache_list[size]++;
161
162        s=s->next;
163      }
164    }
165  }
166}
167
168void block_manager::inspect()
169{
170  memory_node *f=sfirst;
171  for (;f;f=f->next);               // scan through static big list
172
173  int i,bit=1;
174  for (i=0;i<JM_SMALL_SIZE;i++)
175  {
176    for (small_block *s=sblocks[i];s;s=s->next)
177    {
178      char *addr=((char *)(s+1));
179      for (int j=0;j<32;j++)
180      {
181        if (s->alloc_list&bit)
182        {
183          void *next=(void *)(*(((intptr_t *)addr)));
184          if ((intptr_t)next!=(intptr_t)s)
185          {
186            fprintf(stderr,"inspect : bad pointer\n");
187            return ;       
188          }
189        }
190        bit=bit<<1;
191        addr+=s->size+4;
192      }
193    }
194  }
195
196}
197
198void block_manager::report(FILE *fp)
199{
200  fprintf(fp,"************** Block size = %d ***************\n",block_size);
201  fprintf(fp,"************** STATIC SPACE ******************\n");
202  int i=0;
203  memory_node *f=sfirst;
204  for (;f;f=f->next,i++)
205  {   
206    fprintf(fp,"%4d   %p (%d) %4d      ",i,f,((char *)f-(char *)sfirst),f->size);
207#ifdef MEM_CHECK
208    if (f->size>0)
209      fprintf(fp,"%s",f->name);
210    else fprintf(fp,"FREE");
211#endif
212    fprintf(fp,"\n");
213  }   
214  for (i=0;i<JM_SMALL_SIZE;i++)
215  {
216    for (small_block *s=sblocks[i];s;s=s->next)
217    {     
218      fprintf(fp,"*** Small Block size = %d ***\n",i);     
219      uint32_t bit=1;
220      char *addr=((char *)(s+1));
221      for (int j=0;j<32;j++)
222      {
223        fprintf(fp,"%p   ",addr);
224        if (s->alloc_list&bit)
225        {
226#ifdef MEM_CHECK
227          fprintf(fp,"%s\n",s->name[j]);
228#else
229          fprintf(fp,"allocated\n");
230#endif   
231        } else fprintf(fp,"FREE\n");
232        bit=bit<<1;
233        addr+=s->size+4;
234      }
235    }
236  }
237
238
239  fprintf(fp,"************** CACHE SPACE ******************\n",block_size);
240  i=0;
241  for (f=cfirst;f;f=f->next,i++)
242  {   
243    fprintf(fp,"%4d   %p %4d      ",i,f,f->size);
244#ifdef MEM_CHECK
245    if (f->size>0)
246      fprintf(fp,"%s",f->name);
247    else fprintf(fp,"FREE");
248#endif
249    fprintf(fp,"\n");
250  }   
251  for (i=0;i<JM_SMALL_SIZE;i++)
252  {
253    for (small_block *s=cblocks[i];s;s=s->next)
254    {     
255      fprintf(fp,"*** Small Block size = %d ***\n",i);     
256      uint32_t bit=1;
257      char *addr=((char *)(s+1));
258      for (int j=0;j<32;j++)
259      {
260        fprintf(fp,"%p   ",addr);
261        if (s->alloc_list&bit)
262        {
263#ifdef MEM_CHECK
264          fprintf(fp,"%s\n",s->name[j]);
265#else
266          fprintf(fp,"allocated\n");
267#endif   
268        } else fprintf(fp,"FREE\n");
269        bit=bit<<1;
270        addr+=s->size+4;
271      }
272    }
273  }
274}
275
276long block_manager::pointer_size(void *ptr)
277{
278  void *next=(void *)(*(((intptr_t *)ptr)-1));
279  if (next>ptr)
280    return ((memory_node *)(((char *)ptr)-sizeof(memory_node)))->size;
281  else return ((small_block *)next)->size;
282}
283
284long block_manager::available()
285{
286  long size=0;
287  memory_node *f;
288  for (f=sfirst;f;f=f->next)
289    if (f->size<0) size-=f->size;
290
291  for (f=cfirst;f;f=f->next)
292    if (f->size<0) size-=f->size;
293  return size;
294}
295
296long block_manager::allocated()
297{
298  long size=0;
299  memory_node *f;
300  for (f=sfirst;f;f=f->next)
301    if (f->size>0) size+=f->size;
302
303  for (f=cfirst;f;f=f->next)
304    if (f->size>0) size+=f->size;
305  return size;
306}
307
308void block_manager::init(void *block, long Block_size, uchar type)
309{
310  block_size=Block_size;
311  addr=block;
312  /*
313     I'm padding each block, because I'm comparing pointers against size
314     in jfree to determine weither a pointer is too a small object or a large alloc
315     and it must always be true that the address of the pointer is > JM_SMALL_SIZE
316     All systems I know start pointer address pretty high, but this is a porting consern.     
317  */
318 
319  slast=sfirst=(memory_node *)(((char *)block)+JM_SMALL_SIZE);   
320  sfirst->size=-(block_size-sizeof(memory_node)-JM_SMALL_SIZE);
321  sfirst->next=NULL;
322  cfirst=NULL;
323  memset(sblocks,0,sizeof(sblocks));
324  memset(cblocks,0,sizeof(cblocks));
325  block_type=type;
326}
327
328void *block_manager::static_alloc(long size, char *name)
329{
330  if (size<JM_SMALL_SIZE)
331  {
332    small_block *s=sblocks[size];
333    for (;s && s->alloc_list==0xffffffff;s=s->next);
334    if (!s)
335    {
336      s=(small_block *)static_alloc((size+4)*32+sizeof(small_block),"small_block");
337      if (!s) return NULL;   // not enough room for another small block
338      s->alloc_list=1;
339      s->next=sblocks[size];
340      sblocks[size]=s;
341      s->size=size;
342#ifdef MEM_CHECK
343      s->name[0]=strcpy((char *)malloc(strlen(name)+1),name);
344      if ((intptr_t)s==break_mem_point)
345        break_mem_fun();
346#endif     
347      long *addr=(long *)(((char *)s)+sizeof(small_block));
348      *addr=(long)s;
349      return (void *)(addr+1);  // return first block
350    } else
351    {
352      int bit=1,i=0;
353      char *addr=((char *)s)+sizeof(small_block);
354      while (1)        // we already know there is a bit free
355      {
356        if ((s->alloc_list&bit)==0)
357        {
358          s->alloc_list|=bit;
359#ifdef MEM_CHECK
360          s->name[i]=strcpy((char *)malloc(strlen(name)+1),name);
361#endif           
362          *((long *)addr)=(long)s;
363
364#ifdef MEM_CHECK
365          if ((intptr_t)addr==break_mem_point)
366            break_mem_fun();
367#endif
368
369          return (void *)(addr+4);
370        }
371        i++;
372        bit=bit<<1;
373        addr+=size+4;
374      }     
375    }               
376  }
377
378
379  memory_node *s=sfirst;
380  for (;s && -s->size<size;s=s->next);
381  if (!s) return NULL;
382  s->size=-s->size;
383
384  if (s->size-size>(int)sizeof(memory_node)+4)  // is there enough space to split the block?
385  {   
386    memory_node *p=(memory_node *)((char *)s+sizeof(memory_node)+size);
387    if (s==slast)
388      slast=p;
389    p->size=-(s->size-size-sizeof(memory_node));
390#ifdef MEM_CLEAR
391//    memset( ((memory_node *)p)+1,0,-p->size);
392#endif
393    p->next=s->next;
394    s->next=p;
395    s->size=size;
396  }
397#ifdef MEM_CHECK
398  s->name=strcpy((char *)malloc(strlen(name)+1),name);
399
400  if ((intptr_t)s==break_mem_point)
401    break_mem_fun();
402
403#endif
404  return (void *)(((char *)s)+sizeof(memory_node));
405}
406
407
408void *block_manager::cache_alloc(long size, char *name)
409{
410  if (size<JM_SMALL_SIZE)
411  {
412    small_block *s=cblocks[size];
413    for (;s && s->alloc_list==0xffffffff;s=s->next);
414    if (!s)
415    {
416      s=(small_block *)cache_alloc((size+4)*32+sizeof(small_block),"small_block");
417      if (!s) return NULL;   // not enough room for another small block
418      s->alloc_list=1;
419      s->next=cblocks[size];
420      cblocks[size]=s;
421      s->size=size;
422#ifdef MEM_CHECK
423      s->name[0]=strcpy((char *)malloc(strlen(name)+1),name);
424
425#endif     
426      long *addr=(long *)(((char *)s)+sizeof(small_block));
427      *addr=(long)s;
428#ifdef MEM_CHECK
429      if ((intptr_t)s==break_mem_point)
430        break_mem_fun();
431#endif
432      return (void *)(addr+1);  // return first block
433    } else
434    {
435      int bit=1,i=0;
436      char *addr=((char *)s)+sizeof(small_block);
437      while (1)        // we already know there is a bit free
438      {
439        if ((s->alloc_list&bit)==0)
440        {
441          s->alloc_list|=bit;
442#ifdef MEM_CHECK
443          s->name[i]=strcpy((char *)malloc(strlen(name)+1),name);
444          if ((intptr_t)s==break_mem_point)
445            break_mem_fun();
446#endif           
447          *((long *)addr)=(long)s;
448          return (void *)(addr+4);
449        }
450        i++;
451        bit=bit<<1;
452        addr+=size+4;
453      }     
454    }               
455  }
456
457
458  memory_node *clast=NULL;
459  memory_node *s=cfirst;
460  for (;s && -s->size<size;s=s->next) clast=s;
461  if (!s) // no current cache space for object, see if we can enlarge the cache space
462  {
463    long size_avail=-slast->size;
464    size_avail-=sizeof(memory_node);
465
466    if (slast->size>0 || size_avail<size) // not enough space
467      return NULL;
468    else
469    {
470      slast->size+=size+sizeof(memory_node);
471      memory_node *nc=(memory_node *)(((char *)(slast)) + (-slast->size+sizeof(memory_node)));
472     
473      nc->next=NULL;
474      nc->size=size;
475#ifdef MEM_CHECK
476      nc->name=strcpy((char *)malloc(strlen(name)+1),name);     
477      if ((intptr_t)nc==break_mem_point)
478        break_mem_fun();
479#endif     
480      if (!clast)
481        cfirst=nc;
482      else clast->next=nc;
483      return (void *)(((char *)nc)+sizeof(memory_node));
484    }
485  }
486
487
488  s->size=-s->size;
489
490  if (s->size-size>(int)sizeof(memory_node)+4)  // is there enough space to split the block?
491  {
492    memory_node *p=s;    // store this position
493    long psize=s->size-size-sizeof(memory_node);
494    s=(memory_node *)(((char *)s)+psize+sizeof(memory_node));
495    p->size=-psize;
496    s->next=p;
497    s->size=size;
498    if (cfirst==p) cfirst=s;
499    else clast->next=s;
500  }
501#ifdef MEM_CHECK
502  s->name=strcpy((char *)malloc(strlen(name)+1),name);
503  if ((intptr_t)s==break_mem_point)
504    break_mem_fun();
505#endif
506  return (void *)(((char *)s)+sizeof(memory_node));
507}
508
509
510/************************** CACHE FREE ****************************/
511/*    should be called to free a pointer in the cache heap        */
512/*    i.e. end of the heap                                        */
513/******************************************************************/
514void block_manager::cache_free(void *ptr)
515{
516  // see if this was a small_block allocation
517  void *next=(void *)(*(((long *)ptr)-1));
518  if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
519  {
520    small_block *s=(small_block *)next;
521    if (s->size<=0)
522    {
523      fprintf(stderr,"jfree : bad pointer\n");
524      return ;
525    }
526
527    int field=(((char *)ptr)-((char *)s)-sizeof(small_block))/(s->size+4);
528#ifdef MEM_CHECK
529    free(s->name[field]);
530#endif
531    s->alloc_list&=(0xffffffff-(1<<field));
532    if (s->alloc_list==0)
533    {
534      small_block *l=NULL;
535      small_block *n=cblocks[s->size];
536      for (;n!=s;n=n->next) l=n;
537#ifdef MEM_CHECK
538      if (!n)
539      { printf("Free small block error\n"); }
540#endif
541      if (!l)
542      cblocks[s->size]=s->next;
543      else l->next=s->next;
544      cache_free(s);
545    }     
546  } else
547  {
548    memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node)),*last=NULL;
549    memory_node *n=cfirst;
550    for (;n && n!=o;n=n->next) last=n;
551#ifdef MEM_CHECK
552    if (!n)
553    { printf("Free cached big block error\n"); }
554    free(o->name);
555#endif
556   
557    if (last && last->size<0)   // can we add into last block
558    {
559      memory_node *prev=NULL;
560      for (memory_node *n=cfirst;n && n!=last;n=n->next) prev=n;   // find previous to last pointer
561      if (prev)
562        prev->next=o;
563      else cfirst=o;
564
565      o->size=last->size-o->size-sizeof(memory_node);
566      last=prev;
567    } else o->size=-o->size;
568   
569    if (!o->next)           // if no next block, then we should add back into static memory
570    {
571      if (last) last->next=NULL;  // unlink from cache chain
572      else cfirst=NULL;
573
574      if (slast->size>0)    // if last static is allocated then create a new free static at end of list
575      {
576        slast->next=o;
577        slast=o;
578      } else     
579        slast->size+=o->size-sizeof(memory_node);  // else just increase the size of last block
580    } else if (o->next->size<0)   // see if we can add into next block
581    {
582      o->next->size+=o->size-sizeof(memory_node);
583      if (last)     
584        last->next=o->next;
585      else
586        cfirst=o->next;
587    }
588  } 
589}
590
591
592
593/************************** STATIC FREE ***************************/
594/*    should be called to free a pointer in the static heap       */
595/*    i.e. begining of the heap                                   */
596/******************************************************************/
597void block_manager::static_free(void *ptr)
598{
599  // see if this was a small_block allocation
600  void *next=(void *)(*(((long *)ptr)-1));
601  if (next && next<ptr)  // small allocation
602  {
603    small_block *s=(small_block *)next;
604    if (s->size<=0)
605    {
606      fprintf(stderr,"jfree : bad pointer\n");
607      return ;
608    }
609#ifdef MEM_CLEAR
610    memset(ptr,0,s->size);
611#endif
612
613    int field=(((char *)ptr)-((char *)s)-sizeof(small_block))/(s->size+4);
614#ifdef MEM_CHECK
615    free(s->name[field]);
616#endif
617    s->alloc_list&=(0xffffffff-(1<<field));
618    if (s->alloc_list==0)
619    {
620      small_block *l=NULL;
621      small_block *n=sblocks[s->size];
622      for (;n!=s;n=n->next) l=n;
623#ifdef MEM_CHECK
624      if (!n) { printf("Free static small block error\n"); }
625#endif
626      if (!l)
627      sblocks[s->size]=s->next;
628      else l->next=s->next;
629      static_free(s);
630    }     
631  } else
632  {
633    memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node)),*last=NULL;
634#ifdef MEM_CHECK
635    free(o->name);
636#endif
637#ifdef MEM_CLEAR
638    memset(ptr,0,o->size);
639#endif
640
641    if (o->next && o->next->size<0)   // see if we can add into next block
642    {
643      if (o->next==slast)
644        slast=o;
645      o->size+=-o->next->size+sizeof(memory_node);
646      o->next=o->next->next;
647    }
648
649    memory_node *n=sfirst;
650    for (;n && n!=o;n=n->next) last=n;
651#ifdef MEM_CHECK
652    if (!n) { printf("Free static big block error\n"); }
653#endif
654   
655    if (last && last->size<0)
656    {
657      if (o==slast) slast=last;
658      last->next=o->next;
659      last->size-=o->size+sizeof(memory_node); 
660    } else o->size=-o->size;           
661  } 
662}
663
664
665void jmalloc_uninit()
666{
667  for (int i=0;i<bmanage_total;i++)
668  {
669    switch (bmanage[i].block_type)
670    {
671      case HI_BLOCK :
672      { free(bmanage[i].addr); } break;
673#ifdef __WATCOMC__     
674      case LOW_BLOCK :
675      { free_low_memory(bmanage[i].addr); } break;
676#endif     
677    }
678  }
679  bmanage_total=0;
680}
681
682void jmem_cleanup(int ret, void *arg)
683{ jmalloc_uninit(); }
684
685 
686int jmalloc_max_size=3072000;
687int jmalloc_min_low_size=0x1000;
688char *not_enough_total_memory_message="Memory manager : Sorry you do not have enough memory available to\n"
689                                       "                 run this program.\n"
690                                       "    DOS users  : Remove any TSR's and device drivers you can.\n"
691                                       "    UNIX users : Do you have a swapfile/partition setup?\n";
692char *not_enough_low_memory_message="Memory Manager : Not enough low memory available (%d : need %d)\n"
693                                   "  Suggestions...\n"
694                                   "    - make a boot disk\n"
695                                   "    - remove TSR's  & drivers not needed by ABUSE\n"
696                                   "    - add memory to your system\n";
697
698void jmalloc_init(long min_size)
699{
700  fprintf(stderr,"Disabling memory manager, using libc instead\n");
701  return;
702
703  if (bmanage_total)
704    fprintf(stderr,"warning : jmalloc_init called twice\n");
705  else
706  {
707//    exit_proc(jmem_cleanup,jmalloc_uninit);          // make sure memory gets freed up on exit
708    void *mem;
709
710#ifdef __POWERPC__
711    long size=jmalloc_max_size-0x10000;
712    for (mem=NULL;!mem && size>0x10000;)
713    {
714      mem=malloc(size+0x10000);
715      if (!mem) size-=0x100;       
716    }
717    free(mem);
718    mem = malloc(size);
719#else
720    long size=jmalloc_max_size;
721    for (mem=NULL;!mem && size>0x4000;)
722    {
723      mem=malloc(size);
724      if (!mem) size-=0x100;       
725    }
726#endif
727    if (mem)
728    {
729      bmanage[bmanage_total].init(mem,size,HI_BLOCK);
730      bmanage_total++;     
731      fprintf(stderr,"Added himem block (%d bytes)\n",size);
732    }
733
734/*    bmanage[bmanage_total].init(malloc(2039552),2039552,HI_BLOCK);
735    bmanage_total++;     
736    bmanage[bmanage_total].init(malloc(150224),150224,HI_BLOCK);
737    bmanage_total++;      */
738
739#ifdef __WATCOMC__
740    if (size!=jmalloc_max_size)
741    {
742      do
743      {
744        size=low_memory_available();
745        if (size>jmalloc_min_low_size+0x1000)              // save 64K for misc low memory needs
746        {
747          bmanage[bmanage_total].init(alloc_low_memory(size-jmalloc_min_low_size-0x1000),size-jmalloc_min_low_size-0x1000,LOW_BLOCK);
748          bmanage_total++;
749          fprintf(stderr,"Added low memory block (%d bytes)\n",size);
750        }
751      } while (size>jmalloc_min_low_size+0x1000);
752      if (size<jmalloc_min_low_size)
753      {
754        fprintf(stderr,not_enough_low_memory_message,size,jmalloc_min_low_size);
755        exit(0);
756      }
757    }
758#endif
759 
760    fprintf(stderr,"Memory available : %d\n",j_available());
761    if (j_available()<min_size)
762    {
763      fprintf(stderr,not_enough_total_memory_message);
764      exit(0);
765    }
766  }
767}
768
769
770long j_available()
771{
772  long size=0;
773  for (int i=0;i<bmanage_total;i++)
774    size+=bmanage[i].available();
775  return size;
776}
777
778long j_allocated()
779{
780  long size=0;
781  for (int i=0;i<bmanage_total;i++)
782    size+=bmanage[i].allocated();
783  return size;
784}
785
786
787void *jmalloc(long size, char *name)
788
789  if (!bmanage_total)
790    return malloc(size);
791
792  size=(size+3)&(0xffffffff-3);
793  do
794  {
795    for (int i=0;i<bmanage_total;i++)
796    {
797      void *a;
798      if (alloc_space==ALLOC_SPACE_STATIC)
799      {
800        a=bmanage[i].static_alloc(size,name);
801      }
802      else
803      {
804        a=bmanage[i].cache_alloc(size,name);
805      }
806      if (a) return a;
807    }
808    free_up_memory();
809  } while (1); 
810}
811
812void jfree(void *ptr)
813{
814  if (ptr == NULL)
815    return;
816  if (!bmanage_total)
817  {
818    free(ptr);
819    return ;
820  }
821  for (int i=0;i<bmanage_total;i++)
822    if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
823    {
824      if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
825      {
826        bmanage[i].static_free(ptr);
827        return ;
828      } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
829      {
830        bmanage[i].cache_free(ptr);
831        return ;
832      }
833    }
834
835  free (ptr); 
836//  fprintf(stderr,"jfree : bad pointer\n");
837}
838
839
840void *jrealloc(void *ptr, long size, char *name)
841
842  if (!ptr) return jmalloc(size,name);
843  if (!bmanage_total) { return realloc(ptr,size); }
844
845  if (size==0) { jfree(ptr); return NULL; }
846
847  long old_size=0;
848  for (int i=0;i<bmanage_total;i++)
849    if (ptr>=(void *)bmanage[i].sfirst &&
850        ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))
851    {
852      old_size=bmanage[i].pointer_size(ptr); 
853      if (ptr<=(void *)bmanage[i].slast)
854      {
855        int sp=alloc_space; sp=ALLOC_SPACE_STATIC;
856        void *nptr=jmalloc(size,name);
857        if (size>old_size)
858          memcpy(nptr,ptr,old_size);
859        else memcpy(nptr,ptr,size);
860        bmanage[i].static_free(ptr);
861        alloc_space=sp;
862        return nptr;
863      } else
864      {
865        int sp=alloc_space; sp=ALLOC_SPACE_CACHE;
866        void *nptr=jmalloc(size,name);
867        if (size>old_size)
868          memcpy(nptr,ptr,old_size);
869        else memcpy(nptr,ptr,size);
870        bmanage[i].cache_free(ptr);
871        alloc_space=sp;
872        return nptr;
873      }
874    }
875  fprintf(stderr,"jrealloc : bad pointer\n");
876  return NULL;
877}
878
879void dmem_report()
880{
881  mem_report("debug.mem");
882}
883
884
885void mem_report(char *filename)
886{
887        char *reportpath;
888        reportpath = (char *)jmalloc( strlen( get_save_filename_prefix() ) + strlen( filename ) + 1, "reportpath" );
889        sprintf( reportpath, "%s%s", get_save_filename_prefix(), filename );
890
891        FILE *fp = fopen( reportpath, "wb" );
892        if( fp != NULL )        /* make sure we actually got a file */
893        {
894                for( int i = 0; i < bmanage_total; i++ )
895                {
896                        bmanage[i].report( fp );
897                }
898                fclose( fp );
899        }
900        jfree( reportpath );
901}
902
903void *operator new( size_t size)
904
905  return jmalloc(size,"::new object");
906}
907
908void operator delete(void *ptr)
909{
910  jfree(ptr);
911}
912
913
914long small_ptr_size(void *ptr)
915{
916  return ((small_block *)(((long *)ptr)[-1]))->size;
917}
918
919
920int valid_ptr(void *ptr)
921{
922  if (!bmanage_total) { return 0; }
923  for (int i=0;i<bmanage_total;i++)
924    if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
925    {
926      if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
927      {
928        return bmanage[i].valid_static_ptr(ptr);
929      } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
930      {
931        return bmanage[i].valid_cache_ptr(ptr);
932      }
933    }
934
935  return 0;
936}
937
Note: See TracBrowser for help on using the repository browser.