summaryrefslogtreecommitdiff
path: root/test/spass/memory.h
blob: d0edac187bcc8601aaf2a3ff393a0f5e2986ee71 (plain)
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
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
/**************************************************************/
/* ********************************************************** */
/* *                                                        * */
/* *        DYNAMIC MEMORY MANAGEMENT MODULE                * */
/* *                                                        * */
/* *  $Module:   MEMORY                                     * */ 
/* *                                                        * */
/* *  Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001      * */
/* *  MPI fuer Informatik                                   * */
/* *                                                        * */
/* *  This program is free software; you can redistribute   * */
/* *  it and/or modify it under the terms of the GNU        * */
/* *  General Public License as published by the Free       * */
/* *  Software Foundation; either version 2 of the License, * */
/* *  or (at your option) any later version.                * */
/* *                                                        * */
/* *  This program is distributed in the hope that it will  * */
/* *  be useful, but WITHOUT ANY WARRANTY; without even     * */
/* *  the implied warranty of MERCHANTABILITY or FITNESS    * */
/* *  FOR A PARTICULAR PURPOSE.  See the GNU General Public * */
/* *  License for more details.                             * */
/* *                                                        * */
/* *  You should have received a copy of the GNU General    * */
/* *  Public License along with this program; if not, write * */
/* *  to the Free Software Foundation, Inc., 59 Temple      * */
/* *  Place, Suite 330, Boston, MA  02111-1307  USA         * */
/* *                                                        * */
/* *                                                        * */
/* $Revision: 21527 $                                        * */
/* $State$                                            * */
/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $                             * */
/* $Author: duraid $                                       * */
/* *                                                        * */
/* *             Contact:                                   * */
/* *             Christoph Weidenbach                       * */
/* *             MPI fuer Informatik                        * */
/* *             Stuhlsatzenhausweg 85                      * */
/* *             66123 Saarbruecken                         * */
/* *             Email: weidenb@mpi-sb.mpg.de               * */
/* *             Germany                                    * */
/* *                                                        * */
/* ********************************************************** */
/**************************************************************/


/* $RCSfile$ */


#ifndef _MEMORY_
#define _MEMORY_

/**************************************************************/
/* Includes                                                   */
/**************************************************************/

#include "misc.h"

/**************************************************************/
/* Data structures and constants                              */
/**************************************************************/

#ifndef memory__DYNMAXSIZE
#define memory__DYNMAXSIZE   1024 /* At most blocks of size memory__DYNMAXSIZE
				     bytes are administrated by the
				     module, larger requests are
				     directly mapped to system calls */
#endif

#ifndef memory__SHAREDPAGES
#define memory__SHAREDPAGES    1  /* Number of block sizes sharing an allocated 
				     page. By setting memory__SHAREDPAGES to 4, 
				     the module would administrate requests 
				     for 1, 2, 3 and 4 bytes on the same set of 
				     pages, requests for 5, 6, 7 and 8 on another 
				     one, etc. By default every block size has 
				     its own set of pages */
#endif

#ifndef memory__FREESHREDDER
#define memory__FREESHREDDER  'S' /*  The decimal number 83, which can also be 
				      read as 53 hexadecimal, or the character 
				      'S' in ASCII code */
#endif

#define memory__KILOBYTE        1024

#ifndef memory__DEFAULTPAGESIZE
#define memory__DEFAULTPAGESIZE (8 * memory__KILOBYTE)
                                  /* Used to set the default size of a page. 
				     If the default page size is too small to 
				     contain two objects of size memory__DYNMAXSIZE
				     the default page size is automatically 
				     increased by the function memory_Init */
#endif

#ifndef memory__UNLIMITED
#define memory__UNLIMITED       (-1)
                                  /* Used to set the maximal amount of memory
				     available for the memory module to
				     "unlimited" when calling memory_Init. */
#endif

typedef struct MEMORY_RESOURCEHELP {
  POINTER free;                    /* pointer to the next free block in list  */
  POINTER next;                    /* pointer to the next fresh block         */
  POINTER page;                    /* pointer to head of page list            */
  POINTER end_of_page;             /* pointer to the end of current page      */
  int     total_size;              /* total block size inc. debug marks       */
  int     aligned_size;            /* block size without debug marks          */
  int     offset;                  /* offset of last usable block on page     */
} MEMORY_RESOURCE;

extern MEMORY_RESOURCE * memory_ARRAY[];

#if defined(CHECK)
typedef struct MEMORY_INFOHELP {
  const char * mallocInFile;       /* origin of allocation request:   file    */
  const char * freeInFile;         /* origin of deallocation request: file    */
  unsigned short int mallocAtLine; /* origin of allocation request:   line    */
  unsigned short int freeAtLine;   /* origin of deallocation request: line    */
} MEMORY_INFONODE, * MEMORY_INFO;

#endif

typedef struct MEMORY_BIGBLOCKHEADERHELP {
  struct MEMORY_BIGBLOCKHEADERHELP * previous, * next;
} MEMORY_BIGBLOCKHEADERNODE, * MEMORY_BIGBLOCKHEADER;

extern long                  memory_MAXMEM;

extern unsigned long         memory_NEWBYTES;
extern unsigned long         memory_FREEDBYTES;

extern const unsigned int    memory_MAGICMALLOC;
extern const unsigned int    memory_MAGICFREE;

extern const unsigned int    memory_ALIGN;

extern MEMORY_BIGBLOCKHEADER memory_BIGBLOCKS;

/**************************************************************/
/* Debug Information                                          */
/**************************************************************/

extern unsigned int memory_MARKSIZE;
extern unsigned int memory_OFFSET;

/**************************************************************/
/* Check Functions                                            */
/**************************************************************/

#ifdef __cplusplus
extern "C" {
#endif


#ifdef CHECK
void    memory_CheckFree(POINTER Freepointer, unsigned int Size, unsigned int RealBlockSize, const char * File, unsigned short int Line);
#endif /* CHECK */

#ifdef __cplusplus
}
#endif

/**************************************************************/
/* Inline Functions                                           */
/**************************************************************/


static __inline__ unsigned int memory_CalculateRealBlockSize(unsigned int 
							     BlockSize)
/**********************************************************
  INPUT  : Size of a block of memory.
  RETURNS: its real size.
  SUMMARY: Calculates the size of a memory block, 
           including padding due to memory alignment and
           page sharing
**********************************************************/
{  
  unsigned int RealSize;

  RealSize = BlockSize;

  if (RealSize % memory__SHAREDPAGES) {
    RealSize += memory__SHAREDPAGES - (RealSize % memory__SHAREDPAGES);
  }

  if (RealSize % memory_ALIGN) {
    RealSize += memory_ALIGN - (RealSize % memory_ALIGN);
  }

  return RealSize;

}

static __inline__ unsigned int memory_LookupRealBlockSize(unsigned int 
							  BlockSize)
/**********************************************************
  INPUT  : Size of a block of memory.
  RETURNS: its real size.
  SUMMARY: Returns the size of a memory block, 
           including padding due to memory alignment and
           page sharing.
**********************************************************/
{  

  unsigned int RealSize;

  if (BlockSize < memory__DYNMAXSIZE) {
    RealSize = memory_ARRAY[BlockSize]->aligned_size;
  }
  else {
    RealSize = memory_CalculateRealBlockSize(BlockSize);
  }

  return RealSize;

}

#ifdef CHECK
static __inline__ void memory_SetBlockStatusAndSize(POINTER Mem, 
						    unsigned int Status,
						    unsigned int Size)
/**********************************************************
  INPUT  : a pointer to a block of memory, its status
           (memory_MAGICMALLOC or memory_MAGICFREE), and
           size.
  RETURNS: None.
  SUMMARY: Sets a status flag (memory_MAGICMALLOC or
           memory_MAGICFREE) and block size.
**********************************************************/
{
  *((int *)Mem - 1) = Size; 
  *((int *)((char *)Mem + memory_LookupRealBlockSize(Size))) = Status;
}

static __inline__ unsigned int memory_GetBlockSize(POINTER Mem)
/**********************************************************
  INPUT  : A pointer to a block of memory.
  RETURNS: its size.
  SUMMARY: Returns the size of a memory block.
**********************************************************/
{
  return *((int *)Mem - 1);
}

static __inline__ unsigned int memory_GetRealBlockSize(POINTER Mem)
/**********************************************************
  INPUT  : A pointer to a block of memory.
  RETURNS: its real size.
  SUMMARY: Returns the real size of a memory block,
           including padding bytes.
**********************************************************/
{
  return memory_LookupRealBlockSize(memory_GetBlockSize(Mem));
}

static __inline__ unsigned int memory_GetBlockStatus(POINTER Mem) 
/**********************************************************
  INPUT  : A pointer to a block of memory.
  RETURNS: its status.
  SUMMARY: Returns the status of a memory block.
**********************************************************/
{
  unsigned int Size;

  Size = memory_GetBlockSize(Mem); 

  return  *((int *)((char *)Mem + memory_LookupRealBlockSize(Size)));
}

static __inline__ void memory_SetInfo(MEMORY_INFO Info,
				      const char * MallocInFile,
				      unsigned short int MallocAtLine,
				      const char * FreeInFile,
				      unsigned short int FreeAtLine)
/**********************************************************
  INPUT  : a memory info structure, strings for files where
           the block was allocated and freed, and short 
	   integers for the corresponding lines.
  RETURNS: None.
  SUMMARY: Sets the debugging information for a memory block
**********************************************************/
{
  if (!Info) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In memory_SetInfo:");
    misc_ErrorReport("\n Memory Error. Info is a NULL pointer.\n");
    misc_FinishErrorReport();
  }
 
  Info->mallocAtLine   = MallocAtLine;
  Info->mallocInFile   = MallocInFile;
  Info->freeAtLine     = FreeAtLine;
  Info->freeInFile     = FreeInFile;
}
#endif

static __inline__ unsigned long memory_DemandedBytes(void)
/**********************************************************
  INPUT  : Nothing.
  RETURNS: Maximum number of bytes allocated at the same 
           time by the module.
  SUMMARY: Returns maximum number of allocated bytes at the
           same time.
**********************************************************/
{
  return memory_NEWBYTES;
}


static __inline__ unsigned long memory_UsedBytes(void)
/**********************************************************
  INPUT  : Nothing.
  RETURNS: Number of bytes currently in use by your program.
  SUMMARY: Returns number of bytes currently allocated.
**********************************************************/
{
  return memory_NEWBYTES-memory_FREEDBYTES;
}

#ifdef NO_MEMORY_MANAGEMENT

static __inline__ void memory_Free(POINTER Freepointer, unsigned int Size)
{
  free((char*)Freepointer);
}

#else

#ifdef CHECK
static __inline__ void memory_FreeIntern(POINTER  Freepointer, 
					 unsigned int Size, 
					 const char * File, 
					 unsigned short int Line)
#else
static __inline__ void memory_Free(POINTER Freepointer, unsigned int Size)
#endif
/**********************************************************
  INPUT  : Pointer to the block of memory to be freed, 
           and the block's size
  RETURNS: Nothing.
  SUMMARY: Frees a block of memory for reallocation.
           This function performs correctness checks
	   in debugging mode.
**********************************************************/
{ 
  unsigned int RealBlockSize; /* block´s alignment correct size */

  RealBlockSize = memory_LookupRealBlockSize(Size);

#ifdef CHECK
  memory_CheckFree(Freepointer, Size, RealBlockSize, File, Line);
#endif


  /* Check if current block is a big block */ 
  if (Size >= memory__DYNMAXSIZE) {
    /* if that´s true, remove it from the double linked big block list */
    MEMORY_BIGBLOCKHEADER BigBlockHeader;

    BigBlockHeader = 
      (MEMORY_BIGBLOCKHEADER) ((char *) Freepointer - memory_OFFSET
			       - sizeof(MEMORY_BIGBLOCKHEADERNODE));

    /* Check if current big block is the first block in the list */
    if (BigBlockHeader->previous != NULL) {
      /* if that´s not true, set previous block´s successor
	 to current block´s successor
      */
      BigBlockHeader->previous->next = BigBlockHeader->next;
    }
    else {
      /* otherwise set the first block in the big blocks list
	 to current block´s successor
      */
      memory_BIGBLOCKS = BigBlockHeader->next;
    }

    /* Check if current block is the last block in the list */
    if (BigBlockHeader->next != NULL) {
      /* if that´s not true, set next block´ predecessor to
	 current block´s predecessor 
      */
      BigBlockHeader->next->previous = BigBlockHeader->previous;
    }

    /* Adapt total number of freed bytes 
       and number of bytes available for allocation
       accordingly
    */
    memory_FREEDBYTES       += RealBlockSize + memory_MARKSIZE + 
      sizeof(MEMORY_BIGBLOCKHEADERNODE);

    if (memory_MAXMEM >= 0) {
      memory_MAXMEM           += RealBlockSize + memory_MARKSIZE + 
	sizeof(MEMORY_BIGBLOCKHEADERNODE);
    }

    /* pass the call though to free() with correct pointer value */
#ifdef CHECK
    free((char *)Freepointer - memory_OFFSET 
	 - sizeof(MEMORY_BIGBLOCKHEADERNODE));
#else
    free((char*) Freepointer - sizeof(MEMORY_BIGBLOCKHEADERNODE));
#endif
  }
  else {
    /* current block is not a big block */
    /* Adapt number of allocated bytes 
       and the freed blocks list accordingly 
    */
    memory_FREEDBYTES       += memory_ARRAY[Size]->total_size;
    *(POINTER *)Freepointer  = memory_ARRAY[Size]->free;
    memory_ARRAY[Size]->free = Freepointer;
  }

}

#endif

/**************************************************************/
/* Functions                                                  */
/**************************************************************/

#ifdef __cplusplus
extern "C" {
#endif


void    memory_Init(long);
void    memory_Restrict(long);

void    memory_Print(void);
void    memory_FPrint(FILE*);
  
void    memory_PrintLeaks(void);
void    memory_PrintDetailed(void);
void    memory_PrintAllocatedBlocks(unsigned int Size);
void    memory_PrintFreedBlocks(unsigned int Size);
void    memory_PrintAllocatedBigBlocks(void);
  
void    memory_FreeAllMem(void);

#ifdef __cplusplus
}
#endif

#if defined(CHECK) && !defined(NO_MEMORY_MANAGEMENT)
/* declare drop-in debug versions memory functions */
#ifdef __cplusplus
extern "C" {
#endif
POINTER memory_MallocIntern(unsigned int, const char *, unsigned short int);
POINTER memory_CallocIntern(unsigned int,
			    unsigned int, 
			    const char *, 
			    unsigned short int);
#ifdef __cplusplus
}
#endif
#define memory_Malloc(Size) memory_MallocIntern((Size), __FILE__, __LINE__)
#define memory_Calloc(Elements, Size) \
memory_CallocIntern((Elements), (Size), __FILE__, __LINE__)
#define memory_Free(Pointer, Size) \
memory_FreeIntern((Pointer), (Size), __FILE__, __LINE__)
#else
#ifdef __cplusplus
extern "C" {
#endif
POINTER memory_Malloc(unsigned int);
POINTER memory_Calloc(unsigned int, unsigned int);
#ifdef __cplusplus
}
#endif
#endif

#endif