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
|
/*-----------------------------------------------------------------------
File : clb_memory.h
Author: Stephan Schulz
This module implements simple general purpose memory management
routines that is efficient for problems with a very regular memory
access pattern (like most theorem provers). In addition to the
groundwork it also implements secure versions of standard functions
making use of memory allocation.
Copyright 1998-2017 by the author.
This code is released under the GNU General Public Licence and
the GNU Lesser General Public License.
See the file COPYING in the main E directory for details..
Run "eprover -h" for contact information.
Changes
Created: Wed Aug 13 21:56:20 MET DST 1997
-----------------------------------------------------------------------*/
#ifndef CLB_MEMORY
#define CLB_MEMORY
#ifdef USE_NEWMEM
#include "clb_newmem.h"
#else
#include "clb_verbose.h"
#include "clb_os_wrapper.h"
/*---------------------------------------------------------------------*/
/* Data type declarations */
/*---------------------------------------------------------------------*/
/* Administrate deallocated memory blocks */
typedef struct memcell
{
struct memcell* next;
#ifndef NDEBUG
unsigned long test;
#endif
}MemCell, *Mem_p;
/*---------------------------------------------------------------------*/
/* Exported Functions and Variables */
/*---------------------------------------------------------------------*/
#define MEM_ARR_SIZE 8192
#define MEM_ARR_MIN_INDEX sizeof(MemCell)
#define MEM_FREE_PATTERN 0xFAFBFAFA
#define MEM_RSET_PATTERN 0x00000000
extern bool MemIsLow;
extern Mem_p free_mem_list[]; /* Exported for use by inline
* functions/Macros */
static inline void* SizeMallocReal(size_t size);
static inline void SizeFreeReal(void* junk, size_t size);
/* For estimating the real memory consumption of a data type - the
default may be way off for some memory managers, but should be
reasonably ok for many situations. If CONSTANT_MEM_ESTIMATE is on,
a very rough but machine-independent estimate is used. */
#ifdef CONSTANT_MEM_ESTIMATE
#define MEMSIZE(type) "There is a bug in the code! Everything has to work with constants."
#else
#define MEMSIZE(type) (sizeof(type)+sizeof(void*))
#endif
#ifdef USE_SYSTEM_MEM
#ifndef NDEBUG
#define SizeFree(junk, size) free(junk); junk=NULL
#define SizeMalloc(size) malloc(size)
#define ENSURE_NULL(junk) junk=NULL
#else
#define SizeFree(junk, size) free(junk)
#define SizeMalloc(size) malloc(size)
#define ENSURE_NULL(junk) /* Only defined in debug mode */
#endif
#else
#ifndef NDEBUG
#define SizeFree(junk, size) SizeFreeReal(junk, size); junk=NULL
#define SizeMalloc(size) SizeMallocReal(size)
#define ENSURE_NULL(junk) junk=NULL
#else
#define SizeFree(junk, size) SizeFreeReal(junk, size);
#define SizeMalloc(size) SizeMallocReal(size)
#define ENSURE_NULL(junk) /* Only defined in debug mode */
#endif
#endif
void MemFlushFreeList(void);
void* SecureMalloc(size_t size);
void* SecureRealloc(void *ptr, size_t size);
char* SecureStrdup(const char* source);
char* SecureStrndup(const char* source, size_t n);
#define FREE(junk) assert(junk);free(junk); junk=NULL
long* IntArrayAlloc(int size);
#define IntArrayFree(array, size) SizeFree(array, size*sizeof(long))
#ifdef CLB_MEMORY_DEBUG
void MemDebugPrintStats(FILE* out);
extern long size_malloc_mem;
extern long size_malloc_count;
extern long size_free_mem;
extern long size_free_count;
extern long clb_free_count;
extern long secure_malloc_count;
extern long secure_malloc_mem;
extern long secure_realloc_count;
extern long secure_realloc_m_count;
extern long secure_realloc_f_count;
void MemFreeListPrint(FILE* out);
#undef FREE
#define FREE(junk) assert(junk); clb_free_count++; free(junk); junk=NULL
#endif
#ifdef CLB_MEMORY_DEBUG2
#undef FREE
#define FREE(junk) assert(junk); clb_free_count++; printf("\nBlock %p F:\n", junk); \
free(junk); junk=NULL
#endif
/*-------------------------------------------------------------------------
If you want to have a special Allocator and Deallocator for a
datatype just copy the following templates to your .h-file and fill
them in... The allocated structures will not be initialized - you
need to write a function built on top of the macros if you want more
functionality in you Allocator.
#define DataCellAlloc() (DataCell*)SizeMalloc(sizeof(DataCell))
#define DataCellFree(junk) SizeFree(junk, sizeof(DataCell))
-------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------
//
// Function: SizeMallocReal()
//
// Returns a block of memory sized size using the internal
// free-list. This block is freeable with free(), and in all
// respects behaves like a normal malloc'ed block.
//
// Global Variables: free_mem_list[]
//
// Side Effects : Memory operations
//
/----------------------------------------------------------------------*/
static inline void* SizeMallocReal(size_t size)
{
Mem_p handle;
if(size>=MEM_ARR_MIN_INDEX && size<MEM_ARR_SIZE && free_mem_list[size])
{
assert(free_mem_list[size]->test == MEM_FREE_PATTERN);
assert((free_mem_list[size]->test = MEM_RSET_PATTERN, true));
handle = free_mem_list[size];
free_mem_list[size] = free_mem_list[size]->next;
}
else
{
handle = SecureMalloc(size);
#ifndef NDEBUG
if(size>=MEM_ARR_MIN_INDEX && size<MEM_ARR_SIZE)
{
assert((handle->test = MEM_RSET_PATTERN, true));
}
#endif
}
#ifdef CLB_MEMORY_DEBUG
size_malloc_mem+=size;
size_malloc_count++;
#endif
#ifdef CLB_MEMORY_DEBUG2
printf("\nBlock %p A: size %zd\n", handle, size);
#endif
return handle;
}
/*-----------------------------------------------------------------------
//
// Function: SizeFreeReal()
//
// Returns a block sized size. Note: size has to be exact - you
// should only give blocks to SizeFree() that have been allocated
// with malloc(size) or SizeMalloc(size). Giving blocks that are to
// big wastes memory, blocks that are to small will result in more
// serious trouble (segmentation faults).
//
// Global Variables: free_mem_list[]
//
// Side Effects : Memory operations
//
/----------------------------------------------------------------------*/
static inline void SizeFreeReal(void* junk, size_t size)
{
assert(junk!=NULL);
#ifdef CLB_MEMORY_DEBUG2
printf("\nBlock %p D: size %zd\n", junk, size);
#endif
if(size>=MEM_ARR_MIN_INDEX && size<MEM_ARR_SIZE)
{
((Mem_p)junk)->next = free_mem_list[size];
free_mem_list[size] = (Mem_p)junk;
assert(free_mem_list[size]->test != MEM_FREE_PATTERN);
assert((free_mem_list[size]->test = MEM_FREE_PATTERN));
}
else
{
FREE(junk);
}
#ifdef CLB_MEMORY_DEBUG
size_free_mem+=size;
size_free_count++;
#endif
}
#endif
#endif
/*---------------------------------------------------------------------*/
/* End of File */
/*---------------------------------------------------------------------*/
|