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

Last change on this file since 40 was 40, checked in by Sam Hocevar, 15 years ago
  • Fix a few more warnings.
  • Remove -Wshadow from the warnings because it is too verbose for now.
  • Remove warning flags that have no meaning in C++.
File size: 22.5 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 JM_SMALL_SIZE 128      // above 128 bytes is considered to be a big block and no hashing is done
16int alloc_space=ALLOC_SPACE_STATIC;
17
18extern void free_up_memory();
19
20#ifdef MEM_CHECK
21intptr_t break_mem_point=0;       // can be set in debugger, break mem fun will be called when this address is allocated
22void break_mem_fun()
23{
24  printf("memory breakpoint\n");
25}
26#endif
27
28struct memory_node
29{
30  int32_t size;
31#ifdef MEM_CHECK
32  char *name;                     // name is allocated on regular heap
33#endif                            // because it is used for debugging purposes
34                                  // and will probably be run on my linux box with VMM
35  memory_node *next;
36};
37
38
39struct small_block
40
41  uint32_t size;             // size of blocks...
42  uint32_t alloc_list;            // bit field saying weither each block is allocated or not.
43  small_block *next;              // next small block of same size
44#ifdef MEM_CHECK
45  char *name[32];
46#endif
47} ;
48
49enum { HI_BLOCK, LOW_BLOCK };
50
51class block_manager
52{
53  public :
54
55  int32_t block_size;                             // size of this memory_block
56  small_block *sblocks[JM_SMALL_SIZE];
57  small_block *cblocks[JM_SMALL_SIZE];
58  void *addr;
59
60  memory_node *sfirst,*slast,
61              *cfirst;
62  uint8_t block_type;
63
64  void init(void *block, int32_t Block_size, uint8_t type);
65  void *static_alloc(int32_t size, char const *name);
66  void *cache_alloc(int32_t size, char const *name);
67  void static_free(void *ptr);
68  void cache_free(void *ptr);
69  int32_t available();
70  int32_t allocated();
71  int32_t pointer_size(void *ptr);
72  void report(FILE *fp);
73  void inspect();
74
75  int valid_static_ptr(void *ptr);     // only called from within debugger
76  int valid_cache_ptr(void *ptr);
77} bmanage[5];
78
79int bmanage_total=0;
80
81
82void inspect_memory()
83{
84  for (int i=0;i<bmanage_total;i++)
85    bmanage[i].inspect();
86}
87
88
89int block_manager::valid_static_ptr(void *ptr)
90{
91  void *next=(void *)(*(((int32_t *)ptr)-1));
92  if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
93  {
94    small_block *s=(small_block *)next;
95    if (s->size<=0) return 0;
96
97    small_block *c=sblocks[s->size];
98    while (c && c!=s) c=c->next;
99    if (!c) return 0;
100  }
101
102  memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node));
103  memory_node *f=sfirst;
104  while (f && f!=o) f=f->next;
105  if (f) return 1;
106  else return 0;
107}
108
109
110int block_manager::valid_cache_ptr(void *ptr)
111{
112  void *next=(void *)(*(((int32_t *)ptr)-1));
113  if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
114  {
115    small_block *s=(small_block *)next;
116    if (s->size<=0) return 0;
117
118    small_block *c=cblocks[s->size];
119    while (c && c!=s) c=c->next;
120    if (!c) return 0;
121  }
122
123  memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node));
124  memory_node *f=cfirst;
125  while (f && f!=o) f=f->next;
126  if (f) return 1;
127  else return 0;
128}
129
130void small_static_allocation_summary(int &total, int *&static_list, int *&cache_list)
131{
132  int size=1;
133  total=JM_SMALL_SIZE/4;
134  static_list=(int *)jmalloc(total*sizeof(int),"small static report");
135  cache_list=(int *)jmalloc(total*sizeof(int),"small cache report");
136 
137  for (;size<total;size++)
138  {
139    static_list[size]=0;
140    cache_list[size]=0;
141    int i,x;
142    for (i=0;i<bmanage_total;i++)
143    {
144      small_block *s=bmanage[i].sblocks[size];
145      while (s)
146      {
147        for (x=0;x<32;x++)
148          if (s->alloc_list&(1<<x))
149            static_list[size]++;
150
151        s=s->next;
152      }
153
154      s=bmanage[i].cblocks[size];
155      while (s)
156      {
157        for (x=0;x<32;x++)
158          if (s->alloc_list&(1<<x))
159            cache_list[size]++;
160
161        s=s->next;
162      }
163    }
164  }
165}
166
167void block_manager::inspect()
168{
169  memory_node *f=sfirst;
170  for (;f;f=f->next);               // scan through static big list
171
172  int i,bit=1;
173  for (i=0;i<JM_SMALL_SIZE;i++)
174  {
175    for (small_block *s=sblocks[i];s;s=s->next)
176    {
177      char *addr=((char *)(s+1));
178      for (int j=0;j<32;j++)
179      {
180        if (s->alloc_list&bit)
181        {
182          void *next=(void *)(*(((intptr_t *)addr)));
183          if ((intptr_t)next!=(intptr_t)s)
184          {
185            fprintf(stderr,"inspect : bad pointer\n");
186            return ;       
187          }
188        }
189        bit=bit<<1;
190        addr+=s->size+4;
191      }
192    }
193  }
194
195}
196
197void block_manager::report(FILE *fp)
198{
199  fprintf(fp,"************** Block size = %d ***************\n",block_size);
200  fprintf(fp,"************** STATIC SPACE ******************\n");
201  int i=0;
202  memory_node *f=sfirst;
203  for (;f;f=f->next,i++)
204  {   
205    fprintf(fp, "%4d   %p (%ld) %4ld      ",
206            i, f, (long int)((char *)f - (char *)sfirst), (long int)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 %i ******************\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
276int32_t 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
284int32_t block_manager::available()
285{
286  int32_t 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
296int32_t block_manager::allocated()
297{
298  int32_t 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, int32_t Block_size, uint8_t 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(int32_t size, char const *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      intptr_t *addr=(intptr_t *)(((char *)s)+sizeof(small_block));
348      *addr=(intptr_t)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          *((intptr_t *)addr)=(intptr_t)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(int32_t size, char const *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      intptr_t *addr=(intptr_t *)(((char *)s)+sizeof(small_block));
427      *addr=(intptr_t)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          *((intptr_t *)addr)=(intptr_t)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    int32_t 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    int32_t 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 *)(*(((int32_t *)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 *)(*(((int32_t *)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;
688static char const *not_enough_total_memory_message =
689    "Memory manager : Sorry you do not have enough memory available to\n"
690    "                 run this program.\n"
691    "    DOS users  : Remove any TSR's and device drivers you can.\n"
692    "    UNIX users : Do you have a swapfile/partition setup?\n";
693#ifdef __WATCOMC__
694static char const *not_enough_low_memory_message =
695    "Memory Manager : Not enough low memory available (%d : need %d)\n"
696    "  Suggestions...\n"
697    "    - make a boot disk\n"
698    "    - remove TSRs & drivers not needed by ABUSE\n"
699    "    - add memory to your system\n";
700#endif
701
702void jmalloc_init(int32_t min_size)
703{
704  fprintf(stderr,"Disabling memory manager, using libc instead\n");
705  return;
706
707  if (bmanage_total)
708    fprintf(stderr,"warning : jmalloc_init called twice\n");
709  else
710  {
711//    exit_proc(jmem_cleanup,jmalloc_uninit);          // make sure memory gets freed up on exit
712    void *mem;
713
714#ifdef __POWERPC__
715    int32_t size=jmalloc_max_size-0x10000;
716    for (mem=NULL;!mem && size>0x10000;)
717    {
718      mem=malloc(size+0x10000);
719      if (!mem) size-=0x100;       
720    }
721    free(mem);
722    mem = malloc(size);
723#else
724    int32_t size=jmalloc_max_size;
725    for (mem=NULL;!mem && size>0x4000;)
726    {
727      mem=malloc(size);
728      if (!mem) size-=0x100;       
729    }
730#endif
731    if (mem)
732    {
733      bmanage[bmanage_total].init(mem,size,HI_BLOCK);
734      bmanage_total++;     
735      fprintf(stderr,"Added himem block (%d bytes)\n",size);
736    }
737
738/*    bmanage[bmanage_total].init(malloc(2039552),2039552,HI_BLOCK);
739    bmanage_total++;     
740    bmanage[bmanage_total].init(malloc(150224),150224,HI_BLOCK);
741    bmanage_total++;      */
742
743#ifdef __WATCOMC__
744    if (size!=jmalloc_max_size)
745    {
746      do
747      {
748        size=low_memory_available();
749        if (size>jmalloc_min_low_size+0x1000)              // save 64K for misc low memory needs
750        {
751          bmanage[bmanage_total].init(alloc_low_memory(size-jmalloc_min_low_size-0x1000),size-jmalloc_min_low_size-0x1000,LOW_BLOCK);
752          bmanage_total++;
753          fprintf(stderr,"Added low memory block (%d bytes)\n",size);
754        }
755      } while (size>jmalloc_min_low_size+0x1000);
756      if (size<jmalloc_min_low_size)
757      {
758        fprintf(stderr,not_enough_low_memory_message,size,jmalloc_min_low_size);
759        exit(0);
760      }
761    }
762#endif
763 
764    fprintf(stderr,"Memory available : %d\n",j_available());
765    if (j_available()<min_size)
766    {
767      fprintf(stderr,not_enough_total_memory_message);
768      exit(0);
769    }
770  }
771}
772
773
774int32_t j_available()
775{
776  int32_t size=0;
777  for (int i=0;i<bmanage_total;i++)
778    size+=bmanage[i].available();
779  return size;
780}
781
782int32_t j_allocated()
783{
784  int32_t size=0;
785  for (int i=0;i<bmanage_total;i++)
786    size+=bmanage[i].allocated();
787  return size;
788}
789
790
791void *jmalloc(int32_t size, char const *name)
792
793  if (!bmanage_total)
794    return malloc(size);
795
796  size=(size+3)&(0xffffffff-3);
797  do
798  {
799    for (int i=0;i<bmanage_total;i++)
800    {
801      void *a;
802      if (alloc_space==ALLOC_SPACE_STATIC)
803      {
804        a=bmanage[i].static_alloc(size,name);
805      }
806      else
807      {
808        a=bmanage[i].cache_alloc(size,name);
809      }
810      if (a) return a;
811    }
812    free_up_memory();
813  } while (1); 
814}
815
816void jfree(void *ptr)
817{
818  if (ptr == NULL)
819    return;
820  if (!bmanage_total)
821  {
822    free(ptr);
823    return ;
824  }
825  for (int i=0;i<bmanage_total;i++)
826    if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
827    {
828      if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
829      {
830        bmanage[i].static_free(ptr);
831        return ;
832      } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
833      {
834        bmanage[i].cache_free(ptr);
835        return ;
836      }
837    }
838
839  free (ptr); 
840//  fprintf(stderr,"jfree : bad pointer\n");
841}
842
843
844void *jrealloc(void *ptr, int32_t size, char const *name)
845
846  if (!ptr) return jmalloc(size,name);
847  if (!bmanage_total) { return realloc(ptr,size); }
848
849  if (size==0) { jfree(ptr); return NULL; }
850
851  int32_t old_size=0;
852  for (int i=0;i<bmanage_total;i++)
853    if (ptr>=(void *)bmanage[i].sfirst &&
854        ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))
855    {
856      old_size=bmanage[i].pointer_size(ptr); 
857      if (ptr<=(void *)bmanage[i].slast)
858      {
859        int sp=alloc_space; sp=ALLOC_SPACE_STATIC;
860        void *nptr=jmalloc(size,name);
861        if (size>old_size)
862          memcpy(nptr,ptr,old_size);
863        else memcpy(nptr,ptr,size);
864        bmanage[i].static_free(ptr);
865        alloc_space=sp;
866        return nptr;
867      } else
868      {
869        int sp=alloc_space; sp=ALLOC_SPACE_CACHE;
870        void *nptr=jmalloc(size,name);
871        if (size>old_size)
872          memcpy(nptr,ptr,old_size);
873        else memcpy(nptr,ptr,size);
874        bmanage[i].cache_free(ptr);
875        alloc_space=sp;
876        return nptr;
877      }
878    }
879  fprintf(stderr,"jrealloc : bad pointer\n");
880  return NULL;
881}
882
883void dmem_report()
884{
885  mem_report("debug.mem");
886}
887
888
889void mem_report(char const *filename)
890{
891        char *reportpath;
892        reportpath = (char *)jmalloc( strlen( get_save_filename_prefix() ) + strlen( filename ) + 1, "reportpath" );
893        sprintf( reportpath, "%s%s", get_save_filename_prefix(), filename );
894
895        FILE *fp = fopen( reportpath, "wb" );
896        if( fp != NULL )        /* make sure we actually got a file */
897        {
898                for( int i = 0; i < bmanage_total; i++ )
899                {
900                        bmanage[i].report( fp );
901                }
902                fclose( fp );
903        }
904        jfree( reportpath );
905}
906
907void *operator new( size_t size)
908
909  return jmalloc(size,"::new object");
910}
911
912void operator delete(void *ptr)
913{
914  jfree(ptr);
915}
916
917
918int32_t small_ptr_size(void *ptr)
919{
920  return ((small_block *)(((int32_t *)ptr)[-1]))->size;
921}
922
923
924int valid_ptr(void *ptr)
925{
926  if (!bmanage_total) { return 0; }
927  for (int i=0;i<bmanage_total;i++)
928    if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
929    {
930      if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
931      {
932        return bmanage[i].valid_static_ptr(ptr);
933      } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
934      {
935        return bmanage[i].valid_cache_ptr(ptr);
936      }
937    }
938
939  return 0;
940}
941
Note: See TracBrowser for help on using the repository browser.