source: abuse/tags/pd/macabuse/imlib/jmalloc.c

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