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

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