File: memsubs.c

package info (click to toggle)
libace-perl 1.92-11
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,996 kB
  • sloc: perl: 7,763; ansic: 7,420; makefile: 81
file content (324 lines) | stat: -rw-r--r-- 8,978 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
/*  File: memsubs.c
 *  Author: Richard Durbin (rd@sanger.ac.uk)
 *  Copyright (C) J Thierry-Mieg and R Durbin, 1998
 *-------------------------------------------------------------------
 * This file is part of the ACEDB genome database package, written by
 * 	Richard Durbin (MRC LMB, UK) rd@sanger.ac.uk, and
 *	Jean Thierry-Mieg (CRBM du CNRS, France) mieg@kaa.cnrs-mop.fr
 *
 * Description:
 * Exported functions:
 * HISTORY:
 * Last edited: Dec  4 11:24 1998 (fw)
 * Created: Thu Aug 20 16:54:55 1998 (rd)
 *-------------------------------------------------------------------
 */

/* define MALLOC_CHECK here to check mallocs - also in regular.h */

#include "regular.h"

#if defined(NEXT) || defined(HP) || defined(MACINTOSH) 
extern void* malloc(mysize_t size) ;
#elif !defined(WIN32) && !defined(DARWIN)
#include <malloc.h>   /* normal machines  */
#endif

/********** primary type definition **************/

typedef struct _STORE_HANDLE_STRUCT {
  STORE_HANDLE next ;	/* for chaining together on Handles */
  STORE_HANDLE back ;	/* to unchain */
  void (*final)(void*) ;	/* finalisation routine */
  int size ;			/* of user memory to follow */
#ifdef MALLOC_CHECK
  int check1 ;			/* set to known value */
#endif
} STORE_HANDLE_STRUCT ;

/*********************************************************************/
/********** memory allocation - messalloc() and handles  *************/

static int numMessAlloc = 0 ;
static int totMessAlloc = 0 ;


  /* Calculate to size of an STORE_HANDLE_STRUCT rounded to the nearest upward
     multiple of sizeof(double). This avoids alignment problems when
     we put an STORE_HANDLE_STRUCT at the start of a memory block */

#define STORE_OFFSET ((((sizeof(STORE_HANDLE_STRUCT)-1)/MALLOC_ALIGNMENT)+1)\
                             * MALLOC_ALIGNMENT)


  /* macros to convert between a void* and the corresponding STORE_HANDLE */

#define toAllocUnit(x) (STORE_HANDLE) ((char*)(x) - STORE_OFFSET)
#define toMemPtr(unit)((void*)((char*)(unit) + STORE_OFFSET))

#ifdef MALLOC_CHECK
BOOL handlesInitialised = FALSE;
static Array handles = 0 ;

  /* macro to give the terminal check int for an STORE_HANDLE_STRUCT */
  /* unit->size must be a multiple of sizeof(int) */
#define check2(unit)  *(int*)(((char*)toMemPtr(unit)) + (unit)->size)

static void checkUnit (STORE_HANDLE unit) ;
static int handleOrder (void *a, void  *b)
{ return (*((STORE_HANDLE *)a) == *((STORE_HANDLE *)b)) ? 0 : 
	  (*((STORE_HANDLE *)a) > *((STORE_HANDLE *)b)) ? 1 : -1 ;
}
#endif
#if defined(MALLOC_CHECK) || defined(MEM_DEBUG)
STORE_HANDLE_STRUCT handle0 ;
#endif

/************** halloc(): key function - messalloc() calls this ****************/

#ifdef MEM_DEBUG
void *halloc_dbg(int size, STORE_HANDLE handle,const char *hfname, int hlineno) 
#else
void *halloc(int size, STORE_HANDLE handle)
#endif
{ 
  STORE_HANDLE unit ;
  
#ifdef MALLOC_CHECK
  if (!handlesInitialised)		/* initialise */
    { handlesInitialised = TRUE;
      /* BEWARE, arrayCreate calls handleAlloc, line above must precede
         following line to avoid infinite recursion */
      handles = arrayCreate (16, STORE_HANDLE) ;
      array (handles, 0, STORE_HANDLE) = &handle0 ;
      handle0.next = 0 ;
    }

  while (size % INT_ALIGNMENT) size++ ; /* so check2 alignment is OK */
  unit = (STORE_HANDLE) malloc(STORE_OFFSET + size + sizeof(int)) ;
  if (unit) memset (unit, 0, STORE_OFFSET + size + sizeof(int)) ;
#else
  unit = (STORE_HANDLE) malloc(STORE_OFFSET + size) ;
  if (unit) memset (unit, 0, STORE_OFFSET + size) ;
#endif

  if (!unit)			/* out of memory -> messcrash */
    {
      messcrash (
 "Memory allocation failure when requesting %d bytes, %d already allocated", 
  size, totMessAlloc) ;
    }
#if defined(MALLOC_CHECK) || defined(MEM_DEBUG)
  if (!handle)
    handle = &handle0 ;
#endif
  if (handle) 
    { unit->next = handle->next ;
      unit->back = handle ;
      if (handle->next) (handle->next)->back = unit ;
      handle->next = unit ;
    }

  unit->size = size ;
#ifdef MALLOC_CHECK
  unit->check1 = 0x12345678 ;
  check2(unit) = 0x12345678 ;
#endif

  ++numMessAlloc ;
  totMessAlloc += size ;

  return toMemPtr(unit) ;
}

void blockSetFinalise(void *block, void (*final)(void *))
{ STORE_HANDLE unit = toAllocUnit(block);
  unit->final = final ;
}  

/***** handleAlloc() - does halloc() + blockSetFinalise() - archaic *****/

#ifdef MEM_DEBUG
void *handleAlloc_dbg (void (*final)(void*), STORE_HANDLE handle, int size,
		   const char *hfname, int hlineno)
{
  void *result = halloc_dbg(size, handle, hfname, hlineno) ;
#else
void *handleAlloc (void (*final)(void*), STORE_HANDLE handle, int size)
{
  void *result = halloc(size, handle);
#endif
  if (final) 
    blockSetFinalise(result, final);

  return result;
}

/****************** useful utility ************/

#ifdef MEM_DEBUG
char *strnew_dbg(char *old, STORE_HANDLE handle, const char *hfname, int hlineno)
{ char *result = 0 ;
  if (old)
    { result = (char *)halloc_dbg(1+strlen(old), handle, hfname, hlineno) ;
#else
char *strnew(char *old, STORE_HANDLE handle)
{ char *result = 0 ;
  if (old)
    { result = (char *)halloc(1+strlen(old), handle);
#endif
      strcpy(result, old);
    }
  return result;
}

/****************** messfree ***************/

void umessfree (void *cp)
{
  STORE_HANDLE unit = toAllocUnit(cp) ;

#ifdef MALLOC_CHECK
  checkUnit (unit) ;
  unit->check1 = 0x87654321; /* test for double free */
#endif

  if (unit->final)
    (*unit->final)(cp) ;

  if (unit->back) 
    { (unit->back)->next = unit->next;
      if (unit->next) (unit->next)->back = unit->back;
    }
  
  --numMessAlloc ;
  totMessAlloc -= unit->size ;
  free (unit) ;
}

/************** create and destroy handles **************/

/* NOTE: handleDestroy is #defined in regular.h to be messfree */
/* The actual work is done by handleFinalise, which is the finalisation */
/* routine attached to all STORE_HANDLEs. This allows multiple levels */
/* of free-ing by allocating new STORE_HANDLES on old ones, using */
/* handleHandleCreate. handleCreate is simply defined as handleHandleCreate(0) */

static void handleFinalise (void *p)
{
  STORE_HANDLE handle = (STORE_HANDLE)p;
  STORE_HANDLE next, unit = handle->next ;

/* do handle finalisation first */  
  if (handle->final)
    (*handle->final)((void *)handle->back);

      while (unit)
    { 
#ifdef MALLOC_CHECK
      checkUnit (unit) ;
      unit->check1 = 0x87654321; /* test for double free */
#endif
      if (unit->final)
	(*unit->final)(toMemPtr(unit)) ;
      next = unit->next ;
      --numMessAlloc ;
      totMessAlloc -= unit->size ;
      free (unit) ;
      unit = next ;
    }

#ifdef MALLOC_CHECK
  arrayRemove (handles, &p, handleOrder) ;
#endif

/* This is a finalisation routine, the actual store is freed in messfree,
   or another invokation of itself. */
}
  
void handleSetFinalise(STORE_HANDLE handle, void (*final)(void *), void *arg)
{ handle->final = final;
  handle->back = (STORE_HANDLE)arg;
}

STORE_HANDLE handleHandleCreate(STORE_HANDLE handle)
{ 
  STORE_HANDLE res = (STORE_HANDLE) handleAlloc(handleFinalise, 
						handle,
						sizeof(STORE_HANDLE_STRUCT));
#ifdef MALLOC_CHECK
  /* NB call to handleAlloc above ensures that handles is initialised here */
  arrayInsert (handles, &res, handleOrder) ;
#endif
  res->next = res->back = 0 ; /* No blocks on this handle yet. */
  res->final = 0 ; /* No handle finalisation */
  return res ;
}

BOOL finalCleanup = FALSE ;
#ifdef MEM_DEBUG
void handleCleanUp (void) 
{ finalCleanup = TRUE ;
  handleFinalise ((void *)&handle0) ;
}
#endif

/************** checking functions, require MALLOC_CHECK *****/

#ifdef MALLOC_CHECK
static void checkUnit (STORE_HANDLE unit)
{
  if (unit->check1 == 0x87654321)
    messerror ("Block at %x freed twice - bad things will happen.",
	       toMemPtr(unit));
  else
    if (unit->check1 != 0x12345678)
      messerror ("Malloc error at %x length %d: "
		 "start overwritten with %x",
		 toMemPtr(unit), unit->size, unit->check1) ;
  
  if (check2(unit) != 0x12345678)
    messerror ("Malloc error at %x length %d: "
	       "end overwritten with %x",
	       toMemPtr(unit), unit->size, check2(unit)) ;
}

void messalloccheck (void)
{
  int i ;
  STORE_HANDLE unit ;

  if (!handles) return ;

  for (i = 0 ; i < arrayMax(handles) ; ++i) 
    for (unit = arr(handles,i,STORE_HANDLE)->next ; unit ; unit=unit->next)
      checkUnit (unit) ;
}
#else
void messalloccheck (void) {}
#endif

/******************* status monitoring functions ******************/

void handleInfo (STORE_HANDLE handle, int *number, int *size)
{
  STORE_HANDLE unit = handle->next;

  *number = 0;
  *size = 0;

  while (unit)
    { ++*number ;
      *size += unit->size ;
      unit = unit->next ;
    }
}

int messAllocStatus (int *mem)
{ 
  *mem = totMessAlloc ;
  return numMessAlloc ;
}

/*************************** end of file ************************/
/****************************************************************/