source: golgotha/src/i4/memory/bmanage.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 8.9 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "memory/bmanage.hh"
10#include "error/error.hh"
11#include "file/file.hh"
12#include <string.h>
13#include <stdlib.h>
14
15//#define i4_MEM_CLEAR 1
16
17#ifdef i4_MEM_CHECK
18static int i4_show_libc_mallocs=0;
19
20static char *str_alloc(char *s)
21{
22  if (i4_show_libc_mallocs)
23    i4_warning("str_alloc : '%s'", s);
24
25  int l=strlen(s)+1;
26  char *t=(char *)::malloc(l);
27  if (!t)
28    i4_error("could not allocate memory for string on libc heap");
29  memcpy(t,s,l);
30  return t;
31}
32
33static void str_free(char *s)
34{
35  if (!s || s[0]==0)
36    i4_error("trying to free libc str (0)");
37
38  if (i4_show_libc_mallocs)
39    i4_warning("str_free : '%s'", s);
40
41  ::free(s);
42}
43
44#endif
45
46int i4_block_manager_class::valid_ptr(void *ptr)
47{
48  void *next=(void *)(*(((long *)ptr)-1));
49  if (next && next<ptr)                        // small allocation
50  {
51    small_block *s=(small_block *)next;
52    if (s->size<=0) return 0;
53
54    small_block *c=sblocks[s->size];
55    while (c && c!=s) c=c->next;
56    if (!c) return 0;
57    return 1;
58  }
59
60  memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node));
61  memory_node *f=sfirst;
62  while (f && f!=o) f=f->next;
63  if (f) return 1;
64  else return 0;
65}
66
67
68void i4_block_manager_class::inspect()
69{
70  memory_node *f=sfirst;
71  for (;f;f=f->next);               // scan through static big list
72
73  int i,bit=1;
74  for (i=0;i<JM_SMALL_SIZE;i++)
75  {
76    for (small_block *s=sblocks[i];s;s=s->next)
77    {
78      char *addr=((char *)(s+1));
79      bit = 1;
80      for (int j=0;j<32;j++)
81      {
82        if (s->alloc_list&bit)
83        {
84          void *next=(void *)(*(((long *)addr)));
85          if ((long)next!=(long)s)
86          {
87            i4_warning("inspect : bad pointer\n");
88            return;
89          }
90        }
91        bit=bit<<1;
92        addr+=s->size+4;
93      }
94    }
95  }
96}
97
98static char *check_allocation(char *s)
99{
100  char tmp[200];
101  strcpy(tmp,s);
102  ::free(s);
103  s=(char *)::malloc(strlen(tmp)+1);
104  strcpy(s,tmp);
105  return s;
106}
107
108void i4_block_manager_class::report(i4_file_class *fp)
109{
110  fp->printf("************** Block size = %d ***************\n",block_size);
111  int i=0;
112  memory_node *f=sfirst;
113  int f_total=0, a_total=0;
114
115  for (;f;f=f->next,i++)
116  {   
117    fp->printf("%4d   %p (%d) %4d      ",i,f,((char *)f-(char *)sfirst),f->size);
118    if (f->size>0)
119      a_total+=f->size;
120    else
121      f_total+=-f->size;
122
123#ifdef i4_MEM_CHECK
124    if (f->size>0)   
125      fp->printf("%s",check_allocation(f->name));
126    else
127      fp->printf("FREE");
128#endif
129    fp->printf("\n");
130  }   
131  for (i=0;i<JM_SMALL_SIZE;i++)
132  {
133    for (small_block *s=sblocks[i];s;s=s->next)
134    {     
135      fp->printf("*** Small Block size = %d ***\n",i);     
136      unsigned long bit=1;
137      char *addr=((char *)(s+1));
138      for (int j=0;j<32;j++)
139      {
140        fp->printf("%p   ",addr);
141        if (s->alloc_list&bit)
142        {
143#ifdef i4_MEM_CHECK
144          fp->printf("%s\n",check_allocation(s->name[j]));
145#else
146          fp->printf("allocated\n");
147#endif   
148        } else fp->printf("FREE\n");
149        bit=bit<<1;
150        addr+=s->size+4;
151      }
152    }
153  }
154
155  fp->printf("**************** Block summary : %d free, %d allocated\n", f_total, a_total);
156
157}
158
159long i4_block_manager_class::pointer_size(void *ptr)
160{
161  long ret;
162  void *next=(void *)(*(((long *)ptr)-1));
163  if (next>ptr)
164    ret=((memory_node *)(((char *)ptr)-sizeof(memory_node)))->size;
165  else
166    ret=((small_block *)next)->size; 
167
168  return ret;
169}
170
171
172long i4_block_manager_class::largest_free_block()
173{
174  long l=0;
175  memory_node *f;
176  for (f=sfirst;f;f=f->next)
177    if (-f->size>l)
178      l=-f->size;
179
180  return l;
181}
182
183long i4_block_manager_class::available()
184{
185  long size=0;
186  memory_node *f;
187  for (f=sfirst;f;f=f->next)
188    if (f->size<0) size-=f->size;
189
190  return size;
191}
192
193long i4_block_manager_class::allocated()
194{
195  long size=0;
196  memory_node *f;
197  for (f=sfirst;f;f=f->next)
198    if (f->size>0) size+=f->size;
199
200  return size;
201}
202
203void i4_block_manager_class::init(void *block, long Block_size)
204{
205  block_size=Block_size;
206  addr=block;
207  /*
208     I'm padding each block, because I'm comparing pointers against size
209     in jfree to determine weither a pointer is too a small object or a large alloc
210     and it must always be true that the address of the pointer is > JM_SMALL_SIZE
211     All systems I know start pointer address pretty high, but this is a porting consern.     
212  */
213 
214  slast=sfirst=(memory_node *)(((char *)block)+JM_SMALL_SIZE);   
215  sfirst->size=-(block_size-(sw32)sizeof(memory_node)-(sw32)JM_SMALL_SIZE);
216  sfirst->next=NULL;
217  memset(sblocks,0,sizeof(sblocks));
218
219}
220
221void *i4_block_manager_class::alloc(long size, char *name)
222{
223  if (size<JM_SMALL_SIZE)
224  {
225    small_block *s=sblocks[size];
226    for (;s && s->alloc_list==0xffffffff;s=s->next);
227    if (!s)
228    {
229      s=(small_block *)i4_block_manager_class::alloc((size+4)*32+sizeof(small_block),"small_block");
230      if (!s) return NULL;   // not enough room for another small block
231      s->alloc_list=1;
232      s->next=sblocks[size];
233      sblocks[size]=s;
234      s->size=size;
235#ifdef i4_MEM_CHECK
236      s->name[0]=str_alloc(name);
237#endif     
238      long *addr=(long *)(((char *)s)+sizeof(small_block));
239      *addr=(long)s;
240      return (void *)(addr+1);  // return first block
241    } else
242    {
243      int bit=1,i=0;
244      char *addr=((char *)s)+sizeof(small_block);
245      while (1)        // we already know there is a bit free
246      {
247        if ((s->alloc_list&bit)==0)
248        {
249          s->alloc_list|=bit;
250#ifdef i4_MEM_CHECK
251          s->name[i]=str_alloc(name);
252#endif           
253          *((long *)addr)=(long)s;
254
255          return (void *)(addr+4);
256        }
257        i++;
258        bit=bit<<1;
259        addr+=size+4;
260      }     
261    }               
262  }
263
264
265  memory_node *s=sfirst;
266  if (!s) return NULL;
267  for (;s && -s->size<size;s=s->next); 
268  if (!s) return NULL;
269  s->size=-s->size;
270
271  if (s->size-size>sizeof(memory_node)+4)  // is there enough space to split the block?
272  {   
273    memory_node *p=(memory_node *)((char *)s+sizeof(memory_node)+size);
274    if (s==slast)
275      slast=p;
276    p->size=-(s->size-size-(sw32)sizeof(memory_node));
277#ifdef i4_MEM_CLEAR
278    memset( ((memory_node *)p)+1,0,-p->size);
279#endif
280    p->next=s->next;
281    s->next=p;
282    s->size=size;
283  }
284#ifdef i4_MEM_CHECK
285  s->name=str_alloc(name);
286#endif
287  return (void *)(((char *)s)+sizeof(memory_node));
288}
289
290
291int i4_show_frees=0;
292
293/************************** FREE **********************************/
294/*    should be called to free a pointer in the static heap       */
295/*    i.e. begining of the heap                                   */
296/******************************************************************/
297void i4_block_manager_class::free(void *ptr)
298{
299  // see if this was a small_block allocation
300  void *next=(void *)(*(((long *)ptr)-1));
301  if (next && next<ptr)  // small allocation
302  {
303    small_block *s=(small_block *)next;
304    if (s->size<=0)
305    {
306      i4_warning("i4_free : bad pointer\n");
307      return ;
308    }
309#ifdef i4_MEM_CLEAR
310    memset(ptr,0,s->size);
311#endif
312
313    int field=(((char *)ptr)-((char *)s)-sizeof(small_block))/(s->size+4);
314#ifdef i4_MEM_CHECK
315    if (i4_show_frees)
316      i4_warning("small free : %s",s->name[field]);
317    str_free(s->name[field]);
318#endif
319    s->alloc_list&=(0xffffffff-(1<<field));
320    if (s->alloc_list==0)
321    {
322      small_block *l=NULL;
323      small_block *n=sblocks[s->size];
324      for (;n!=s;n=n->next) l=n;
325#ifdef i4_MEM_CHECK
326      if (!n) { i4_warning("Free small block error\n"); }
327#endif
328      if (!l)
329      sblocks[s->size]=s->next;
330      else l->next=s->next;
331      i4_block_manager_class::free(s);
332    }     
333  } else
334  {
335    memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node)),*last=NULL;
336#ifdef i4_MEM_CHECK
337    if (i4_show_frees)
338      i4_warning("big free : %s",o->name);
339    str_free(o->name);
340#endif
341#ifdef i4_MEM_CLEAR
342    memset(ptr,0,o->size);
343#endif
344
345    if (o->next && o->next->size<0)   // see if we can add into next block
346    {
347      if (o->next==slast)
348        slast=o;
349      o->size+=-o->next->size+sizeof(memory_node);
350      o->next=o->next->next;
351    }
352
353    memory_node *n=sfirst;
354    for (;n && n!=o;n=n->next) last=n;
355#ifdef i4_MEM_CHECK
356    if (!n) { i4_warning("Free big block error\n"); }
357#endif
358   
359    if (last && last->size<0)
360    {
361      if (o==slast) {
362        slast=last;
363      }
364      last->next=o->next;
365      last->size-=o->size+sizeof(memory_node); 
366    } else o->size=-o->size;           
367  } 
368}
Note: See TracBrowser for help on using the repository browser.