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