1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 /****************************************************************************/
4 /* */
5 /* File: heaps.c */
6 /* */
7 /* Purpose: low-level memory management for ug 2.0 */
8 /* */
9 /* Author: Peter Bastian/Henrik Rentz-Reichert */
10 /* Institut fuer Computeranwendungen III */
11 /* Universitaet Stuttgart */
12 /* Pfaffenwaldring 27 */
13 /* 70569 Stuttgart */
14 /* email: ug@ica3.uni-stuttgart.de */
15 /* */
16 /* History: 29.01.92 begin, ug version 2.0 */
17 /* 02.02.95 begin, ug version 3.0 */
18 /* */
19 /* Revision: 04.09.95 */
20 /* */
21 /****************************************************************************/
22
23 /****************************************************************************/
24 /* */
25 /* include files in the order */
26 /* system include files */
27 /* application include files */
28 /* */
29 /****************************************************************************/
30
31 #include <config.h>
32
33 #include <cstdlib>
34 #include <cstddef>
35 #include <cstring>
36 #include <cassert>
37 #include <cstdio>
38
39 #include "ugtypes.h"
40 #include "architecture.h"
41 #include "heaps.h"
42 #include "misc.h"
43 #include "debug.h"
44 #include <dune/uggrid/ugdevices.h>
45
46 #include "namespace.h"
47 USING_UG_NAMESPACE
48
49 /****************************************************************************/
50 /* */
51 /* defines in the following order */
52 /* */
53 /* compile time constants defining static data size (i.e. arrays) */
54 /* other constants */
55 /* macros */
56 /* */
57 /****************************************************************************/
58
59 #define FLOOR(n) ((n)&ALIGNMASK) /* lower next multiple of four */
60 #define CEIL(n) ((n)+((ALIGNMENT-((n)&(ALIGNMENT-1)))&(ALIGNMENT-1)))
61
62
63 /* defines and macros for the virtual heap management */
64
65 #define B_OFFSET(bhm,i) ((bhm)->BlockDesc[i].offset)
66 #define B_SIZE(bhm,i) ((bhm)->BlockDesc[i].size)
67 #define B_ID(bhm,i) ((bhm)->BlockDesc[i].id)
68
69 #define CALC_B_OFFSET(bhm,i) (((i)==0) ? 0 : (B_OFFSET(theVHM,(i)-1)+B_SIZE(theVHM,(i)-1)))
70
71 /****************************************************************************/
72 /** \brief Install a new heap structure
73
74 \param type - type of heap
75 \param size - size of new heap in bytes
76 \param buffer - 4-aligned memory for the heap
77
78 This function installs a new heap structure.
79 Valid 'type' is either 'SIMPLE_HEAP' or 'GENERAL_HEAP'.
80 The allocation of memory starts at the address given by
81 '*buffer' and is of 'size' bytes.
82
83 \return <ul>
84 <li> pointer to HEAP </li>
85 <li> NULL if not enough space available </li>
86 </ul>
87 */
88 /****************************************************************************/
89
NewHeap(enum HeapType type,MEM size,void * buffer)90 HEAP *NS_PREFIX NewHeap (enum HeapType type, MEM size, void *buffer)
91 {
92 HEAP *theHeap;
93
94 /* check size */
95 if (buffer==NULL) return(NULL);
96 if (size<MIN_HEAP_SIZE) return(NULL);
97
98 /* initialize heap structure */
99 theHeap = (HEAP *) buffer;
100 theHeap->type = type;
101 theHeap->size = size;
102 theHeap->markKey = 0;
103
104 /* No constructor is ever called for theHeap. Consequently, no constructor
105 * has been called for its member markedMemory, either. Here we force this
106 * constructor call using placement new. */
107 new(theHeap->markedMemory) std::vector<void*>[MARK_STACK_SIZE+1];
108
109 /* return heap structure */
110 return(theHeap);
111 }
112
113 /****************************************************************************/
114 /** \brief Clean up and deallocate a heap structure
115
116 \param theHeap The heap to be deallocated
117
118 This method properly cleans up a HEAP data structure, and then frees the
119 memory.
120 */
121 /****************************************************************************/
122
123
124
DisposeHeap(HEAP * theHeap)125 void NS_PREFIX DisposeHeap (HEAP *theHeap)
126 {
127 if (theHeap != NULL) {
128 /* When using the system heap, the HEAP data structure contains an array of
129 * std::vectors, which have all be created using placement new. Therefore,
130 * before freeing the memory of a HEAP we have to call the destructors of
131 * these std::vectors explicitly. Otherwise we get memory leaks.
132 */
133 using namespace std;
134 for (INT i=0; i<MARK_STACK_SIZE; i++)
135 theHeap->markedMemory[i].~vector<void*>();
136
137 free(theHeap);
138 }
139 }
140
141 /****************************************************************************/
142 /** \brief Allocate memory from heap
143
144 \param theHeap - heap structure which manages memory allocation
145 \param n - number of bytes to allocate
146
147 this function now only forwards to `malloc`.
148 */
GetMem(HEAP * theHeap,MEM n)149 void *NS_PREFIX GetMem (HEAP *theHeap, MEM n)
150 {
151 return malloc(n);
152 }
153
154 /****************************************************************************/
155 /** \brief Allocate memory and register it for rollback
156
157 \param theHeap - heap structure which manages memory allocation
158 \param n - number of bytes to allocate
159 \param key - key with which we can identify the rollback record
160
161 this function allocates memory on the heap and tags it with the `key`.
162 */
GetTmpMem(HEAP * theHeap,MEM n,INT key)163 void *NS_PREFIX GetTmpMem (HEAP *theHeap, MEM n, INT key)
164 {
165 if (theHeap->type==SIMPLE_HEAP)
166 {
167 ASSERT(key == theHeap->markKey);
168 /* we have to keep track of allocated memory, in order to do a proper rollback */
169 void* ptr = GetMem(theHeap,n);
170 theHeap->markedMemory[key].push_back(ptr);
171 return theHeap->markedMemory[key].back();
172 }
173 /* no key for GENERAL_HEAP */
174 return (GetMem(theHeap,n));
175 }
176
177 /****************************************************************************/
178 /** \brief Free memory previously allocated from that heap
179
180 \param theHeap - heap structure which manages memory allocation
181 \param buffer - memory area previously allocated
182
183 This function creates free memory previously allocated from that heap.
184 */
185 /****************************************************************************/
186
DisposeMem(HEAP * theHeap,void * buffer)187 void NS_PREFIX DisposeMem (HEAP *theHeap, void *buffer)
188 {
189 free(buffer);
190 }
191
192 /****************************************************************************/
193 /** \copydoc Allocate memory from heap
194
195 \param theHeap - heap structure which manages memory allocation
196 \param size - number of bytes to allocate
197
198 \note the allocated memory is initialized to zero
199
200 \return pointer to an object of the requested size
201 */
202 /****************************************************************************/
203
GetFreelistMemory(HEAP * theHeap,INT size)204 void *NS_PREFIX GetFreelistMemory (HEAP *theHeap, INT size)
205 {
206 void* obj = malloc(size);
207
208 if (obj != NULL)
209 memset(obj,0,size);
210
211 return(obj);
212 }
213
214 /****************************************************************************/
215 /** \brief Mark heap position for future release
216
217 \param theHeap - heap to mark
218
219 This function marks heap position for future release. Only valid in
220 the 'SIMPLE_HEAP' type.
221
222 \return <ul>
223 <li> 0 if OK </li>
224 <li> 1 if mark stack full or wrong heap type </li>
225 </ul>
226 */
227 /****************************************************************************/
228
MarkTmpMem(HEAP * theHeap,INT * key)229 INT NS_PREFIX MarkTmpMem (HEAP *theHeap, INT *key)
230 {
231 assert(theHeap->type==SIMPLE_HEAP);
232 if (theHeap->type!=SIMPLE_HEAP) return(1);
233
234 if(theHeap->markKey >= MARK_STACK_SIZE)
235 return 1;
236 theHeap->markKey++;
237 *key = theHeap->markKey;
238 return 0;
239 }
240
241 /****************************************************************************/
242 /** \brief Release to next stack position
243
244 \param theHeap - heap to release
245
246 This function releases to the next stack position. Only valid in the
247 'SIMPLE_HEAP' type.
248
249 \return <ul>
250 <li> 0 if OK </li>
251 <li> 1 if mark stack empty or wrong heap type. </li>
252 </ul>
253 */
254 /****************************************************************************/
255
ReleaseTmpMem(HEAP * theHeap,INT key)256 INT NS_PREFIX ReleaseTmpMem (HEAP *theHeap, INT key)
257 {
258 if (theHeap->type!=SIMPLE_HEAP) return 1;
259
260 if (theHeap->markKey == 0) return 0;
261 if (key > theHeap->markKey) return 1;
262
263 /* Free all memory associated to 'key' */
264 for (void* ptr : theHeap->markedMemory[key])
265 free(ptr);
266 theHeap->markedMemory[key].resize(0);
267
268 if (key < theHeap->markKey) return 2;
269 while (theHeap->markKey > 0 && theHeap->markedMemory[theHeap->markKey].size() == 0)
270 theHeap->markKey--;
271
272 return 0;
273 }
274