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

Last change on this file since 90 was 90, checked in by Sam Hocevar, 11 years ago
  • Get rid of WATCOMC tests.
File size: 21.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    }
683  }
684  bmanage_total=0;
685}
686
687void jmem_cleanup(int ret, void *arg)
688{ jmalloc_uninit(); }
689
690 
691int jmalloc_max_size = 3072000;
692int jmalloc_min_low_size = 0x1000;
693static char const *not_enough_total_memory_message =
694    "Memory manager : Sorry you do not have enough memory available to\n"
695    "                 run this program.\n"
696    "    DOS users  : Remove any TSR's and device drivers you can.\n"
697    "    UNIX users : Do you have a swapfile/partition setup?\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    fprintf(stderr,"Memory available : %d\n",j_available());
741    if (j_available()<min_size)
742    {
743      fprintf(stderr, "%s", not_enough_total_memory_message);
744      exit(0);
745    }
746  }
747}
748
749
750int32_t j_available()
751{
752  int32_t size=0;
753  for (int i=0;i<bmanage_total;i++)
754    size+=bmanage[i].available();
755  return size;
756}
757
758int32_t j_allocated()
759{
760  int32_t size=0;
761  for (int i=0;i<bmanage_total;i++)
762    size+=bmanage[i].allocated();
763  return size;
764}
765
766
767void *jmalloc(int32_t size, char const *name)
768
769  if (!bmanage_total)
770    return malloc(size);
771
772  size=(size+3)&(0xffffffff-3);
773  do
774  {
775    for (int i=0;i<bmanage_total;i++)
776    {
777      void *a;
778      if (alloc_space==ALLOC_SPACE_STATIC)
779      {
780        a=bmanage[i].static_alloc(size,name);
781      }
782      else
783      {
784        a=bmanage[i].cache_alloc(size,name);
785      }
786      if (a) return a;
787    }
788    free_up_memory();
789  } while (1); 
790}
791
792void jfree(void *ptr)
793{
794  if (ptr == NULL)
795    return;
796  if (!bmanage_total)
797  {
798    free(ptr);
799    return ;
800  }
801  for (int i=0;i<bmanage_total;i++)
802    if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
803    {
804      if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
805      {
806        bmanage[i].static_free(ptr);
807        return ;
808      } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
809      {
810        bmanage[i].cache_free(ptr);
811        return ;
812      }
813    }
814
815  free (ptr); 
816//  fprintf(stderr,"jfree : bad pointer\n");
817}
818
819
820void *jrealloc(void *ptr, int32_t size, char const *name)
821
822  if (!ptr) return jmalloc(size,name);
823  if (!bmanage_total) { return realloc(ptr,size); }
824
825  if (size==0) { jfree(ptr); return NULL; }
826
827  int32_t old_size=0;
828  for (int i=0;i<bmanage_total;i++)
829    if (ptr>=(void *)bmanage[i].sfirst &&
830        ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))
831    {
832      old_size=bmanage[i].pointer_size(ptr); 
833      if (ptr<=(void *)bmanage[i].slast)
834      {
835        int sp=alloc_space; sp=ALLOC_SPACE_STATIC;
836        void *nptr=jmalloc(size,name);
837        if (size>old_size)
838          memcpy(nptr,ptr,old_size);
839        else memcpy(nptr,ptr,size);
840        bmanage[i].static_free(ptr);
841        alloc_space=sp;
842        return nptr;
843      } else
844      {
845        int sp=alloc_space; sp=ALLOC_SPACE_CACHE;
846        void *nptr=jmalloc(size,name);
847        if (size>old_size)
848          memcpy(nptr,ptr,old_size);
849        else memcpy(nptr,ptr,size);
850        bmanage[i].cache_free(ptr);
851        alloc_space=sp;
852        return nptr;
853      }
854    }
855  fprintf(stderr,"jrealloc : bad pointer\n");
856  return NULL;
857}
858
859void dmem_report()
860{
861  mem_report("debug.mem");
862}
863
864
865void mem_report(char const *filename)
866{
867        char *reportpath;
868        reportpath = (char *)jmalloc( strlen( get_save_filename_prefix() ) + strlen( filename ) + 1, "reportpath" );
869        sprintf( reportpath, "%s%s", get_save_filename_prefix(), filename );
870
871        FILE *fp = fopen( reportpath, "wb" );
872        if( fp != NULL )        /* make sure we actually got a file */
873        {
874                for( int i = 0; i < bmanage_total; i++ )
875                {
876                        bmanage[i].report( fp );
877                }
878                fclose( fp );
879        }
880        jfree( reportpath );
881}
882
883void *operator new( size_t size)
884
885  return jmalloc(size,"::new object");
886}
887
888void operator delete(void *ptr)
889{
890  jfree(ptr);
891}
892
893
894int32_t small_ptr_size(void *ptr)
895{
896  return ((small_block *)(((int32_t *)ptr)[-1]))->size;
897}
898
899
900int valid_ptr(void *ptr)
901{
902  if (!bmanage_total) { return 0; }
903  for (int i=0;i<bmanage_total;i++)
904    if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
905    {
906      if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
907      {
908        return bmanage[i].valid_static_ptr(ptr);
909      } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
910      {
911        return bmanage[i].valid_cache_ptr(ptr);
912      }
913    }
914
915  return 0;
916}
917
Note: See TracBrowser for help on using the repository browser.