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

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