| rev |
line source |
|
Me@50
|
1 /*
|
|
Me@50
|
2 * Copyright 2009 OpenSourceCodeStewardshipFoundation.org
|
|
Me@50
|
3 * Licensed under GNU General Public License version 2
|
|
Me@50
|
4 *
|
|
Me@50
|
5 * Author: seanhalle@yahoo.com
|
|
Me@50
|
6 *
|
|
Me@50
|
7 * Created on November 14, 2009, 9:07 PM
|
|
Me@50
|
8 */
|
|
Me@50
|
9
|
|
Me@50
|
10 #include <malloc.h>
|
|
msach@76
|
11 #include <inttypes.h>
|
|
Me@53
|
12 #include <stdlib.h>
|
|
msach@76
|
13 #include <stdio.h>
|
|
msach@101
|
14 #include <string.h>
|
|
msach@101
|
15 #include <math.h>
|
|
Me@50
|
16
|
|
Me@50
|
17 #include "VMS.h"
|
|
Me@68
|
18 #include "Histogram/Histogram.h"
|
|
Me@50
|
19
|
|
msach@102
|
20 //A MallocProlog is a head element if the HigherInMem variable is NULL
|
|
msach@102
|
21 //A Chunk is free if the prevChunkInFreeList variable is NULL
|
|
msach@102
|
22
|
|
msach@101
|
23 /*
|
|
msach@101
|
24 * This calculates the container which fits the given size.
|
|
Me@50
|
25 */
|
|
msach@101
|
26 inline
|
|
msach@101
|
27 uint32 getContainer(size_t size)
|
|
msach@101
|
28 {
|
|
msach@102
|
29 return (log10(size)-LOG128)/LOG54;
|
|
msach@101
|
30 }
|
|
msach@101
|
31
|
|
msach@101
|
32 /*
|
|
msach@101
|
33 * This calculates the size of a given container
|
|
msach@101
|
34 */
|
|
msach@101
|
35 inline
|
|
msach@101
|
36 size_t getContainerSize(uint32 idx)
|
|
msach@101
|
37 {
|
|
msach@101
|
38 return pow(CHUNK_INCREASE_RATE,idx)*LOWER_BOUND;
|
|
msach@101
|
39 }
|
|
msach@101
|
40
|
|
msach@101
|
41 /*
|
|
msach@101
|
42 * Removes the first chunk of a freeList
|
|
msach@101
|
43 * The chunk is removed but not set as free. There is no check if
|
|
msach@101
|
44 * the free list is empty, so make sure this is not the case.
|
|
msach@101
|
45 */
|
|
msach@101
|
46 inline
|
|
msach@101
|
47 MallocProlog *removeChunk(MallocProlog** container)
|
|
msach@101
|
48 {
|
|
msach@101
|
49 MallocProlog *removedChunk = *container;
|
|
msach@101
|
50 *container = removedChunk->nextChunkInFreeList;
|
|
msach@101
|
51
|
|
msach@101
|
52 if(removedChunk->nextChunkInFreeList)
|
|
msach@101
|
53 removedChunk->nextChunkInFreeList->prevChunkInFreeList =
|
|
msach@101
|
54 (MallocProlog*)container;
|
|
msach@101
|
55
|
|
msach@101
|
56 return removedChunk;
|
|
msach@101
|
57 }
|
|
msach@101
|
58
|
|
msach@102
|
59 inline
|
|
msach@102
|
60 void recycleSmallChunks(MallocProlog** container)
|
|
msach@102
|
61 {
|
|
msach@102
|
62 //TODO recycle small chunks
|
|
msach@102
|
63 }
|
|
msach@102
|
64
|
|
msach@101
|
65 /*
|
|
msach@101
|
66 * Removes a chunk from a free list.
|
|
msach@101
|
67 */
|
|
msach@101
|
68 inline
|
|
msach@102
|
69 void extractChunk(MallocProlog* chunk)
|
|
msach@101
|
70 {
|
|
msach@102
|
71 chunk->prevChunkInFreeList->nextChunkInFreeList = chunk->nextChunkInFreeList;
|
|
msach@102
|
72 if(chunk->nextChunkInFreeList)
|
|
msach@102
|
73 chunk->nextChunkInFreeList->prevChunkInFreeList = chunk->prevChunkInFreeList;
|
|
msach@101
|
74 }
|
|
msach@101
|
75
|
|
msach@101
|
76 /*
|
|
msach@101
|
77 * Merges two chunks.
|
|
msach@102
|
78 * Chunk A has to be before chunk B in memory. Both have to be removed from
|
|
msach@102
|
79 * a free list
|
|
msach@101
|
80 */
|
|
msach@101
|
81 inline
|
|
msach@101
|
82 MallocProlog *mergeChunks(MallocProlog* chunkA, MallocProlog* chunkB)
|
|
msach@101
|
83 {
|
|
msach@102
|
84 chunkA->nextHigherInMem = chunkB->nextHigherInMem;
|
|
msach@102
|
85 return chunkA;
|
|
msach@101
|
86 }
|
|
msach@101
|
87 /*
|
|
msach@101
|
88 * Inserts a chunk into a free list.
|
|
msach@101
|
89 */
|
|
msach@101
|
90 inline
|
|
msach@101
|
91 void insertChunk(MallocProlog* chunk, MallocProlog** container)
|
|
msach@101
|
92 {
|
|
msach@101
|
93 chunk->nextChunkInFreeList = *container;
|
|
msach@101
|
94 chunk->prevChunkInFreeList = (MallocProlog*)container;
|
|
msach@101
|
95 if(*container)
|
|
msach@101
|
96 (*container)->prevChunkInFreeList = chunk;
|
|
msach@101
|
97 *container = chunk;
|
|
msach@101
|
98 }
|
|
msach@101
|
99
|
|
msach@101
|
100 /*
|
|
msach@101
|
101 * Divides the chunk that a new chunk of newSize is created.
|
|
msach@101
|
102 * There is no size check, so make sure the size value is valid.
|
|
msach@101
|
103 */
|
|
msach@101
|
104 inline
|
|
msach@101
|
105 MallocProlog *divideChunk(MallocProlog* chunk, size_t newSize)
|
|
msach@101
|
106 {
|
|
msach@101
|
107 MallocProlog* newChunk = (MallocProlog*)((uintptr_t)chunk->nextHigherInMem -
|
|
msach@101
|
108 newSize - sizeof(MallocProlog));
|
|
msach@101
|
109
|
|
msach@101
|
110 newChunk->nextLowerInMem = chunk;
|
|
msach@101
|
111 newChunk->nextHigherInMem = chunk->nextHigherInMem;
|
|
msach@101
|
112
|
|
msach@101
|
113 chunk->nextHigherInMem = newChunk;
|
|
msach@101
|
114 chunk->nextHigherInMem->nextLowerInMem = newChunk;
|
|
msach@101
|
115
|
|
msach@101
|
116 return newChunk;
|
|
msach@101
|
117 }
|
|
msach@101
|
118
|
|
msach@101
|
119 inline
|
|
msach@101
|
120 size_t getChunkSize(MallocProlog* chunk)
|
|
msach@101
|
121 {
|
|
msach@101
|
122 return (uintptr_t)chunk->nextHigherInMem -
|
|
msach@101
|
123 (uintptr_t)chunk - sizeof(MallocProlog);
|
|
msach@101
|
124 }
|
|
msach@101
|
125
|
|
msach@102
|
126
|
|
msach@102
|
127 /*
|
|
msach@102
|
128 * This makes 5 Chunks of the requested size.
|
|
msach@102
|
129 */
|
|
msach@102
|
130 inline
|
|
msach@102
|
131 void makeChunks(size_t size, MallocProlog **container)
|
|
msach@102
|
132 {
|
|
msach@102
|
133 MallocArrays *freeLists = _VMSMasterEnv->freeLists;
|
|
msach@102
|
134 size_t addedSize = 5*(size + sizeof(MallocProlog));
|
|
msach@102
|
135
|
|
msach@102
|
136 uint32 containerIdx = getContainer(addedSize)+4;
|
|
msach@102
|
137 while(freeLists->bigChunks[containerIdx] == NULL )
|
|
msach@102
|
138 containerIdx++;
|
|
msach@102
|
139
|
|
msach@102
|
140 MallocProlog *foundChunk = removeChunk(&freeLists->bigChunks[containerIdx]);
|
|
msach@102
|
141
|
|
msach@102
|
142 int i;
|
|
msach@102
|
143 for(i=0; i<5; i++)
|
|
msach@102
|
144 {
|
|
msach@102
|
145 insertChunk(divideChunk(foundChunk,size), container);
|
|
msach@102
|
146 }
|
|
msach@102
|
147 containerIdx = getContainer(getChunkSize(foundChunk));
|
|
msach@102
|
148 insertChunk(foundChunk, &freeLists->bigChunks[containerIdx]);
|
|
msach@102
|
149 }
|
|
msach@102
|
150
|
|
msach@101
|
151 /*
|
|
msach@101
|
152 * This is sequential code, meant to only be called from the Master, not from
|
|
msach@101
|
153 * any slave VPs.
|
|
msach@101
|
154 */
|
|
msach@101
|
155 void *VMS__malloc( size_t sizeRequested )
|
|
msach@101
|
156 {
|
|
msach@101
|
157 //============================= MEASUREMENT STUFF ========================
|
|
msach@101
|
158 #ifdef MEAS__TIME_MALLOC
|
|
msach@101
|
159 int32 startStamp, endStamp;
|
|
msach@101
|
160 saveLowTimeStampCountInto( startStamp );
|
|
msach@101
|
161 #endif
|
|
msach@101
|
162 //========================================================================
|
|
msach@101
|
163
|
|
msach@102
|
164
|
|
msach@101
|
165 MallocArrays* freeList = _VMSMasterEnv->freeLists;
|
|
msach@101
|
166
|
|
msach@101
|
167 //Return a small chunk if the requested size is smaller than 128B
|
|
msach@102
|
168 if(sizeRequested <= LOWER_BOUND)
|
|
msach@102
|
169 {
|
|
msach@102
|
170 uint32 freeListIdx = (sizeRequested-1)/32;
|
|
msach@102
|
171 if(freeList->smallChunkCount[freeListIdx] == 0)
|
|
msach@102
|
172 {
|
|
msach@102
|
173 makeChunks((freeListIdx+1)*32, &freeList->smallChunks[freeListIdx]);
|
|
msach@102
|
174 freeList->smallChunkCount[freeListIdx] += 5;
|
|
msach@102
|
175 }
|
|
msach@102
|
176
|
|
msach@102
|
177 freeList->smallChunkCount[freeListIdx]--;
|
|
msach@102
|
178 return removeChunk(&freeList->smallChunks[freeListIdx]) + 1;
|
|
msach@102
|
179 }
|
|
msach@102
|
180
|
|
msach@101
|
181 //Calculate the expected container. Start one higher to have a Chunk that's
|
|
msach@101
|
182 //always big enough.
|
|
msach@101
|
183 uint32 targetContainerIdx = getContainer(sizeRequested);
|
|
msach@101
|
184 uint32 containerIdx = targetContainerIdx + 1;
|
|
msach@101
|
185
|
|
msach@101
|
186 MallocProlog* foundChunk;
|
|
msach@101
|
187 if(freeList->bigChunks[containerIdx] == NULL)
|
|
msach@101
|
188 {
|
|
msach@101
|
189 while(freeList->bigChunks[containerIdx] == NULL)
|
|
msach@101
|
190 {
|
|
msach@101
|
191 containerIdx++;
|
|
msach@102
|
192 if(containerIdx >= freeList->containerCount)
|
|
msach@101
|
193 {
|
|
msach@101
|
194 printf("VMS malloc failed: low memory");
|
|
msach@101
|
195 exit(1);
|
|
msach@101
|
196 }
|
|
msach@101
|
197 }
|
|
msach@101
|
198
|
|
msach@101
|
199 foundChunk = removeChunk(&freeList->bigChunks[containerIdx]);
|
|
msach@101
|
200 size_t chunkSize = getChunkSize(foundChunk);
|
|
msach@101
|
201
|
|
msach@102
|
202 if(chunkSize > sizeRequested + sizeof(MallocProlog))
|
|
msach@101
|
203 {
|
|
msach@102
|
204 MallocProlog *newChunk = divideChunk(foundChunk,sizeRequested);
|
|
msach@102
|
205 containerIdx = getContainer(chunkSize - sizeRequested - sizeof(MallocProlog));
|
|
msach@102
|
206 insertChunk(foundChunk,&freeList->bigChunks[containerIdx]);
|
|
msach@102
|
207 foundChunk = newChunk;
|
|
msach@102
|
208 }
|
|
msach@101
|
209 }
|
|
msach@101
|
210 else
|
|
msach@101
|
211 {
|
|
msach@101
|
212 foundChunk = removeChunk(&freeList->bigChunks[containerIdx]);
|
|
msach@101
|
213 }
|
|
msach@101
|
214
|
|
msach@101
|
215 //Mark as allocated
|
|
msach@101
|
216 foundChunk->prevChunkInFreeList = NULL;
|
|
msach@101
|
217
|
|
msach@101
|
218 //============================= MEASUREMENT STUFF ========================
|
|
msach@101
|
219 #ifdef MEAS__TIME_MALLOC
|
|
msach@101
|
220 saveLowTimeStampCountInto( endStamp );
|
|
msach@101
|
221 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist );
|
|
msach@101
|
222 #endif
|
|
msach@101
|
223 //========================================================================
|
|
msach@102
|
224
|
|
msach@101
|
225 //skip over the prolog by adding its size to the pointer return
|
|
msach@102
|
226 return foundChunk + 1;
|
|
Me@50
|
227 }
|
|
Me@50
|
228
|
|
msach@101
|
229 /*
|
|
msach@101
|
230 * This is sequential code, meant to only be called from the Master, not from
|
|
Me@50
|
231 * any slave VPs.
|
|
Me@50
|
232 */
|
|
msach@101
|
233 void
|
|
msach@101
|
234 VMS__free( void *ptrToFree )
|
|
msach@101
|
235 {
|
|
Me@50
|
236
|
|
Me@65
|
237 //============================= MEASUREMENT STUFF ========================
|
|
Me@65
|
238 #ifdef MEAS__TIME_MALLOC
|
|
Me@65
|
239 int32 startStamp, endStamp;
|
|
Me@65
|
240 saveLowTimeStampCountInto( startStamp );
|
|
Me@65
|
241 #endif
|
|
Me@65
|
242 //========================================================================
|
|
Me@65
|
243
|
|
msach@102
|
244 MallocArrays* freeLists = _VMSMasterEnv->freeLists;
|
|
msach@101
|
245 MallocProlog *chunkToFree = (MallocProlog*)ptrToFree - 1;
|
|
msach@102
|
246 uint32 containerIdx;
|
|
msach@102
|
247
|
|
msach@102
|
248 size_t chunkSize = getChunkSize(chunkToFree);
|
|
msach@102
|
249 if(chunkSize <= LOWER_BOUND)
|
|
msach@102
|
250 {
|
|
msach@102
|
251 containerIdx = (chunkSize-1)/32;
|
|
msach@102
|
252 insertChunk(chunkToFree,&freeLists->smallChunks[containerIdx]);
|
|
msach@102
|
253 freeLists->smallChunkCount[containerIdx]++;
|
|
msach@102
|
254
|
|
msach@102
|
255 if(freeLists->smallChunkCount[containerIdx] > 20)
|
|
msach@102
|
256 recycleSmallChunks(&freeLists->smallChunks[containerIdx]);
|
|
msach@102
|
257
|
|
msach@102
|
258 return;
|
|
msach@102
|
259 }
|
|
msach@101
|
260
|
|
msach@101
|
261 //Check for free neighbors
|
|
msach@101
|
262 if(chunkToFree->nextLowerInMem)
|
|
msach@101
|
263 {
|
|
msach@101
|
264 if(chunkToFree->nextLowerInMem->prevChunkInFreeList != NULL)
|
|
msach@101
|
265 {//Chunk is not allocated
|
|
msach@102
|
266 if(getChunkSize(chunkToFree->nextLowerInMem) > LOWER_BOUND)
|
|
msach@102
|
267 {
|
|
msach@102
|
268 extractChunk(chunkToFree->nextLowerInMem);
|
|
msach@102
|
269 chunkToFree = mergeChunks(chunkToFree->nextLowerInMem, chunkToFree);
|
|
msach@102
|
270 }
|
|
Me@50
|
271 }
|
|
msach@101
|
272 }
|
|
msach@102
|
273 if(chunkToFree->nextHigherInMem)
|
|
msach@102
|
274 {
|
|
msach@102
|
275 if(chunkToFree->nextHigherInMem->prevChunkInFreeList != NULL)
|
|
msach@102
|
276 {//Chunk is not allocated
|
|
msach@102
|
277 if(getChunkSize(chunkToFree->nextHigherInMem) > LOWER_BOUND)
|
|
msach@102
|
278 {
|
|
msach@102
|
279 extractChunk(chunkToFree->nextHigherInMem);
|
|
msach@102
|
280 chunkToFree = mergeChunks(chunkToFree, chunkToFree->nextHigherInMem);
|
|
msach@102
|
281 }
|
|
msach@102
|
282 }
|
|
msach@102
|
283 }
|
|
msach@102
|
284
|
|
msach@102
|
285 containerIdx = getContainer(chunkSize);
|
|
msach@102
|
286 insertChunk(chunkToFree, &freeLists->bigChunks[containerIdx]);
|
|
msach@102
|
287
|
|
Me@65
|
288 //============================= MEASUREMENT STUFF ========================
|
|
Me@65
|
289 #ifdef MEAS__TIME_MALLOC
|
|
Me@65
|
290 saveLowTimeStampCountInto( endStamp );
|
|
Me@65
|
291 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->freeTimeHist );
|
|
Me@65
|
292 #endif
|
|
Me@65
|
293 //========================================================================
|
|
Me@50
|
294
|
|
Me@50
|
295 }
|
|
Me@50
|
296
|
|
Me@50
|
297
|
|
Me@53
|
298 /*Allocates memory from the external system -- higher overhead
|
|
Me@53
|
299 *
|
|
Me@53
|
300 *Because of Linux's malloc throwing bizarre random faults when malloc is
|
|
Me@53
|
301 * used inside a VMS virtual processor, have to pass this as a request and
|
|
Me@53
|
302 * have the core loop do it when it gets around to it -- will look for these
|
|
Me@53
|
303 * chores leftover from the previous animation of masterVP the next time it
|
|
Me@53
|
304 * goes to animate the masterVP -- so it takes two separate masterVP
|
|
Me@53
|
305 * animations, separated by work, to complete an external malloc or
|
|
Me@53
|
306 * external free request.
|
|
Me@53
|
307 *
|
|
Me@53
|
308 *Thinking core loop accepts signals -- just looks if signal-location is
|
|
Me@53
|
309 * empty or not --
|
|
Me@53
|
310 */
|
|
Me@53
|
311 void *
|
|
msach@76
|
312 VMS__malloc_in_ext( size_t sizeRequested )
|
|
Me@53
|
313 {
|
|
Me@53
|
314 /*
|
|
Me@53
|
315 //This is running in the master, so no chance for multiple cores to be
|
|
Me@53
|
316 // competing for the core's flag.
|
|
Me@53
|
317 if( *(_VMSMasterEnv->coreLoopSignalAddr[ 0 ]) != 0 )
|
|
Me@53
|
318 { //something has already signalled to core loop, so save the signal
|
|
Me@53
|
319 // and look, next time master animated, to see if can send it.
|
|
Me@53
|
320 //Note, the addr to put a signal is in the coreloop's frame, so just
|
|
Me@53
|
321 // checks it each time through -- make it volatile to avoid GCC
|
|
Me@53
|
322 // optimizations -- it's a coreloop local var that only changes
|
|
Me@53
|
323 // after jumping away. The signal includes the addr to send the
|
|
Me@53
|
324 //return to -- even if just empty return completion-signal
|
|
Me@53
|
325 //
|
|
Me@53
|
326 //save the signal in some queue that the master looks at each time
|
|
Me@53
|
327 // it starts up -- one loc says if empty for fast common case --
|
|
Me@53
|
328 //something like that -- want to hide this inside this call -- but
|
|
Me@53
|
329 // think this has to come as a request -- req handler gives procr
|
|
Me@53
|
330 // back to master loop, which gives it back to req handler at point
|
|
Me@53
|
331 // it sees that core loop has sent return signal. Something like
|
|
Me@53
|
332 // that.
|
|
Me@53
|
333 saveTheSignal
|
|
Me@53
|
334
|
|
Me@53
|
335 }
|
|
Me@53
|
336 coreSigData->type = malloc;
|
|
Me@53
|
337 coreSigData->sizeToMalloc = sizeRequested;
|
|
Me@53
|
338 coreSigData->locToSignalCompletion = &figureOut;
|
|
Me@53
|
339 _VMSMasterEnv->coreLoopSignals[ 0 ] = coreSigData;
|
|
Me@53
|
340 */
|
|
Me@53
|
341 //just risk system-stack faults until get this figured out
|
|
Me@53
|
342 return malloc( sizeRequested );
|
|
Me@53
|
343 }
|
|
Me@53
|
344
|
|
Me@53
|
345
|
|
Me@53
|
346 /*Frees memory that was allocated in the external system -- higher overhead
|
|
Me@53
|
347 *
|
|
Me@53
|
348 *As noted in external malloc comment, this is clunky 'cause the free has
|
|
Me@53
|
349 * to be called in the core loop.
|
|
Me@53
|
350 */
|
|
Me@53
|
351 void
|
|
Me@53
|
352 VMS__free_in_ext( void *ptrToFree )
|
|
Me@53
|
353 {
|
|
Me@53
|
354 //just risk system-stack faults until get this figured out
|
|
Me@53
|
355 free( ptrToFree );
|
|
Me@53
|
356
|
|
Me@53
|
357 //TODO: fix this -- so
|
|
Me@53
|
358 }
|
|
Me@53
|
359
|
|
Me@53
|
360
|
|
Me@50
|
361 /*Designed to be called from the main thread outside of VMS, during init
|
|
Me@50
|
362 */
|
|
msach@101
|
363 MallocArrays *
|
|
Me@53
|
364 VMS_ext__create_free_list()
|
|
msach@101
|
365 {
|
|
msach@101
|
366 //Initialize containers for small chunks and fill with zeros
|
|
msach@101
|
367 _VMSMasterEnv->freeLists = (MallocArrays*)malloc( sizeof(MallocArrays) );
|
|
msach@101
|
368 MallocArrays *freeLists = _VMSMasterEnv->freeLists;
|
|
msach@101
|
369
|
|
msach@101
|
370 freeLists->smallChunks =
|
|
msach@101
|
371 (MallocProlog**)malloc(SMALL_CHUNK_COUNT*sizeof(MallocProlog*));
|
|
msach@101
|
372 memset((void*)freeLists->smallChunks,
|
|
msach@101
|
373 0,SMALL_CHUNK_COUNT*sizeof(MallocProlog*));
|
|
msach@102
|
374 memset((void*)freeLists->smallChunkCount,
|
|
msach@102
|
375 0,SMALL_CHUNK_COUNT*sizeof(uint32));
|
|
msach@101
|
376
|
|
msach@101
|
377 //Calculate number of containers for big chunks
|
|
msach@101
|
378 uint32 container = getContainer(MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE)+1;
|
|
msach@101
|
379 freeLists->bigChunks = (MallocProlog**)malloc(container*sizeof(MallocProlog*));
|
|
msach@101
|
380 memset((void*)freeLists->bigChunks,0,container*sizeof(MallocProlog*));
|
|
msach@101
|
381 freeLists->containerCount = container;
|
|
msach@101
|
382
|
|
msach@101
|
383 //Create first element in lastContainer
|
|
msach@101
|
384 MallocProlog *firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE );
|
|
Me@50
|
385 if( firstChunk == NULL ) {printf("malloc error\n"); exit(1);}
|
|
msach@102
|
386 freeLists->memSpace = firstChunk;
|
|
msach@79
|
387
|
|
msach@101
|
388 firstChunk->nextLowerInMem = NULL;
|
|
msach@101
|
389 firstChunk->nextHigherInMem = (MallocProlog*)((uintptr_t)firstChunk +
|
|
msach@101
|
390 MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE - sizeof(MallocProlog*));
|
|
msach@101
|
391 firstChunk->nextChunkInFreeList = NULL;
|
|
msach@101
|
392 //previous element in the queue is the container
|
|
msach@101
|
393 firstChunk->prevChunkInFreeList = freeLists->bigChunks[container-1];
|
|
Me@53
|
394
|
|
msach@101
|
395 freeLists->bigChunks[container-1] = firstChunk;
|
|
msach@101
|
396
|
|
msach@101
|
397 //Create dummy chunk to mark the top of stack this is of course
|
|
msach@101
|
398 //never freed
|
|
msach@101
|
399 MallocProlog *dummyChunk = firstChunk->nextHigherInMem;
|
|
msach@101
|
400 dummyChunk->nextHigherInMem = dummyChunk+1;
|
|
msach@101
|
401 dummyChunk->nextLowerInMem = NULL;
|
|
msach@101
|
402 dummyChunk->nextChunkInFreeList = NULL;
|
|
msach@101
|
403 dummyChunk->prevChunkInFreeList = NULL;
|
|
msach@101
|
404
|
|
msach@101
|
405 return freeLists;
|
|
Me@50
|
406 }
|
|
Me@50
|
407
|
|
Me@50
|
408
|
|
Me@50
|
409 /*Designed to be called from the main thread outside of VMS, during cleanup
|
|
Me@50
|
410 */
|
|
Me@50
|
411 void
|
|
msach@102
|
412 VMS_ext__free_free_list( MallocArrays *freeLists )
|
|
Me@50
|
413 {
|
|
msach@102
|
414 free(freeLists->memSpace);
|
|
msach@102
|
415 free(freeLists->bigChunks);
|
|
msach@102
|
416 free(freeLists->smallChunks);
|
|
msach@102
|
417
|
|
Me@50
|
418 }
|
|
Me@50
|
419
|