annotate vmalloc.c @ 141:79bb48d7d93b

changed free back to request to master and bugfixes
author Merten Sach <msach@mailbox.tu-berlin.de>
date Wed, 21 Sep 2011 11:51:29 +0200
parents 2c8f3cf6c058
children 98fc8f3761a2
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