annotate vmalloc.c @ 140:2c8f3cf6c058

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