| 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
|
|
msach@141
|
17 #define NDEBUG
|
|
msach@141
|
18 #include <assert.h>
|
|
msach@141
|
19
|
|
msach@134
|
20 #include "VMS.h"
|
|
msach@140
|
21 #include "vmalloc.h"
|
|
Me@68
|
22 #include "Histogram/Histogram.h"
|
|
Me@50
|
23
|
|
msach@115
|
24 #define MAX_UINT64 0xFFFFFFFFFFFFFFFF
|
|
msach@115
|
25
|
|
msach@141
|
26
|
|
msach@141
|
27
|
|
msach@135
|
28 inline void
|
|
msach@135
|
29 sendFreeReqst_lib(int receiverID, void *ptrToFree, VirtProcr *animPr);
|
|
msach@135
|
30
|
|
msach@135
|
31 inline void
|
|
msach@135
|
32 sendFreeReqst_master(int receiverID, void *ptrToFree);
|
|
msach@135
|
33
|
|
msach@141
|
34 void VMS__check_free_list(MallocArrays *freeLists);
|
|
msach@141
|
35
|
|
msach@102
|
36 //A MallocProlog is a head element if the HigherInMem variable is NULL
|
|
msach@102
|
37 //A Chunk is free if the prevChunkInFreeList variable is NULL
|
|
msach@102
|
38
|
|
msach@101
|
39 /*
|
|
msach@101
|
40 * This calculates the container which fits the given size.
|
|
Me@50
|
41 */
|
|
msach@101
|
42 inline
|
|
msach@101
|
43 uint32 getContainer(size_t size)
|
|
msach@101
|
44 {
|
|
msach@118
|
45 return (log2(size)-LOG128)/LOG54;
|
|
msach@101
|
46 }
|
|
msach@101
|
47
|
|
msach@101
|
48 /*
|
|
msach@101
|
49 * Removes the first chunk of a freeList
|
|
msach@101
|
50 * The chunk is removed but not set as free. There is no check if
|
|
msach@101
|
51 * the free list is empty, so make sure this is not the case.
|
|
msach@101
|
52 */
|
|
msach@101
|
53 inline
|
|
msach@116
|
54 MallocProlog *removeChunk(MallocArrays* freeLists, uint32 containerIdx)
|
|
msach@101
|
55 {
|
|
msach@116
|
56 MallocProlog** container = &freeLists->bigChunks[containerIdx];
|
|
msach@116
|
57 MallocProlog* removedChunk = *container;
|
|
msach@116
|
58 *container = removedChunk->nextChunkInFreeList;
|
|
msach@116
|
59
|
|
msach@116
|
60 if(removedChunk->nextChunkInFreeList)
|
|
msach@116
|
61 removedChunk->nextChunkInFreeList->prevChunkInFreeList =
|
|
msach@116
|
62 (MallocProlog*)container;
|
|
msach@116
|
63
|
|
msach@141
|
64 assert((freeLists->bigChunksSearchVector[0] & ((uint64)1 << containerIdx)) != 0);
|
|
msach@141
|
65
|
|
msach@116
|
66 if(*container == NULL)
|
|
msach@116
|
67 {
|
|
msach@116
|
68 if(containerIdx < 64)
|
|
msach@141
|
69 {
|
|
msach@141
|
70 assert((freeLists->bigChunksSearchVector[0] & ((uint64)1 << containerIdx)) != 0);
|
|
msach@116
|
71 freeLists->bigChunksSearchVector[0] &= ~((uint64)1 << containerIdx);
|
|
msach@141
|
72 }
|
|
msach@116
|
73 else
|
|
msach@141
|
74 {
|
|
msach@141
|
75 assert((freeLists->bigChunksSearchVector[1] & ((uint64)1 << (containerIdx-64))) != 0);
|
|
msach@116
|
76 freeLists->bigChunksSearchVector[1] &= ~((uint64)1 << (containerIdx-64));
|
|
msach@141
|
77 }
|
|
msach@116
|
78 }
|
|
msach@116
|
79 return removedChunk;
|
|
msach@116
|
80 }
|
|
msach@116
|
81
|
|
msach@116
|
82 /*
|
|
msach@116
|
83 * Removes the first chunk of a freeList
|
|
msach@116
|
84 * The chunk is removed but not set as free. There is no check if
|
|
msach@116
|
85 * the free list is empty, so make sure this is not the case.
|
|
msach@116
|
86 */
|
|
msach@116
|
87 inline
|
|
msach@116
|
88 MallocProlog *removeSmallChunk(MallocArrays* freeLists, uint32 containerIdx)
|
|
msach@116
|
89 {
|
|
msach@116
|
90 MallocProlog** container = &freeLists->smallChunks[containerIdx];
|
|
msach@116
|
91 MallocProlog* removedChunk = *container;
|
|
msach@101
|
92 *container = removedChunk->nextChunkInFreeList;
|
|
msach@101
|
93
|
|
msach@101
|
94 if(removedChunk->nextChunkInFreeList)
|
|
msach@101
|
95 removedChunk->nextChunkInFreeList->prevChunkInFreeList =
|
|
msach@101
|
96 (MallocProlog*)container;
|
|
msach@101
|
97
|
|
msach@101
|
98 return removedChunk;
|
|
msach@101
|
99 }
|
|
msach@101
|
100
|
|
msach@102
|
101 inline
|
|
msach@117
|
102 size_t getChunkSize(MallocProlog* chunk)
|
|
msach@102
|
103 {
|
|
msach@117
|
104 return (uintptr_t)chunk->nextHigherInMem -
|
|
msach@117
|
105 (uintptr_t)chunk - sizeof(MallocProlog);
|
|
msach@102
|
106 }
|
|
msach@102
|
107
|
|
msach@101
|
108 /*
|
|
msach@101
|
109 * Removes a chunk from a free list.
|
|
msach@101
|
110 */
|
|
msach@101
|
111 inline
|
|
msach@115
|
112 void extractChunk(MallocProlog* chunk, MallocArrays *freeLists)
|
|
msach@101
|
113 {
|
|
msach@102
|
114 chunk->prevChunkInFreeList->nextChunkInFreeList = chunk->nextChunkInFreeList;
|
|
msach@102
|
115 if(chunk->nextChunkInFreeList)
|
|
msach@102
|
116 chunk->nextChunkInFreeList->prevChunkInFreeList = chunk->prevChunkInFreeList;
|
|
msach@116
|
117
|
|
msach@116
|
118 //The last element in the list points to the container. If the container points
|
|
msach@116
|
119 //to NULL the container is empty
|
|
msach@141
|
120 if(((*((void**)(chunk->prevChunkInFreeList))) == NULL) && (getChunkSize(chunk) >= BIG_LOWER_BOUND))
|
|
msach@115
|
121 {
|
|
msach@141
|
122 assert((*((void**)(chunk->prevChunkInFreeList))) == NULL);
|
|
msach@117
|
123 //Find the approppiate container because we do not know it
|
|
msach@117
|
124 uint64 containerIdx = ((uintptr_t)chunk->prevChunkInFreeList - (uintptr_t)freeLists->bigChunks) >> 3;
|
|
msach@140
|
125 if(containerIdx < (uint64)64)
|
|
msach@141
|
126 {
|
|
msach@141
|
127 assert((freeLists->bigChunksSearchVector[0] & ((uint64)1 << containerIdx)) != 0);
|
|
msach@116
|
128 freeLists->bigChunksSearchVector[0] &= ~((uint64)1 << containerIdx);
|
|
msach@141
|
129 }
|
|
msach@116
|
130 if(containerIdx < 128 && containerIdx >=64)
|
|
msach@141
|
131 {
|
|
msach@141
|
132 assert((freeLists->bigChunksSearchVector[1] & ((uint64)1 << (containerIdx-64))) != 0);
|
|
msach@116
|
133 freeLists->bigChunksSearchVector[1] &= ~((uint64)1 << (containerIdx-64));
|
|
msach@141
|
134 }
|
|
msach@117
|
135
|
|
msach@115
|
136 }
|
|
msach@101
|
137 }
|
|
msach@101
|
138
|
|
msach@101
|
139 /*
|
|
msach@101
|
140 * Merges two chunks.
|
|
msach@102
|
141 * Chunk A has to be before chunk B in memory. Both have to be removed from
|
|
msach@102
|
142 * a free list
|
|
msach@101
|
143 */
|
|
msach@101
|
144 inline
|
|
msach@101
|
145 MallocProlog *mergeChunks(MallocProlog* chunkA, MallocProlog* chunkB)
|
|
msach@101
|
146 {
|
|
msach@102
|
147 chunkA->nextHigherInMem = chunkB->nextHigherInMem;
|
|
msach@117
|
148 chunkB->nextHigherInMem->nextLowerInMem = chunkA;
|
|
msach@102
|
149 return chunkA;
|
|
msach@101
|
150 }
|
|
msach@101
|
151 /*
|
|
msach@101
|
152 * Inserts a chunk into a free list.
|
|
msach@101
|
153 */
|
|
msach@101
|
154 inline
|
|
msach@101
|
155 void insertChunk(MallocProlog* chunk, MallocProlog** container)
|
|
msach@101
|
156 {
|
|
msach@101
|
157 chunk->nextChunkInFreeList = *container;
|
|
msach@101
|
158 chunk->prevChunkInFreeList = (MallocProlog*)container;
|
|
msach@101
|
159 if(*container)
|
|
msach@101
|
160 (*container)->prevChunkInFreeList = chunk;
|
|
msach@101
|
161 *container = chunk;
|
|
msach@101
|
162 }
|
|
msach@101
|
163
|
|
msach@101
|
164 /*
|
|
msach@101
|
165 * Divides the chunk that a new chunk of newSize is created.
|
|
msach@101
|
166 * There is no size check, so make sure the size value is valid.
|
|
msach@101
|
167 */
|
|
msach@101
|
168 inline
|
|
msach@101
|
169 MallocProlog *divideChunk(MallocProlog* chunk, size_t newSize)
|
|
msach@101
|
170 {
|
|
msach@101
|
171 MallocProlog* newChunk = (MallocProlog*)((uintptr_t)chunk->nextHigherInMem -
|
|
msach@101
|
172 newSize - sizeof(MallocProlog));
|
|
msach@101
|
173
|
|
msach@101
|
174 newChunk->nextLowerInMem = chunk;
|
|
msach@101
|
175 newChunk->nextHigherInMem = chunk->nextHigherInMem;
|
|
msach@101
|
176
|
|
msach@117
|
177 chunk->nextHigherInMem->nextLowerInMem = newChunk;
|
|
msach@101
|
178 chunk->nextHigherInMem = newChunk;
|
|
msach@101
|
179
|
|
msach@101
|
180 return newChunk;
|
|
msach@101
|
181 }
|
|
msach@101
|
182
|
|
msach@117
|
183 /*
|
|
msach@117
|
184 * Search for chunk in the list of big chunks. Split the block if it's too big
|
|
msach@117
|
185 */
|
|
msach@101
|
186 inline
|
|
msach@117
|
187 MallocProlog *searchChunk(MallocArrays *freeLists, size_t sizeRequested, uint32 containerIdx)
|
|
msach@101
|
188 {
|
|
msach@117
|
189 MallocProlog* foundChunk;
|
|
msach@117
|
190
|
|
msach@117
|
191 uint64 searchVector = freeLists->bigChunksSearchVector[0];
|
|
msach@117
|
192 //set small chunk bits to zero
|
|
msach@117
|
193 searchVector &= MAX_UINT64 << containerIdx;
|
|
msach@117
|
194 containerIdx = __builtin_ffsl(searchVector);
|
|
msach@117
|
195
|
|
msach@117
|
196 if(containerIdx == 0)
|
|
msach@117
|
197 {
|
|
msach@117
|
198 searchVector = freeLists->bigChunksSearchVector[1];
|
|
msach@117
|
199 containerIdx = __builtin_ffsl(searchVector);
|
|
msach@117
|
200 if(containerIdx == 0)
|
|
msach@117
|
201 {
|
|
msach@117
|
202 printf("VMS malloc failed: low memory");
|
|
msach@117
|
203 exit(1);
|
|
msach@117
|
204 }
|
|
msach@117
|
205 containerIdx += 64;
|
|
msach@117
|
206 }
|
|
msach@141
|
207 containerIdx--; // ffsl index starts at 1
|
|
msach@117
|
208
|
|
msach@117
|
209
|
|
msach@117
|
210 foundChunk = removeChunk(freeLists, containerIdx);
|
|
msach@117
|
211 size_t chunkSize = getChunkSize(foundChunk);
|
|
msach@117
|
212
|
|
msach@117
|
213 //If the new chunk is larger than the requested size: split
|
|
msach@125
|
214 if(chunkSize > sizeRequested + 2 * sizeof(MallocProlog) + BIG_LOWER_BOUND)
|
|
msach@117
|
215 {
|
|
msach@117
|
216 MallocProlog *newChunk = divideChunk(foundChunk,sizeRequested);
|
|
msach@117
|
217 containerIdx = getContainer(getChunkSize(foundChunk)) - 1;
|
|
msach@117
|
218 insertChunk(foundChunk,&freeLists->bigChunks[containerIdx]);
|
|
msach@117
|
219 if(containerIdx < 64)
|
|
msach@117
|
220 freeLists->bigChunksSearchVector[0] |= ((uint64)1 << containerIdx);
|
|
msach@117
|
221 else
|
|
msach@117
|
222 freeLists->bigChunksSearchVector[1] |= ((uint64)1 << (containerIdx-64));
|
|
msach@141
|
223 assert(freeLists->bigChunks[containerIdx] == foundChunk);
|
|
msach@141
|
224 assert((freeLists->bigChunksSearchVector[0] & ((uint64)1 << containerIdx)) != 0);
|
|
msach@117
|
225 foundChunk = newChunk;
|
|
msach@117
|
226 }
|
|
msach@117
|
227
|
|
msach@117
|
228 return foundChunk;
|
|
msach@101
|
229 }
|
|
Me@50
|
230
|
|
msach@132
|
231 /*
|
|
msach@132
|
232 * This function is called by code which is part of the master loop.
|
|
msach@132
|
233 * This reads the animating coreID from the MasterEnv and calls the normal malloc
|
|
msach@132
|
234 * in VMS__malloc_on_core
|
|
msach@132
|
235 */
|
|
msach@132
|
236 void *
|
|
msach@132
|
237 VMS__malloc( size_t sizeRequested)
|
|
msach@132
|
238 {
|
|
msach@132
|
239 return VMS__malloc_on_core(sizeRequested, _VMSMasterEnv->currentMasterProcrID);
|
|
msach@132
|
240 }
|
|
Me@50
|
241
|
|
msach@132
|
242 /*
|
|
msach@132
|
243 * This is called by the plugin. This call to VMS_malloc_on_core is run on the
|
|
msach@132
|
244 * slave VPs stack so there is no switch to the VMS runtime.
|
|
msach@132
|
245 */
|
|
msach@132
|
246 void *
|
|
msach@132
|
247 VMS__malloc_in_lib(size_t sizeRequested, VirtProcr *VProcr)
|
|
msach@132
|
248 {
|
|
msach@132
|
249 return VMS__malloc_on_core(sizeRequested, VProcr->coreAnimatedBy);
|
|
msach@132
|
250 }
|
|
msach@132
|
251
|
|
msach@132
|
252 /*
|
|
msach@101
|
253 * This is sequential code, meant to only be called from the Master, not from
|
|
msach@101
|
254 * any slave VPs.
|
|
Me@50
|
255 */
|
|
msach@139
|
256 void *VMS__malloc_on_core( size_t sizeRequested, int procrID )
|
|
msach@101
|
257 {
|
|
Me@65
|
258 //============================= MEASUREMENT STUFF ========================
|
|
Me@65
|
259 #ifdef MEAS__TIME_MALLOC
|
|
Me@65
|
260 int32 startStamp, endStamp;
|
|
Me@65
|
261 saveLowTimeStampCountInto( startStamp );
|
|
Me@65
|
262 #endif
|
|
Me@65
|
263 //========================================================================
|
|
Me@65
|
264
|
|
msach@139
|
265 MallocArrays* freeLists = _VMSMasterEnv->freeLists[procrID];
|
|
msach@117
|
266 MallocProlog* foundChunk;
|
|
msach@139
|
267 MallocPrologAllocated* returnChunk;
|
|
msach@78
|
268
|
|
msach@101
|
269 //Return a small chunk if the requested size is smaller than 128B
|
|
msach@102
|
270 if(sizeRequested <= LOWER_BOUND)
|
|
msach@102
|
271 {
|
|
msach@117
|
272 uint32 freeListIdx = (sizeRequested-1)/SMALL_CHUNK_SIZE;
|
|
msach@117
|
273 if(freeLists->smallChunks[freeListIdx] == NULL)
|
|
msach@117
|
274 foundChunk = searchChunk(freeLists, SMALL_CHUNK_SIZE*(freeListIdx+1), 0);
|
|
msach@117
|
275 else
|
|
msach@117
|
276 foundChunk = removeSmallChunk(freeLists, freeListIdx);
|
|
msach@102
|
277
|
|
msach@140
|
278 _VMSMasterEnv->amtOfOutstandingMem -= getChunkSize(foundChunk) + sizeof(MallocProlog);
|
|
msach@139
|
279 returnChunk = (MallocPrologAllocated*)foundChunk;
|
|
msach@139
|
280 returnChunk->prevChunkInFreeList = NULL;//indicates elem currently allocated
|
|
msach@140
|
281 returnChunk->procrID = procrID;
|
|
msach@139
|
282 return returnChunk + 1;
|
|
msach@102
|
283 }
|
|
msach@78
|
284
|
|
msach@101
|
285 //Calculate the expected container. Start one higher to have a Chunk that's
|
|
msach@101
|
286 //always big enough.
|
|
msach@117
|
287 uint32 containerIdx = getContainer(sizeRequested);
|
|
msach@78
|
288
|
|
msach@115
|
289 if(freeLists->bigChunks[containerIdx] == NULL)
|
|
msach@117
|
290 foundChunk = searchChunk(freeLists, sizeRequested, containerIdx);
|
|
msach@78
|
291 else
|
|
msach@117
|
292 foundChunk = removeChunk(freeLists, containerIdx);
|
|
msach@101
|
293
|
|
msach@101
|
294 //Mark as allocated
|
|
msach@140
|
295 _VMSMasterEnv->amtOfOutstandingMem -= getChunkSize(foundChunk) + sizeof(MallocProlog);
|
|
msach@139
|
296 returnChunk = (MallocPrologAllocated*)foundChunk;
|
|
msach@139
|
297 returnChunk->prevChunkInFreeList = NULL;//indicates elem currently allocated
|
|
msach@139
|
298 returnChunk->procrID = procrID;
|
|
msach@101
|
299
|
|
msach@78
|
300 //============================= MEASUREMENT STUFF ========================
|
|
msach@78
|
301 #ifdef MEAS__TIME_MALLOC
|
|
msach@78
|
302 saveLowTimeStampCountInto( endStamp );
|
|
msach@78
|
303 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist );
|
|
msach@78
|
304 #endif
|
|
msach@78
|
305 //========================================================================
|
|
msach@141
|
306 assert(getChunkSize((MallocProlog*)returnChunk)>=sizeRequested);
|
|
msach@102
|
307
|
|
msach@101
|
308 //skip over the prolog by adding its size to the pointer return
|
|
msach@139
|
309 return returnChunk + 1;
|
|
msach@78
|
310 }
|
|
msach@139
|
311
|
|
msach@139
|
312 /*
|
|
msach@132
|
313 * This free is called for a master loop. It decides whether the allocation of
|
|
msach@132
|
314 * chunk was done on the same core. If it was it calls VMS__free_on_core
|
|
msach@132
|
315 * otherwise it sends a message to the responsible core.
|
|
msach@78
|
316 */
|
|
msach@132
|
317 void
|
|
msach@132
|
318 VMS__free(void *ptrToFree)
|
|
msach@132
|
319 {
|
|
msach@134
|
320 MallocPrologAllocated *chunk = (MallocPrologAllocated*)ptrToFree - 1;
|
|
msach@132
|
321 if(chunk->procrID == _VMSMasterEnv->currentMasterProcrID)
|
|
msach@132
|
322 {
|
|
msach@132
|
323 VMS__free_on_core(ptrToFree, _VMSMasterEnv->currentMasterProcrID);
|
|
msach@132
|
324 }
|
|
msach@132
|
325 else
|
|
msach@132
|
326 {
|
|
msach@135
|
327 sendFreeReqst_master(chunk->procrID, ptrToFree);
|
|
msach@135
|
328
|
|
msach@132
|
329 }
|
|
msach@132
|
330 }
|
|
msach@78
|
331
|
|
msach@132
|
332 /*
|
|
msach@132
|
333 * This free is called for the plugins. It decides whether the allocation of
|
|
msach@132
|
334 * chunk was done on the same core. If it was it calls VMS__free_on_core
|
|
msach@132
|
335 * otherwise it sends a message to the responsible core.
|
|
msach@132
|
336 */
|
|
msach@132
|
337 void
|
|
msach@132
|
338 VMS__free_in_lib(void *ptrToFree, VirtProcr *VProc)
|
|
msach@132
|
339 {
|
|
msach@134
|
340 MallocPrologAllocated *chunk = (MallocPrologAllocated*)ptrToFree - 1;
|
|
msach@132
|
341 if(chunk->procrID == VProc->coreAnimatedBy)
|
|
msach@132
|
342 {
|
|
msach@132
|
343 VMS__free_on_core(ptrToFree, VProc->coreAnimatedBy);
|
|
msach@78
|
344 }
|
|
msach@132
|
345 else
|
|
msach@132
|
346 {
|
|
msach@135
|
347 sendFreeReqst_lib(chunk->procrID, ptrToFree, VProc);
|
|
Me@50
|
348 }
|
|
msach@132
|
349 }
|
|
Me@50
|
350
|
|
msach@135
|
351 /*
|
|
msach@135
|
352 * This is called form a masterVP and request an free from a different masterVP.
|
|
msach@135
|
353 * The free of the request structure is done after the request is handled.
|
|
msach@135
|
354 */
|
|
msach@135
|
355 inline void
|
|
msach@135
|
356 sendFreeReqst_master(int receiverID, void *ptrToFree)
|
|
msach@135
|
357 {
|
|
msach@135
|
358 InterVMSCoreReqst *freeReqst = VMS__malloc(sizeof(InterVMSCoreReqst));
|
|
msach@135
|
359 freeReqst->freePtr = ptrToFree;
|
|
msach@135
|
360 freeReqst->secondReqType = transfer_free_ptr;
|
|
msach@141
|
361
|
|
msach@141
|
362 VMS__sendInterMasterReqst(receiverID, (InterMasterReqst*)freeReqst);
|
|
msach@135
|
363 }
|
|
msach@135
|
364
|
|
msach@135
|
365 /*
|
|
msach@135
|
366 * This is called if the free is called from the plugin. This requests an inter
|
|
msach@135
|
367 * master request from his master.
|
|
msach@135
|
368 */
|
|
msach@135
|
369 inline void
|
|
msach@135
|
370 sendFreeReqst_lib(int receiverID, void *ptrToFree, VirtProcr *animPr )
|
|
msach@135
|
371 {
|
|
msach@135
|
372 VMSSemReq reqData;
|
|
msach@135
|
373 InterVMSCoreReqst *freeReqst = VMS__malloc(sizeof(InterVMSCoreReqst));
|
|
msach@135
|
374 freeReqst->freePtr = ptrToFree;
|
|
msach@135
|
375 freeReqst->secondReqType = transfer_free_ptr;
|
|
msach@135
|
376
|
|
msach@135
|
377 reqData.reqType = interMasterReqst;
|
|
msach@135
|
378 reqData.receiverID = receiverID;
|
|
msach@135
|
379 reqData.data = (void*)freeReqst;
|
|
msach@135
|
380
|
|
msach@135
|
381 VMS__send_VMSSem_request( (void*)&reqData, animPr );
|
|
msach@135
|
382 }
|
|
msach@135
|
383
|
|
msach@141
|
384 void VMS__check_free_list(MallocArrays *freeLists)
|
|
msach@141
|
385 {
|
|
msach@141
|
386 int idx;
|
|
msach@141
|
387 for(idx=0; idx< freeLists->containerCount; idx++)
|
|
msach@141
|
388 {
|
|
msach@141
|
389 if(freeLists->bigChunks[idx])
|
|
msach@141
|
390 assert((freeLists->bigChunksSearchVector[0] & ((uint64)1 << idx)) != 0);
|
|
msach@141
|
391 if((freeLists->bigChunksSearchVector[0] & ((uint64)1 << idx)))
|
|
msach@141
|
392 assert(freeLists->bigChunks[idx] != NULL);
|
|
msach@141
|
393 }
|
|
msach@141
|
394 }
|
|
msach@141
|
395
|
|
msach@101
|
396 /*
|
|
msach@101
|
397 * This is sequential code, meant to only be called from the Master, not from
|
|
msach@82
|
398 * any slave VPs.
|
|
Me@50
|
399 */
|
|
Me@50
|
400 void
|
|
msach@139
|
401 VMS__free_on_core( void *ptrToFree, int procrID )
|
|
msach@101
|
402 {
|
|
msach@117
|
403
|
|
Me@65
|
404 //============================= MEASUREMENT STUFF ========================
|
|
Me@65
|
405 #ifdef MEAS__TIME_MALLOC
|
|
Me@65
|
406 int32 startStamp, endStamp;
|
|
Me@65
|
407 saveLowTimeStampCountInto( startStamp );
|
|
Me@65
|
408 #endif
|
|
Me@65
|
409 //========================================================================
|
|
msach@134
|
410
|
|
msach@139
|
411 MallocArrays* freeLists = _VMSMasterEnv->freeLists[procrID];
|
|
msach@101
|
412 MallocProlog *chunkToFree = (MallocProlog*)ptrToFree - 1;
|
|
msach@102
|
413 uint32 containerIdx;
|
|
msach@140
|
414 _VMSMasterEnv->amtOfOutstandingMem += getChunkSize(chunkToFree) + sizeof(MallocProlog);
|
|
msach@101
|
415
|
|
msach@101
|
416 //Check for free neighbors
|
|
msach@101
|
417 if(chunkToFree->nextLowerInMem)
|
|
msach@101
|
418 {
|
|
msach@101
|
419 if(chunkToFree->nextLowerInMem->prevChunkInFreeList != NULL)
|
|
msach@101
|
420 {//Chunk is not allocated
|
|
msach@117
|
421 extractChunk(chunkToFree->nextLowerInMem, freeLists);
|
|
msach@117
|
422 chunkToFree = mergeChunks(chunkToFree->nextLowerInMem, chunkToFree);
|
|
Me@50
|
423 }
|
|
msach@101
|
424 }
|
|
msach@102
|
425 if(chunkToFree->nextHigherInMem)
|
|
msach@102
|
426 {
|
|
msach@102
|
427 if(chunkToFree->nextHigherInMem->prevChunkInFreeList != NULL)
|
|
msach@102
|
428 {//Chunk is not allocated
|
|
msach@117
|
429 extractChunk(chunkToFree->nextHigherInMem, freeLists);
|
|
msach@117
|
430 chunkToFree = mergeChunks(chunkToFree, chunkToFree->nextHigherInMem);
|
|
Me@50
|
431 }
|
|
msach@102
|
432 }
|
|
msach@117
|
433
|
|
msach@117
|
434 size_t chunkSize = getChunkSize(chunkToFree);
|
|
msach@125
|
435 if(chunkSize < BIG_LOWER_BOUND)
|
|
msach@117
|
436 {
|
|
msach@117
|
437 containerIdx = (chunkSize/SMALL_CHUNK_SIZE)-1;
|
|
msach@125
|
438 if(containerIdx > SMALL_CHUNK_COUNT-1)
|
|
msach@125
|
439 containerIdx = SMALL_CHUNK_COUNT-1;
|
|
msach@117
|
440 insertChunk(chunkToFree, &freeLists->smallChunks[containerIdx]);
|
|
msach@117
|
441 }
|
|
Me@50
|
442 else
|
|
msach@117
|
443 {
|
|
msach@117
|
444 containerIdx = getContainer(getChunkSize(chunkToFree)) - 1;
|
|
msach@117
|
445 insertChunk(chunkToFree, &freeLists->bigChunks[containerIdx]);
|
|
msach@117
|
446 if(containerIdx < 64)
|
|
msach@117
|
447 freeLists->bigChunksSearchVector[0] |= (uint64)1 << containerIdx;
|
|
msach@117
|
448 else
|
|
msach@117
|
449 freeLists->bigChunksSearchVector[1] |= (uint64)1 << (containerIdx-64);
|
|
msach@141
|
450 assert((freeLists->bigChunksSearchVector[0] & (uint64)1 << containerIdx) != 0);
|
|
msach@141
|
451 }
|
|
msach@102
|
452
|
|
Me@65
|
453 //============================= MEASUREMENT STUFF ========================
|
|
Me@65
|
454 #ifdef MEAS__TIME_MALLOC
|
|
Me@65
|
455 saveLowTimeStampCountInto( endStamp );
|
|
Me@65
|
456 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->freeTimeHist );
|
|
Me@65
|
457 #endif
|
|
Me@65
|
458 //========================================================================
|
|
Me@50
|
459
|
|
Me@50
|
460 }
|
|
Me@50
|
461
|
|
msach@117
|
462 /*
|
|
msach@117
|
463 * Designed to be called from the main thread outside of VMS, during init
|
|
Me@53
|
464 */
|
|
msach@101
|
465 MallocArrays *
|
|
Me@53
|
466 VMS_ext__create_free_list()
|
|
msach@101
|
467 {
|
|
msach@101
|
468 //Initialize containers for small chunks and fill with zeros
|
|
msach@139
|
469 MallocArrays *freeLists = (MallocArrays*)malloc( sizeof(MallocArrays) );
|
|
msach@101
|
470
|
|
msach@101
|
471 freeLists->smallChunks =
|
|
msach@101
|
472 (MallocProlog**)malloc(SMALL_CHUNK_COUNT*sizeof(MallocProlog*));
|
|
msach@101
|
473 memset((void*)freeLists->smallChunks,
|
|
msach@101
|
474 0,SMALL_CHUNK_COUNT*sizeof(MallocProlog*));
|
|
msach@101
|
475
|
|
msach@101
|
476 //Calculate number of containers for big chunks
|
|
msach@101
|
477 uint32 container = getContainer(MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE)+1;
|
|
msach@101
|
478 freeLists->bigChunks = (MallocProlog**)malloc(container*sizeof(MallocProlog*));
|
|
msach@101
|
479 memset((void*)freeLists->bigChunks,0,container*sizeof(MallocProlog*));
|
|
msach@101
|
480 freeLists->containerCount = container;
|
|
msach@101
|
481
|
|
msach@101
|
482 //Create first element in lastContainer
|
|
msach@101
|
483 MallocProlog *firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE );
|
|
msach@117
|
484 if( firstChunk == NULL ) {printf("Can't allocate initial memory\n"); exit(1);}
|
|
msach@102
|
485 freeLists->memSpace = firstChunk;
|
|
msach@79
|
486
|
|
msach@82
|
487 //Touch memory to avoid page faults
|
|
msach@81
|
488 void *ptr,*endPtr;
|
|
msach@81
|
489 endPtr = (void*)firstChunk+MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE;
|
|
msach@81
|
490 for(ptr = firstChunk; ptr < endPtr; ptr+=PAGE_SIZE)
|
|
msach@81
|
491 {
|
|
msach@81
|
492 *(char*)ptr = 0;
|
|
msach@81
|
493 }
|
|
Me@53
|
494
|
|
msach@101
|
495 firstChunk->nextLowerInMem = NULL;
|
|
msach@101
|
496 firstChunk->nextHigherInMem = (MallocProlog*)((uintptr_t)firstChunk +
|
|
msach@141
|
497 MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE - sizeof(MallocProlog));
|
|
msach@101
|
498 firstChunk->nextChunkInFreeList = NULL;
|
|
msach@101
|
499 //previous element in the queue is the container
|
|
msach@139
|
500 firstChunk->prevChunkInFreeList = (MallocProlog*)&freeLists->bigChunks[container-2];
|
|
msach@82
|
501
|
|
msach@117
|
502 freeLists->bigChunks[container-2] = firstChunk;
|
|
msach@115
|
503 //Insert into bit search list
|
|
msach@117
|
504 if(container <= 65)
|
|
msach@141
|
505 {
|
|
msach@139
|
506 freeLists->bigChunksSearchVector[0] = ((uint64)1 << (container-2));
|
|
msach@141
|
507 freeLists->bigChunksSearchVector[1] = 0;
|
|
msach@141
|
508 }
|
|
msach@116
|
509 else
|
|
msach@141
|
510 {
|
|
msach@141
|
511 freeLists->bigChunksSearchVector[0] = 0;
|
|
msach@139
|
512 freeLists->bigChunksSearchVector[1] = ((uint64)1 << (container-66));
|
|
msach@141
|
513 }
|
|
msach@101
|
514
|
|
msach@101
|
515 //Create dummy chunk to mark the top of stack this is of course
|
|
msach@101
|
516 //never freed
|
|
msach@101
|
517 MallocProlog *dummyChunk = firstChunk->nextHigherInMem;
|
|
msach@101
|
518 dummyChunk->nextHigherInMem = dummyChunk+1;
|
|
msach@101
|
519 dummyChunk->nextLowerInMem = NULL;
|
|
msach@101
|
520 dummyChunk->nextChunkInFreeList = NULL;
|
|
msach@101
|
521 dummyChunk->prevChunkInFreeList = NULL;
|
|
msach@101
|
522
|
|
msach@101
|
523 return freeLists;
|
|
Me@50
|
524 }
|
|
Me@50
|
525
|
|
Me@50
|
526
|
|
Me@50
|
527 /*Designed to be called from the main thread outside of VMS, during cleanup
|
|
Me@50
|
528 */
|
|
Me@50
|
529 void
|
|
msach@102
|
530 VMS_ext__free_free_list( MallocArrays *freeLists )
|
|
Me@50
|
531 {
|
|
msach@102
|
532 free(freeLists->memSpace);
|
|
msach@102
|
533 free(freeLists->bigChunks);
|
|
msach@102
|
534 free(freeLists->smallChunks);
|
|
msach@139
|
535 free(freeLists);
|
|
Me@50
|
536 }
|
|
Me@50
|
537
|