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

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