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

Last change on this file since 39 was 39, checked in by Sam Hocevar, 15 years ago
  • Fix almost 2,000 warnings by using proper "const" keywords where needed.
File size: 22.4 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 (%d) %4d      ",i,f,((char *)f-(char *)sfirst),f->size);
206#ifdef MEM_CHECK
207    if (f->size>0)
208      fprintf(fp,"%s",f->name);
209    else fprintf(fp,"FREE");
210#endif
211    fprintf(fp,"\n");
212  }   
213  for (i=0;i<JM_SMALL_SIZE;i++)
214  {
215    for (small_block *s=sblocks[i];s;s=s->next)
216    {     
217      fprintf(fp,"*** Small Block size = %d ***\n",i);     
218      uint32_t bit=1;
219      char *addr=((char *)(s+1));
220      for (int j=0;j<32;j++)
221      {
222        fprintf(fp,"%p   ",addr);
223        if (s->alloc_list&bit)
224        {
225#ifdef MEM_CHECK
226          fprintf(fp,"%s\n",s->name[j]);
227#else
228          fprintf(fp,"allocated\n");
229#endif   
230        } else fprintf(fp,"FREE\n");
231        bit=bit<<1;
232        addr+=s->size+4;
233      }
234    }
235  }
236
237
238  fprintf(fp,"************** CACHE SPACE ******************\n",block_size);
239  i=0;
240  for (f=cfirst;f;f=f->next,i++)
241  {   
242    fprintf(fp,"%4d   %p %4d      ",i,f,f->size);
243#ifdef MEM_CHECK
244    if (f->size>0)
245      fprintf(fp,"%s",f->name);
246    else fprintf(fp,"FREE");
247#endif
248    fprintf(fp,"\n");
249  }   
250  for (i=0;i<JM_SMALL_SIZE;i++)
251  {
252    for (small_block *s=cblocks[i];s;s=s->next)
253    {     
254      fprintf(fp,"*** Small Block size = %d ***\n",i);     
255      uint32_t bit=1;
256      char *addr=((char *)(s+1));
257      for (int j=0;j<32;j++)
258      {
259        fprintf(fp,"%p   ",addr);
260        if (s->alloc_list&bit)
261        {
262#ifdef MEM_CHECK
263          fprintf(fp,"%s\n",s->name[j]);
264#else
265          fprintf(fp,"allocated\n");
266#endif   
267        } else fprintf(fp,"FREE\n");
268        bit=bit<<1;
269        addr+=s->size+4;
270      }
271    }
272  }
273}
274
275int32_t block_manager::pointer_size(void *ptr)
276{
277  void *next=(void *)(*(((intptr_t *)ptr)-1));
278  if (next>ptr)
279    return ((memory_node *)(((char *)ptr)-sizeof(memory_node)))->size;
280  else return ((small_block *)next)->size;
281}
282
283int32_t block_manager::available()
284{
285  int32_t size=0;
286  memory_node *f;
287  for (f=sfirst;f;f=f->next)
288    if (f->size<0) size-=f->size;
289
290  for (f=cfirst;f;f=f->next)
291    if (f->size<0) size-=f->size;
292  return size;
293}
294
295int32_t block_manager::allocated()
296{
297  int32_t size=0;
298  memory_node *f;
299  for (f=sfirst;f;f=f->next)
300    if (f->size>0) size+=f->size;
301
302  for (f=cfirst;f;f=f->next)
303    if (f->size>0) size+=f->size;
304  return size;
305}
306
307void block_manager::init(void *block, int32_t Block_size, uint8_t type)
308{
309  block_size=Block_size;
310  addr=block;
311  /*
312     I'm padding each block, because I'm comparing pointers against size
313     in jfree to determine weither a pointer is too a small object or a large alloc
314     and it must always be true that the address of the pointer is > JM_SMALL_SIZE
315     All systems I know start pointer address pretty high, but this is a porting consern.     
316  */
317 
318  slast=sfirst=(memory_node *)(((char *)block)+JM_SMALL_SIZE);   
319  sfirst->size=-(block_size-sizeof(memory_node)-JM_SMALL_SIZE);
320  sfirst->next=NULL;
321  cfirst=NULL;
322  memset(sblocks,0,sizeof(sblocks));
323  memset(cblocks,0,sizeof(cblocks));
324  block_type=type;
325}
326
327void *block_manager::static_alloc(int32_t size, char const *name)
328{
329  if (size<JM_SMALL_SIZE)
330  {
331    small_block *s=sblocks[size];
332    for (;s && s->alloc_list==0xffffffff;s=s->next);
333    if (!s)
334    {
335      s=(small_block *)static_alloc((size+4)*32+sizeof(small_block),"small_block");
336      if (!s) return NULL;   // not enough room for another small block
337      s->alloc_list=1;
338      s->next=sblocks[size];
339      sblocks[size]=s;
340      s->size=size;
341#ifdef MEM_CHECK
342      s->name[0]=strcpy((char *)malloc(strlen(name)+1),name);
343      if ((intptr_t)s==break_mem_point)
344        break_mem_fun();
345#endif     
346      intptr_t *addr=(intptr_t *)(((char *)s)+sizeof(small_block));
347      *addr=(intptr_t)s;
348      return (void *)(addr+1);  // return first block
349    } else
350    {
351      int bit=1,i=0;
352      char *addr=((char *)s)+sizeof(small_block);
353      while (1)        // we already know there is a bit free
354      {
355        if ((s->alloc_list&bit)==0)
356        {
357          s->alloc_list|=bit;
358#ifdef MEM_CHECK
359          s->name[i]=strcpy((char *)malloc(strlen(name)+1),name);
360#endif           
361          *((intptr_t *)addr)=(intptr_t)s;
362
363#ifdef MEM_CHECK
364          if ((intptr_t)addr==break_mem_point)
365            break_mem_fun();
366#endif
367
368          return (void *)(addr+4);
369        }
370        i++;
371        bit=bit<<1;
372        addr+=size+4;
373      }     
374    }               
375  }
376
377
378  memory_node *s=sfirst;
379  for (;s && -s->size<size;s=s->next);
380  if (!s) return NULL;
381  s->size=-s->size;
382
383  if (s->size-size>(int)sizeof(memory_node)+4)  // is there enough space to split the block?
384  {   
385    memory_node *p=(memory_node *)((char *)s+sizeof(memory_node)+size);
386    if (s==slast)
387      slast=p;
388    p->size=-(s->size-size-sizeof(memory_node));
389#ifdef MEM_CLEAR
390//    memset( ((memory_node *)p)+1,0,-p->size);
391#endif
392    p->next=s->next;
393    s->next=p;
394    s->size=size;
395  }
396#ifdef MEM_CHECK
397  s->name=strcpy((char *)malloc(strlen(name)+1),name);
398
399  if ((intptr_t)s==break_mem_point)
400    break_mem_fun();
401
402#endif
403  return (void *)(((char *)s)+sizeof(memory_node));
404}
405
406
407void *block_manager::cache_alloc(int32_t size, char const *name)
408{
409  if (size<JM_SMALL_SIZE)
410  {
411    small_block *s=cblocks[size];
412    for (;s && s->alloc_list==0xffffffff;s=s->next);
413    if (!s)
414    {
415      s=(small_block *)cache_alloc((size+4)*32+sizeof(small_block),"small_block");
416      if (!s) return NULL;   // not enough room for another small block
417      s->alloc_list=1;
418      s->next=cblocks[size];
419      cblocks[size]=s;
420      s->size=size;
421#ifdef MEM_CHECK
422      s->name[0]=strcpy((char *)malloc(strlen(name)+1),name);
423
424#endif     
425      intptr_t *addr=(intptr_t *)(((char *)s)+sizeof(small_block));
426      *addr=(intptr_t)s;
427#ifdef MEM_CHECK
428      if ((intptr_t)s==break_mem_point)
429        break_mem_fun();
430#endif
431      return (void *)(addr+1);  // return first block
432    } else
433    {
434      int bit=1,i=0;
435      char *addr=((char *)s)+sizeof(small_block);
436      while (1)        // we already know there is a bit free
437      {
438        if ((s->alloc_list&bit)==0)
439        {
440          s->alloc_list|=bit;
441#ifdef MEM_CHECK
442          s->name[i]=strcpy((char *)malloc(strlen(name)+1),name);
443          if ((intptr_t)s==break_mem_point)
444            break_mem_fun();
445#endif           
446          *((intptr_t *)addr)=(intptr_t)s;
447          return (void *)(addr+4);
448        }
449        i++;
450        bit=bit<<1;
451        addr+=size+4;
452      }     
453    }               
454  }
455
456
457  memory_node *clast=NULL;
458  memory_node *s=cfirst;
459  for (;s && -s->size<size;s=s->next) clast=s;
460  if (!s) // no current cache space for object, see if we can enlarge the cache space
461  {
462    int32_t size_avail=-slast->size;
463    size_avail-=sizeof(memory_node);
464
465    if (slast->size>0 || size_avail<size) // not enough space
466      return NULL;
467    else
468    {
469      slast->size+=size+sizeof(memory_node);
470      memory_node *nc=(memory_node *)(((char *)(slast)) + (-slast->size+sizeof(memory_node)));
471     
472      nc->next=NULL;
473      nc->size=size;
474#ifdef MEM_CHECK
475      nc->name=strcpy((char *)malloc(strlen(name)+1),name);     
476      if ((intptr_t)nc==break_mem_point)
477        break_mem_fun();
478#endif     
479      if (!clast)
480        cfirst=nc;
481      else clast->next=nc;
482      return (void *)(((char *)nc)+sizeof(memory_node));
483    }
484  }
485
486
487  s->size=-s->size;
488
489  if (s->size-size>(int)sizeof(memory_node)+4)  // is there enough space to split the block?
490  {
491    memory_node *p=s;    // store this position
492    int32_t psize=s->size-size-sizeof(memory_node);
493    s=(memory_node *)(((char *)s)+psize+sizeof(memory_node));
494    p->size=-psize;
495    s->next=p;
496    s->size=size;
497    if (cfirst==p) cfirst=s;
498    else clast->next=s;
499  }
500#ifdef MEM_CHECK
501  s->name=strcpy((char *)malloc(strlen(name)+1),name);
502  if ((intptr_t)s==break_mem_point)
503    break_mem_fun();
504#endif
505  return (void *)(((char *)s)+sizeof(memory_node));
506}
507
508
509/************************** CACHE FREE ****************************/
510/*    should be called to free a pointer in the cache heap        */
511/*    i.e. end of the heap                                        */
512/******************************************************************/
513void block_manager::cache_free(void *ptr)
514{
515  // see if this was a small_block allocation
516  void *next=(void *)(*(((int32_t *)ptr)-1));
517  if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
518  {
519    small_block *s=(small_block *)next;
520    if (s->size<=0)
521    {
522      fprintf(stderr,"jfree : bad pointer\n");
523      return ;
524    }
525
526    int field=(((char *)ptr)-((char *)s)-sizeof(small_block))/(s->size+4);
527#ifdef MEM_CHECK
528    free(s->name[field]);
529#endif
530    s->alloc_list&=(0xffffffff-(1<<field));
531    if (s->alloc_list==0)
532    {
533      small_block *l=NULL;
534      small_block *n=cblocks[s->size];
535      for (;n!=s;n=n->next) l=n;
536#ifdef MEM_CHECK
537      if (!n)
538      { printf("Free small block error\n"); }
539#endif
540      if (!l)
541      cblocks[s->size]=s->next;
542      else l->next=s->next;
543      cache_free(s);
544    }     
545  } else
546  {
547    memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node)),*last=NULL;
548    memory_node *n=cfirst;
549    for (;n && n!=o;n=n->next) last=n;
550#ifdef MEM_CHECK
551    if (!n)
552    { printf("Free cached big block error\n"); }
553    free(o->name);
554#endif
555   
556    if (last && last->size<0)   // can we add into last block
557    {
558      memory_node *prev=NULL;
559      for (memory_node *n=cfirst;n && n!=last;n=n->next) prev=n;   // find previous to last pointer
560      if (prev)
561        prev->next=o;
562      else cfirst=o;
563
564      o->size=last->size-o->size-sizeof(memory_node);
565      last=prev;
566    } else o->size=-o->size;
567   
568    if (!o->next)           // if no next block, then we should add back into static memory
569    {
570      if (last) last->next=NULL;  // unlink from cache chain
571      else cfirst=NULL;
572
573      if (slast->size>0)    // if last static is allocated then create a new free static at end of list
574      {
575        slast->next=o;
576        slast=o;
577      } else     
578        slast->size+=o->size-sizeof(memory_node);  // else just increase the size of last block
579    } else if (o->next->size<0)   // see if we can add into next block
580    {
581      o->next->size+=o->size-sizeof(memory_node);
582      if (last)     
583        last->next=o->next;
584      else
585        cfirst=o->next;
586    }
587  } 
588}
589
590
591
592/************************** STATIC FREE ***************************/
593/*    should be called to free a pointer in the static heap       */
594/*    i.e. begining of the heap                                   */
595/******************************************************************/
596void block_manager::static_free(void *ptr)
597{
598  // see if this was a small_block allocation
599  void *next=(void *)(*(((int32_t *)ptr)-1));
600  if (next && next<ptr)  // small allocation
601  {
602    small_block *s=(small_block *)next;
603    if (s->size<=0)
604    {
605      fprintf(stderr,"jfree : bad pointer\n");
606      return ;
607    }
608#ifdef MEM_CLEAR
609    memset(ptr,0,s->size);
610#endif
611
612    int field=(((char *)ptr)-((char *)s)-sizeof(small_block))/(s->size+4);
613#ifdef MEM_CHECK
614    free(s->name[field]);
615#endif
616    s->alloc_list&=(0xffffffff-(1<<field));
617    if (s->alloc_list==0)
618    {
619      small_block *l=NULL;
620      small_block *n=sblocks[s->size];
621      for (;n!=s;n=n->next) l=n;
622#ifdef MEM_CHECK
623      if (!n) { printf("Free static small block error\n"); }
624#endif
625      if (!l)
626      sblocks[s->size]=s->next;
627      else l->next=s->next;
628      static_free(s);
629    }     
630  } else
631  {
632    memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node)),*last=NULL;
633#ifdef MEM_CHECK
634    free(o->name);
635#endif
636#ifdef MEM_CLEAR
637    memset(ptr,0,o->size);
638#endif
639
640    if (o->next && o->next->size<0)   // see if we can add into next block
641    {
642      if (o->next==slast)
643        slast=o;
644      o->size+=-o->next->size+sizeof(memory_node);
645      o->next=o->next->next;
646    }
647
648    memory_node *n=sfirst;
649    for (;n && n!=o;n=n->next) last=n;
650#ifdef MEM_CHECK
651    if (!n) { printf("Free static big block error\n"); }
652#endif
653   
654    if (last && last->size<0)
655    {
656      if (o==slast) slast=last;
657      last->next=o->next;
658      last->size-=o->size+sizeof(memory_node); 
659    } else o->size=-o->size;           
660  } 
661}
662
663
664void jmalloc_uninit()
665{
666  for (int i=0;i<bmanage_total;i++)
667  {
668    switch (bmanage[i].block_type)
669    {
670      case HI_BLOCK :
671      { free(bmanage[i].addr); } break;
672#ifdef __WATCOMC__     
673      case LOW_BLOCK :
674      { free_low_memory(bmanage[i].addr); } break;
675#endif     
676    }
677  }
678  bmanage_total=0;
679}
680
681void jmem_cleanup(int ret, void *arg)
682{ jmalloc_uninit(); }
683
684 
685int jmalloc_max_size = 3072000;
686int jmalloc_min_low_size = 0x1000;
687static char const *not_enough_total_memory_message =
688    "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";
692static char const *not_enough_low_memory_message =
693    "Memory Manager : Not enough low memory available (%d : need %d)\n"
694    "  Suggestions...\n"
695    "    - make a boot disk\n"
696    "    - remove TSRs & drivers not needed by ABUSE\n"
697    "    - add memory to your system\n";
698
699void jmalloc_init(int32_t min_size)
700{
701  fprintf(stderr,"Disabling memory manager, using libc instead\n");
702  return;
703
704  if (bmanage_total)
705    fprintf(stderr,"warning : jmalloc_init called twice\n");
706  else
707  {
708//    exit_proc(jmem_cleanup,jmalloc_uninit);          // make sure memory gets freed up on exit
709    void *mem;
710
711#ifdef __POWERPC__
712    int32_t size=jmalloc_max_size-0x10000;
713    for (mem=NULL;!mem && size>0x10000;)
714    {
715      mem=malloc(size+0x10000);
716      if (!mem) size-=0x100;       
717    }
718    free(mem);
719    mem = malloc(size);
720#else
721    int32_t size=jmalloc_max_size;
722    for (mem=NULL;!mem && size>0x4000;)
723    {
724      mem=malloc(size);
725      if (!mem) size-=0x100;       
726    }
727#endif
728    if (mem)
729    {
730      bmanage[bmanage_total].init(mem,size,HI_BLOCK);
731      bmanage_total++;     
732      fprintf(stderr,"Added himem block (%d bytes)\n",size);
733    }
734
735/*    bmanage[bmanage_total].init(malloc(2039552),2039552,HI_BLOCK);
736    bmanage_total++;     
737    bmanage[bmanage_total].init(malloc(150224),150224,HI_BLOCK);
738    bmanage_total++;      */
739
740#ifdef __WATCOMC__
741    if (size!=jmalloc_max_size)
742    {
743      do
744      {
745        size=low_memory_available();
746        if (size>jmalloc_min_low_size+0x1000)              // save 64K for misc low memory needs
747        {
748          bmanage[bmanage_total].init(alloc_low_memory(size-jmalloc_min_low_size-0x1000),size-jmalloc_min_low_size-0x1000,LOW_BLOCK);
749          bmanage_total++;
750          fprintf(stderr,"Added low memory block (%d bytes)\n",size);
751        }
752      } while (size>jmalloc_min_low_size+0x1000);
753      if (size<jmalloc_min_low_size)
754      {
755        fprintf(stderr,not_enough_low_memory_message,size,jmalloc_min_low_size);
756        exit(0);
757      }
758    }
759#endif
760 
761    fprintf(stderr,"Memory available : %d\n",j_available());
762    if (j_available()<min_size)
763    {
764      fprintf(stderr,not_enough_total_memory_message);
765      exit(0);
766    }
767  }
768}
769
770
771int32_t j_available()
772{
773  int32_t size=0;
774  for (int i=0;i<bmanage_total;i++)
775    size+=bmanage[i].available();
776  return size;
777}
778
779int32_t j_allocated()
780{
781  int32_t size=0;
782  for (int i=0;i<bmanage_total;i++)
783    size+=bmanage[i].allocated();
784  return size;
785}
786
787
788void *jmalloc(int32_t size, char const *name)
789
790  if (!bmanage_total)
791    return malloc(size);
792
793  size=(size+3)&(0xffffffff-3);
794  do
795  {
796    for (int i=0;i<bmanage_total;i++)
797    {
798      void *a;
799      if (alloc_space==ALLOC_SPACE_STATIC)
800      {
801        a=bmanage[i].static_alloc(size,name);
802      }
803      else
804      {
805        a=bmanage[i].cache_alloc(size,name);
806      }
807      if (a) return a;
808    }
809    free_up_memory();
810  } while (1); 
811}
812
813void jfree(void *ptr)
814{
815  if (ptr == NULL)
816    return;
817  if (!bmanage_total)
818  {
819    free(ptr);
820    return ;
821  }
822  for (int i=0;i<bmanage_total;i++)
823    if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
824    {
825      if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
826      {
827        bmanage[i].static_free(ptr);
828        return ;
829      } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
830      {
831        bmanage[i].cache_free(ptr);
832        return ;
833      }
834    }
835
836  free (ptr); 
837//  fprintf(stderr,"jfree : bad pointer\n");
838}
839
840
841void *jrealloc(void *ptr, int32_t size, char const *name)
842
843  if (!ptr) return jmalloc(size,name);
844  if (!bmanage_total) { return realloc(ptr,size); }
845
846  if (size==0) { jfree(ptr); return NULL; }
847
848  int32_t old_size=0;
849  for (int i=0;i<bmanage_total;i++)
850    if (ptr>=(void *)bmanage[i].sfirst &&
851        ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))
852    {
853      old_size=bmanage[i].pointer_size(ptr); 
854      if (ptr<=(void *)bmanage[i].slast)
855      {
856        int sp=alloc_space; sp=ALLOC_SPACE_STATIC;
857        void *nptr=jmalloc(size,name);
858        if (size>old_size)
859          memcpy(nptr,ptr,old_size);
860        else memcpy(nptr,ptr,size);
861        bmanage[i].static_free(ptr);
862        alloc_space=sp;
863        return nptr;
864      } else
865      {
866        int sp=alloc_space; sp=ALLOC_SPACE_CACHE;
867        void *nptr=jmalloc(size,name);
868        if (size>old_size)
869          memcpy(nptr,ptr,old_size);
870        else memcpy(nptr,ptr,size);
871        bmanage[i].cache_free(ptr);
872        alloc_space=sp;
873        return nptr;
874      }
875    }
876  fprintf(stderr,"jrealloc : bad pointer\n");
877  return NULL;
878}
879
880void dmem_report()
881{
882  mem_report("debug.mem");
883}
884
885
886void mem_report(char const *filename)
887{
888        char *reportpath;
889        reportpath = (char *)jmalloc( strlen( get_save_filename_prefix() ) + strlen( filename ) + 1, "reportpath" );
890        sprintf( reportpath, "%s%s", get_save_filename_prefix(), filename );
891
892        FILE *fp = fopen( reportpath, "wb" );
893        if( fp != NULL )        /* make sure we actually got a file */
894        {
895                for( int i = 0; i < bmanage_total; i++ )
896                {
897                        bmanage[i].report( fp );
898                }
899                fclose( fp );
900        }
901        jfree( reportpath );
902}
903
904void *operator new( size_t size)
905
906  return jmalloc(size,"::new object");
907}
908
909void operator delete(void *ptr)
910{
911  jfree(ptr);
912}
913
914
915int32_t small_ptr_size(void *ptr)
916{
917  return ((small_block *)(((int32_t *)ptr)[-1]))->size;
918}
919
920
921int valid_ptr(void *ptr)
922{
923  if (!bmanage_total) { return 0; }
924  for (int i=0;i<bmanage_total;i++)
925    if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
926    {
927      if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
928      {
929        return bmanage[i].valid_static_ptr(ptr);
930      } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
931      {
932        return bmanage[i].valid_cache_ptr(ptr);
933      }
934    }
935
936  return 0;
937}
938
Note: See TracBrowser for help on using the repository browser.