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

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