comparison vmalloc.c @ 116:35547e66b971

malloc: multiple small chunk allocation
author Merten Sach <msach@mailbox.tu-berlin.de>
date Mon, 29 Aug 2011 17:09:00 +0200
parents 62c59f2ac9f1
children 07e679ee2095
comparison
equal deleted inserted replaced
15:5f703d658f90 16:f60c85476efd
44 * Removes the first chunk of a freeList 44 * Removes the first chunk of a freeList
45 * The chunk is removed but not set as free. There is no check if 45 * The chunk is removed but not set as free. There is no check if
46 * the free list is empty, so make sure this is not the case. 46 * the free list is empty, so make sure this is not the case.
47 */ 47 */
48 inline 48 inline
49 MallocProlog *removeChunk(MallocProlog** container) 49 MallocProlog *removeChunk(MallocArrays* freeLists, uint32 containerIdx)
50 { 50 {
51 MallocProlog *removedChunk = *container; 51 MallocProlog** container = &freeLists->bigChunks[containerIdx];
52 MallocProlog* removedChunk = *container;
52 *container = removedChunk->nextChunkInFreeList; 53 *container = removedChunk->nextChunkInFreeList;
53 54
54 if(removedChunk->nextChunkInFreeList) 55 if(removedChunk->nextChunkInFreeList)
55 removedChunk->nextChunkInFreeList->prevChunkInFreeList = 56 removedChunk->nextChunkInFreeList->prevChunkInFreeList =
56 (MallocProlog*)container; 57 (MallocProlog*)container;
57 58
59 if(*container == NULL)
60 {
61 if(containerIdx < 64)
62 freeLists->bigChunksSearchVector[0] &= ~((uint64)1 << containerIdx);
63 else
64 freeLists->bigChunksSearchVector[1] &= ~((uint64)1 << (containerIdx-64));
65 }
66
67 return removedChunk;
68 }
69
70 /*
71 * Removes the first chunk of a freeList
72 * The chunk is removed but not set as free. There is no check if
73 * the free list is empty, so make sure this is not the case.
74 */
75 inline
76 MallocProlog *removeSmallChunk(MallocArrays* freeLists, uint32 containerIdx)
77 {
78 MallocProlog** container = &freeLists->smallChunks[containerIdx];
79 MallocProlog* removedChunk = *container;
80 *container = removedChunk->nextChunkInFreeList;
81
82 if(removedChunk->nextChunkInFreeList)
83 removedChunk->nextChunkInFreeList->prevChunkInFreeList =
84 (MallocProlog*)container;
85
58 return removedChunk; 86 return removedChunk;
59 } 87 }
60 88
61 inline 89 inline
62 void recycleSmallChunks(MallocProlog** container) 90 void recycleSmallChunks(MallocProlog** container)
71 void extractChunk(MallocProlog* chunk, MallocArrays *freeLists) 99 void extractChunk(MallocProlog* chunk, MallocArrays *freeLists)
72 { 100 {
73 chunk->prevChunkInFreeList->nextChunkInFreeList = chunk->nextChunkInFreeList; 101 chunk->prevChunkInFreeList->nextChunkInFreeList = chunk->nextChunkInFreeList;
74 if(chunk->nextChunkInFreeList) 102 if(chunk->nextChunkInFreeList)
75 chunk->nextChunkInFreeList->prevChunkInFreeList = chunk->prevChunkInFreeList; 103 chunk->nextChunkInFreeList->prevChunkInFreeList = chunk->prevChunkInFreeList;
76 if(*(chunk->prevChunkInFreeList) == NULL) 104
77 { 105 //The last element in the list points to the container. If the container points
78 uint32 containerIdx = (uintptr_t)(chunk->prevChunkInFreeList - freeLists->bigChunks) / sizeof(MallocProlog*); 106 //to NULL the container is empty
79 freeLists->bigChunksSearchVector &= ~(1 << containerIdx); 107 if(*((void**)(chunk->prevChunkInFreeList)) == NULL)
108 {
109 uint32 containerIdx = ((uintptr_t)chunk->prevChunkInFreeList - (uintptr_t)freeLists->bigChunks) >> 6;
110 if(containerIdx < (uint32)64)
111 freeLists->bigChunksSearchVector[0] &= ~((uint64)1 << containerIdx);
112 if(containerIdx < 128 && containerIdx >=64)
113 freeLists->bigChunksSearchVector[1] &= ~((uint64)1 << (containerIdx-64));
80 } 114 }
81 } 115 }
82 116
83 /* 117 /*
84 * Merges two chunks. 118 * Merges two chunks.
142 176
143 uint32 containerIdx = getContainer(addedSize)+4; 177 uint32 containerIdx = getContainer(addedSize)+4;
144 while(freeLists->bigChunks[containerIdx] == NULL ) 178 while(freeLists->bigChunks[containerIdx] == NULL )
145 containerIdx++; 179 containerIdx++;
146 180
147 MallocProlog *foundChunk = removeChunk(&freeLists->bigChunks[containerIdx]); 181 MallocProlog *foundChunk = removeChunk(freeLists, containerIdx);
148 182
149 int i; 183 int i;
150 for(i=0; i<5; i++) 184 for(i=0; i<5; i++)
151 { 185 {
152 insertChunk(divideChunk(foundChunk,size), container); 186 insertChunk(divideChunk(foundChunk,size), container);
153 } 187 }
154 containerIdx = getContainer(getChunkSize(foundChunk)); 188 containerIdx = getContainer(getChunkSize(foundChunk));
155 insertChunk(foundChunk, &freeLists->bigChunks[containerIdx]); 189 insertChunk(foundChunk, &freeLists->bigChunks[containerIdx]);
190 if(containerIdx < 64)
191 freeLists->bigChunksSearchVector[0] |= ((uint64)1 << containerIdx);
192 else
193 freeLists->bigChunksSearchVector[1] |= ((uint64)1 << (containerIdx-64));
156 } 194 }
157 195
158 /* 196 /*
159 * This is sequential code, meant to only be called from the Master, not from 197 * This is sequential code, meant to only be called from the Master, not from
160 * any slave VPs. 198 * any slave VPs.
166 int32 startStamp, endStamp; 204 int32 startStamp, endStamp;
167 saveLowTimeStampCountInto( startStamp ); 205 saveLowTimeStampCountInto( startStamp );
168 #endif 206 #endif
169 //======================================================================== 207 //========================================================================
170 208
171
172 MallocArrays* freeLists = _VMSMasterEnv->freeLists; 209 MallocArrays* freeLists = _VMSMasterEnv->freeLists;
173 210
174 //Return a small chunk if the requested size is smaller than 128B 211 //Return a small chunk if the requested size is smaller than 128B
175 if(sizeRequested <= LOWER_BOUND) 212 if(sizeRequested <= LOWER_BOUND)
176 { 213 {
180 makeChunks((freeListIdx+1)*32, &freeLists->smallChunks[freeListIdx]); 217 makeChunks((freeListIdx+1)*32, &freeLists->smallChunks[freeListIdx]);
181 freeLists->smallChunkCount[freeListIdx] += 5; 218 freeLists->smallChunkCount[freeListIdx] += 5;
182 } 219 }
183 220
184 freeLists->smallChunkCount[freeListIdx]--; 221 freeLists->smallChunkCount[freeListIdx]--;
185 return removeChunk(&freeLists->smallChunks[freeListIdx]) + 1; 222 return removeSmallChunk(freeLists, freeListIdx) + 1;
186 } 223 }
187 224
188 //Calculate the expected container. Start one higher to have a Chunk that's 225 //Calculate the expected container. Start one higher to have a Chunk that's
189 //always big enough. 226 //always big enough.
190 uint32 targetContainerIdx = getContainer(sizeRequested); 227 uint32 containerIdx = getContainer(sizeRequested) + 1;
191 uint32 containerIdx = targetContainerIdx + 1;
192 228
193 MallocProlog* foundChunk; 229 MallocProlog* foundChunk;
194 if(freeLists->bigChunks[containerIdx] == NULL) 230 if(freeLists->bigChunks[containerIdx] == NULL)
195 { 231 {
196 uint64 searchVector = freeLists->bigChunksSearchVector; 232 uint64 searchVector = freeLists->bigChunksSearchVector[0];
197 //set small chunk bits to zero 233 //set small chunk bits to zero
198 searchVector &= MAX_UINT64 << containerIdx; 234 searchVector &= MAX_UINT64 << containerIdx;
199 containerIdx = __builtin_ffsl(searchVector); 235 containerIdx = __builtin_ffsl(searchVector);
200 236
201 if(containerIdx == 0) 237 if(containerIdx == 0)
202 { 238 {
203 printf("VMS malloc failed: low memory"); 239 searchVector = freeLists->bigChunksSearchVector[1];
204 exit(1); 240 containerIdx = __builtin_ffsl(searchVector);
205 } 241 if(containerIdx == 0)
206 /*
207 while(freeList->bigChunks[containerIdx] == NULL)
208 {
209 containerIdx++;
210 if(containerIdx >= freeList->containerCount)
211 { 242 {
212 printf("VMS malloc failed: low memory"); 243 printf("VMS malloc failed: low memory");
213 exit(1); 244 exit(1);
214 } 245 }
215 }*/ 246 containerIdx += 64;
216 247 }
217 foundChunk = removeChunk(&freeLists->bigChunks[containerIdx]); 248 containerIdx--;
249
250
251 foundChunk = removeChunk(freeLists, containerIdx);
218 size_t chunkSize = getChunkSize(foundChunk); 252 size_t chunkSize = getChunkSize(foundChunk);
219 253
220 //If the new chunk is larger than the requested size: split 254 //If the new chunk is larger than the requested size: split
221 if(chunkSize > sizeRequested + 2 * sizeof(MallocProlog) + LOWER_BOUND) 255 if(chunkSize > sizeRequested + 2 * sizeof(MallocProlog) + LOWER_BOUND)
222 { 256 {
223 MallocProlog *newChunk = divideChunk(foundChunk,sizeRequested); 257 MallocProlog *newChunk = divideChunk(foundChunk,sizeRequested);
224 containerIdx = getContainer(getChunkSize(newChunk)); 258 containerIdx = getContainer(getChunkSize(foundChunk));
225 insertChunk(foundChunk,&freeLists->bigChunks[containerIdx]); 259 insertChunk(foundChunk,&freeLists->bigChunks[containerIdx]);
226 freeLists->bigChunksSearchVector |= 1 << containerIdx; 260 if(containerIdx < 64)
261 freeLists->bigChunksSearchVector[0] |= ((uint64)1 << containerIdx);
262 else
263 freeLists->bigChunksSearchVector[1] |= ((uint64)1 << (containerIdx-64));
227 foundChunk = newChunk; 264 foundChunk = newChunk;
228 } 265 }
229 } 266 }
230 else 267 else
231 { 268 {
232 foundChunk = removeChunk(&freeLists->bigChunks[containerIdx]); 269 foundChunk = removeChunk(freeLists, containerIdx);
233 } 270 }
234 271
235 //Mark as allocated 272 //Mark as allocated
236 foundChunk->prevChunkInFreeList = NULL; 273 foundChunk->prevChunkInFreeList = NULL;
237 274
283 { 320 {
284 if(chunkToFree->nextLowerInMem->prevChunkInFreeList != NULL) 321 if(chunkToFree->nextLowerInMem->prevChunkInFreeList != NULL)
285 {//Chunk is not allocated 322 {//Chunk is not allocated
286 if(getChunkSize(chunkToFree->nextLowerInMem) > LOWER_BOUND) 323 if(getChunkSize(chunkToFree->nextLowerInMem) > LOWER_BOUND)
287 { 324 {
288 extractChunk(chunkToFree->nextLowerInMem); 325 extractChunk(chunkToFree->nextLowerInMem, freeLists);
289 chunkToFree = mergeChunks(chunkToFree->nextLowerInMem, chunkToFree); 326 chunkToFree = mergeChunks(chunkToFree->nextLowerInMem, chunkToFree);
290 } 327 }
291 } 328 }
292 } 329 }
293 if(chunkToFree->nextHigherInMem) 330 if(chunkToFree->nextHigherInMem)
294 { 331 {
295 if(chunkToFree->nextHigherInMem->prevChunkInFreeList != NULL) 332 if(chunkToFree->nextHigherInMem->prevChunkInFreeList != NULL)
296 {//Chunk is not allocated 333 {//Chunk is not allocated
297 if(getChunkSize(chunkToFree->nextHigherInMem) > LOWER_BOUND) 334 if(getChunkSize(chunkToFree->nextHigherInMem) > LOWER_BOUND)
298 { 335 {
299 extractChunk(chunkToFree->nextHigherInMem); 336 extractChunk(chunkToFree->nextHigherInMem, freeLists);
300 chunkToFree = mergeChunks(chunkToFree, chunkToFree->nextHigherInMem); 337 chunkToFree = mergeChunks(chunkToFree, chunkToFree->nextHigherInMem);
301 } 338 }
302 } 339 }
303 } 340 }
304 341
305 containerIdx = getContainer(chunkSize); 342 containerIdx = getContainer(getChunkSize(chunkToFree));
306 insertChunk(chunkToFree, &freeLists->bigChunks[containerIdx]); 343 insertChunk(chunkToFree, &freeLists->bigChunks[containerIdx]);
344 if(containerIdx < 64)
345 freeLists->bigChunksSearchVector[0] |= (uint64)1 << containerIdx;
346 else
347 freeLists->bigChunksSearchVector[1] |= (uint64)1 << (containerIdx-64);
307 348
308 //============================= MEASUREMENT STUFF ======================== 349 //============================= MEASUREMENT STUFF ========================
309 #ifdef MEAS__TIME_MALLOC 350 #ifdef MEAS__TIME_MALLOC
310 saveLowTimeStampCountInto( endStamp ); 351 saveLowTimeStampCountInto( endStamp );
311 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->freeTimeHist ); 352 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->freeTimeHist );
412 //previous element in the queue is the container 453 //previous element in the queue is the container
413 firstChunk->prevChunkInFreeList = freeLists->bigChunks[container-1]; 454 firstChunk->prevChunkInFreeList = freeLists->bigChunks[container-1];
414 455
415 freeLists->bigChunks[container-1] = firstChunk; 456 freeLists->bigChunks[container-1] = firstChunk;
416 //Insert into bit search list 457 //Insert into bit search list
417 freeLists->bigChunksSearchVector |= (1 << (container-1)); 458 if(container <= 64)
459 freeLists->bigChunksSearchVector[0] |= ((uint64)1 << (container-1));
460 else
461 freeLists->bigChunksSearchVector[1] |= ((uint64)1 << (container-65));
418 462
419 //Create dummy chunk to mark the top of stack this is of course 463 //Create dummy chunk to mark the top of stack this is of course
420 //never freed 464 //never freed
421 MallocProlog *dummyChunk = firstChunk->nextHigherInMem; 465 MallocProlog *dummyChunk = firstChunk->nextHigherInMem;
422 dummyChunk->nextHigherInMem = dummyChunk+1; 466 dummyChunk->nextHigherInMem = dummyChunk+1;