annotate vmalloc.c @ 178:c1784868dcea

testing hgeol -- see if it fixes line-ending issues -- commit line endings
author Me@portablequad
date Wed, 04 Jan 2012 16:10:11 -0800
parents 21c95d402fe6
children f6d81915512c 6db9e4898978
rev   line source
Me@178 1 /*
Me@178 2 * Copyright 2009 OpenSourceCodeStewardshipFoundation.org
Me@178 3 * Licensed under GNU General Public License version 2
Me@178 4 *
Me@178 5 * Author: seanhalle@yahoo.com
Me@178 6 *
Me@178 7 * Created on November 14, 2009, 9:07 PM
Me@178 8 */
Me@178 9
Me@178 10 #include <malloc.h>
Me@178 11 #include <inttypes.h>
Me@178 12 #include <stdlib.h>
Me@178 13 #include <stdio.h>
Me@178 14
Me@178 15 #include "VMS.h"
Me@178 16 #include "Histogram/Histogram.h"
Me@178 17
Me@178 18 /*Helper function
Me@178 19 *Insert a newly generated free chunk into the first spot on the free list.
Me@178 20 * The chunk is cast as a MallocProlog, so the various pointers in it are
Me@178 21 * accessed with C's help -- and the size of the prolog is easily added to
Me@178 22 * the pointer when a chunk is returned to the app -- so C handles changes
Me@178 23 * in pointer sizes among machines.
Me@178 24 *
Me@178 25 *The list head is a normal MallocProlog struct -- identified by its
Me@178 26 * prevChunkInFreeList being NULL -- the only one.
Me@178 27 *
Me@178 28 *The end of the list is identified by next chunk being NULL, as usual.
Me@178 29 */
Me@178 30 void inline
Me@178 31 add_chunk_to_free_list( MallocProlog *chunk, MallocProlog *listHead )
Me@178 32 {
Me@178 33 chunk->nextChunkInFreeList = listHead->nextChunkInFreeList;
Me@178 34 if( chunk->nextChunkInFreeList != NULL ) //if not last in free list
Me@178 35 chunk->nextChunkInFreeList->prevChunkInFreeList = chunk;
Me@178 36 chunk->prevChunkInFreeList = listHead;
Me@178 37 listHead->nextChunkInFreeList = chunk;
Me@178 38 }
Me@178 39
Me@178 40
Me@178 41 /*This is sequential code, meant to only be called from the Master, not from
Me@178 42 * any slave VPs.
Me@178 43 *Search down list, checking size by the nextHigherInMem pointer, to find
Me@178 44 * first chunk bigger than size needed.
Me@178 45 *Shave off the extra and make it into a new free-list element, hook it in
Me@178 46 * then return the address of the found element plus size of prolog.
Me@178 47 *
Me@178 48 *Will find a
Me@178 49 */
Me@178 50 void *VMS__malloc( size_t sizeRequested )
Me@178 51 { MallocProlog *foundElem = NULL, *currElem, *newElem;
Me@178 52 ssize_t amountExtra, sizeConsumed,sizeOfFound;
Me@178 53 uint32 foundElemIsTopOfHeap;
Me@178 54
Me@178 55 //============================= MEASUREMENT STUFF ========================
Me@178 56 #ifdef MEAS__TIME_MALLOC
Me@178 57 int32 startStamp, endStamp;
Me@178 58 saveLowTimeStampCountInto( startStamp );
Me@178 59 #endif
Me@178 60 //========================================================================
Me@178 61
Me@178 62 //step up the size to be aligned at 16-byte boundary, prob better ways
Me@178 63 sizeRequested = (sizeRequested + 16) & ~15;
Me@178 64 currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList;
Me@178 65
Me@178 66 while( currElem != NULL )
Me@178 67 { //check if size of currElem is big enough
Me@178 68 sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem);
Me@178 69 amountExtra = sizeOfFound - sizeRequested - sizeof(MallocProlog);
Me@178 70 if( amountExtra > 0 )
Me@178 71 { //found it, get out of loop
Me@178 72 foundElem = currElem;
Me@178 73 currElem = NULL;
Me@178 74 }
Me@178 75 else
Me@178 76 currElem = currElem->nextChunkInFreeList;
Me@178 77 }
Me@178 78
Me@178 79 if( foundElem == NULL )
Me@178 80 { ERROR("\nmalloc failed\n")
Me@178 81 return (void *)NULL; //indicates malloc failed
Me@178 82 }
Me@178 83 //Using a kludge to identify the element that is the top chunk in the
Me@178 84 // heap -- saving top-of-heap addr in head's nextHigherInMem -- and
Me@178 85 // save addr of start of heap in head's nextLowerInMem
Me@178 86 //Will handle top of Heap specially
Me@178 87 foundElemIsTopOfHeap = foundElem->nextHigherInMem ==
Me@178 88 _VMSMasterEnv->freeListHead->nextHigherInMem;
Me@178 89
Me@178 90 //before shave off and try to insert new elem, remove found elem
Me@178 91 //note, foundElem will never be the head, so always has valid prevChunk
Me@178 92 foundElem->prevChunkInFreeList->nextChunkInFreeList =
Me@178 93 foundElem->nextChunkInFreeList;
Me@178 94 if( foundElem->nextChunkInFreeList != NULL )
Me@178 95 { foundElem->nextChunkInFreeList->prevChunkInFreeList =
Me@178 96 foundElem->prevChunkInFreeList;
Me@178 97 }
Me@178 98 foundElem->prevChunkInFreeList = NULL;//indicates elem currently allocated
Me@178 99
Me@178 100 //if enough, turn extra into new elem & insert it
Me@178 101 if( amountExtra > 64 )
Me@178 102 { //make new elem by adding to addr of curr elem then casting
Me@178 103 sizeConsumed = sizeof(MallocProlog) + sizeRequested;
Me@178 104 newElem = (MallocProlog *)( (uintptr_t)foundElem + sizeConsumed );
Me@178 105 newElem->nextLowerInMem = foundElem; //This is evil (but why?)
Me@178 106 newElem->nextHigherInMem = foundElem->nextHigherInMem; //This is evil (but why?)
Me@178 107 foundElem->nextHigherInMem = newElem;
Me@178 108 if( ! foundElemIsTopOfHeap )
Me@178 109 { //there is no next higher for top of heap, so can't write to it
Me@178 110 newElem->nextHigherInMem->nextLowerInMem = newElem;
Me@178 111 }
Me@178 112 add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead );
Me@178 113 }
Me@178 114 else
Me@178 115 {
Me@178 116 sizeConsumed = sizeOfFound;
Me@178 117 }
Me@178 118 _VMSMasterEnv->amtOfOutstandingMem += sizeConsumed;
Me@178 119
Me@178 120 //============================= MEASUREMENT STUFF ========================
Me@178 121 #ifdef MEAS__TIME_MALLOC
Me@178 122 saveLowTimeStampCountInto( endStamp );
Me@178 123 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist );
Me@178 124 #endif
Me@178 125 //========================================================================
Me@178 126
Me@178 127 //skip over the prolog by adding its size to the pointer return
Me@178 128 return (void*)((uintptr_t)foundElem + sizeof(MallocProlog));
Me@178 129 }
Me@178 130
Me@178 131 /*This is sequential code, meant to only be called from the Master, not from
Me@178 132 * any slave VPs.
Me@178 133 *Search down list, checking size by the nextHigherInMem pointer, to find
Me@178 134 * first chunk bigger than size needed.
Me@178 135 *Shave off the extra and make it into a new free-list element, hook it in
Me@178 136 * then return the address of the found element plus size of prolog.
Me@178 137 *
Me@178 138 * The difference to the regular malloc is, that all the allocated chunks are
Me@178 139 * aligned and padded to the size of a CACHE_LINE. Thus creating a new chunk
Me@178 140 * before the aligned chunk.
Me@178 141 */
Me@178 142 void *VMS__malloc_aligned( size_t sizeRequested )
Me@178 143 { MallocProlog *foundElem = NULL, *currElem, *newElem;
Me@178 144 ssize_t amountExtra, sizeConsumed,sizeOfFound,prevAmount;
Me@178 145 uint32 foundElemIsTopOfHeap;
Me@178 146
Me@178 147 //============================= MEASUREMENT STUFF ========================
Me@178 148 #ifdef MEAS__TIME_MALLOC
Me@178 149 uint32 startStamp, endStamp;
Me@178 150 saveLowTimeStampCountInto( startStamp );
Me@178 151 #endif
Me@178 152 //========================================================================
Me@178 153
Me@178 154 //step up the size to be multiple of the cache line size
Me@178 155 sizeRequested = (sizeRequested + CACHE_LINE) & ~(CACHE_LINE-1);
Me@178 156 currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList;
Me@178 157
Me@178 158 while( currElem != NULL )
Me@178 159 { //check if size of currElem is big enough
Me@178 160 sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem);
Me@178 161 amountExtra = sizeOfFound - sizeRequested - sizeof(MallocProlog);
Me@178 162 if( amountExtra > 0 )
Me@178 163 {
Me@178 164 //look if the found element is already aligned
Me@178 165 if((((uintptr_t)currElem+sizeof(MallocProlog)) & (uintptr_t)(CACHE_LINE-1)) == 0){
Me@178 166 //found it, get out of loop
Me@178 167 foundElem = currElem;
Me@178 168 break;
Me@178 169 }else{
Me@178 170 //find first aligned address and check if it's still big enough
Me@178 171 //check also if the space before the aligned address is big enough
Me@178 172 //for a new element
Me@178 173 void *firstAlignedAddr = (void*)(((uintptr_t)currElem + 2*CACHE_LINE) & ~((uintptr_t)(CACHE_LINE-1)));
Me@178 174 prevAmount = (uintptr_t)firstAlignedAddr - (uintptr_t)currElem;
Me@178 175 sizeOfFound=(uintptr_t)currElem->nextHigherInMem -(uintptr_t)firstAlignedAddr + sizeof(MallocProlog);
Me@178 176 amountExtra= sizeOfFound - sizeRequested - sizeof(MallocProlog);
Me@178 177 if(prevAmount > 2*sizeof(MallocProlog) && amountExtra > 0 ){
Me@178 178 //found suitable element
Me@178 179 //create new previous element and exit loop
Me@178 180 MallocProlog *newAlignedElem = (MallocProlog*)firstAlignedAddr - 1;
Me@178 181
Me@178 182 //insert new element into free list
Me@178 183 if(currElem->nextChunkInFreeList != NULL)
Me@178 184 currElem->nextChunkInFreeList->prevChunkInFreeList = newAlignedElem;
Me@178 185 newAlignedElem->prevChunkInFreeList = currElem;
Me@178 186 newAlignedElem->nextChunkInFreeList = currElem->nextChunkInFreeList;
Me@178 187 currElem->nextChunkInFreeList = newAlignedElem;
Me@178 188
Me@178 189 //set higherInMem and lowerInMem
Me@178 190 newAlignedElem->nextHigherInMem = currElem->nextHigherInMem;
Me@178 191 foundElemIsTopOfHeap = currElem->nextHigherInMem ==
Me@178 192 _VMSMasterEnv->freeListHead->nextHigherInMem;
Me@178 193 if(!foundElemIsTopOfHeap)
Me@178 194 currElem->nextHigherInMem->nextLowerInMem = newAlignedElem;
Me@178 195 currElem->nextHigherInMem = newAlignedElem;
Me@178 196 newAlignedElem->nextLowerInMem = currElem;
Me@178 197
Me@178 198 //Found new element leaving loop
Me@178 199 foundElem = newAlignedElem;
Me@178 200 break;
Me@178 201 }
Me@178 202 }
Me@178 203
Me@178 204 }
Me@178 205 currElem = currElem->nextChunkInFreeList;
Me@178 206 }
Me@178 207
Me@178 208 if( foundElem == NULL )
Me@178 209 { ERROR("\nmalloc failed\n")
Me@178 210 return (void *)NULL; //indicates malloc failed
Me@178 211 }
Me@178 212 //Using a kludge to identify the element that is the top chunk in the
Me@178 213 // heap -- saving top-of-heap addr in head's nextHigherInMem -- and
Me@178 214 // save addr of start of heap in head's nextLowerInMem
Me@178 215 //Will handle top of Heap specially
Me@178 216 foundElemIsTopOfHeap = foundElem->nextHigherInMem ==
Me@178 217 _VMSMasterEnv->freeListHead->nextHigherInMem;
Me@178 218
Me@178 219 //before shave off and try to insert new elem, remove found elem
Me@178 220 //note, foundElem will never be the head, so always has valid prevChunk
Me@178 221 foundElem->prevChunkInFreeList->nextChunkInFreeList =
Me@178 222 foundElem->nextChunkInFreeList;
Me@178 223 if( foundElem->nextChunkInFreeList != NULL )
Me@178 224 { foundElem->nextChunkInFreeList->prevChunkInFreeList =
Me@178 225 foundElem->prevChunkInFreeList;
Me@178 226 }
Me@178 227 foundElem->prevChunkInFreeList = NULL;//indicates elem currently allocated
Me@178 228
Me@178 229 //if enough, turn extra into new elem & insert it
Me@178 230 if( amountExtra > 64 )
Me@178 231 { //make new elem by adding to addr of curr elem then casting
Me@178 232 sizeConsumed = sizeof(MallocProlog) + sizeRequested;
Me@178 233 newElem = (MallocProlog *)( (uintptr_t)foundElem + sizeConsumed );
Me@178 234 newElem->nextHigherInMem = foundElem->nextHigherInMem;
Me@178 235 newElem->nextLowerInMem = foundElem;
Me@178 236 foundElem->nextHigherInMem = newElem;
Me@178 237
Me@178 238 if( ! foundElemIsTopOfHeap )
Me@178 239 { //there is no next higher for top of heap, so can't write to it
Me@178 240 newElem->nextHigherInMem->nextLowerInMem = newElem;
Me@178 241 }
Me@178 242 add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead );
Me@178 243 }
Me@178 244 else
Me@178 245 {
Me@178 246 sizeConsumed = sizeOfFound;
Me@178 247 }
Me@178 248 _VMSMasterEnv->amtOfOutstandingMem += sizeConsumed;
Me@178 249
Me@178 250 //============================= MEASUREMENT STUFF ========================
Me@178 251 #ifdef MEAS__TIME_MALLOC
Me@178 252 saveLowTimeStampCountInto( endStamp );
Me@178 253 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist );
Me@178 254 #endif
Me@178 255 //========================================================================
Me@178 256
Me@178 257 //skip over the prolog by adding its size to the pointer return
Me@178 258 return (void*)((uintptr_t)foundElem + sizeof(MallocProlog));
Me@178 259 }
Me@178 260
Me@178 261
Me@178 262 /*This is sequential code -- only to be called from the Master
Me@178 263 * When free, subtract the size of prolog from pointer, then cast it to a
Me@178 264 * MallocProlog. Then check the nextLower and nextHigher chunks to see if
Me@178 265 * one or both are also free, and coalesce if so, and if neither free, then
Me@178 266 * add this one to free-list.
Me@178 267 */
Me@178 268 void
Me@178 269 VMS__free( void *ptrToFree )
Me@178 270 { MallocProlog *elemToFree, *nextLowerElem, *nextHigherElem;
Me@178 271 size_t sizeOfElem;
Me@178 272 uint32 lowerExistsAndIsFree, higherExistsAndIsFree;
Me@178 273
Me@178 274 //============================= MEASUREMENT STUFF ========================
Me@178 275 #ifdef MEAS__TIME_MALLOC
Me@178 276 int32 startStamp, endStamp;
Me@178 277 saveLowTimeStampCountInto( startStamp );
Me@178 278 #endif
Me@178 279 //========================================================================
Me@178 280
Me@178 281 if( ptrToFree < (void*)_VMSMasterEnv->freeListHead->nextLowerInMem ||
Me@178 282 ptrToFree > (void*)_VMSMasterEnv->freeListHead->nextHigherInMem )
Me@178 283 { //outside the range of data owned by VMS's malloc, so do nothing
Me@178 284 return;
Me@178 285 }
Me@178 286 //subtract size of prolog to get pointer to prolog, then cast
Me@178 287 elemToFree = (MallocProlog *)((uintptr_t)ptrToFree - sizeof(MallocProlog));
Me@178 288 sizeOfElem =(size_t)((uintptr_t)elemToFree->nextHigherInMem-(uintptr_t)elemToFree);
Me@178 289
Me@178 290 if( elemToFree->prevChunkInFreeList != NULL )
Me@178 291 { printf( "error: freeing same element twice!" ); exit(1);
Me@178 292 }
Me@178 293
Me@178 294 _VMSMasterEnv->amtOfOutstandingMem -= sizeOfElem;
Me@178 295
Me@178 296 nextLowerElem = elemToFree->nextLowerInMem;
Me@178 297 nextHigherElem = elemToFree->nextHigherInMem;
Me@178 298
Me@178 299 if( nextHigherElem == NULL )
Me@178 300 higherExistsAndIsFree = FALSE;
Me@178 301 else //okay exists, now check if in the free-list by checking back ptr
Me@178 302 higherExistsAndIsFree = (nextHigherElem->prevChunkInFreeList != NULL);
Me@178 303
Me@178 304 if( nextLowerElem == NULL )
Me@178 305 lowerExistsAndIsFree = FALSE;
Me@178 306 else //okay, it exists, now check if it's free
Me@178 307 lowerExistsAndIsFree = (nextLowerElem->prevChunkInFreeList != NULL);
Me@178 308
Me@178 309
Me@178 310 //now, know what exists and what's free
Me@178 311 if( lowerExistsAndIsFree )
Me@178 312 { if( higherExistsAndIsFree )
Me@178 313 { //both exist and are free, so coalesce all three
Me@178 314 //First, remove higher from free-list
Me@178 315 nextHigherElem->prevChunkInFreeList->nextChunkInFreeList =
Me@178 316 nextHigherElem->nextChunkInFreeList;
Me@178 317 if( nextHigherElem->nextChunkInFreeList != NULL ) //end-of-list?
Me@178 318 nextHigherElem->nextChunkInFreeList->prevChunkInFreeList =
Me@178 319 nextHigherElem->prevChunkInFreeList;
Me@178 320 //Now, fix-up sequence-in-mem list -- by side-effect, this also
Me@178 321 // changes size of the lower elem, which is still in free-list
Me@178 322 nextLowerElem->nextHigherInMem = nextHigherElem->nextHigherInMem;
Me@178 323 if( nextHigherElem->nextHigherInMem !=
Me@178 324 _VMSMasterEnv->freeListHead->nextHigherInMem )
Me@178 325 nextHigherElem->nextHigherInMem->nextLowerInMem = nextLowerElem;
Me@178 326 //notice didn't do anything to elemToFree -- it simply is no
Me@178 327 // longer reachable from any of the lists. Wonder if could be a
Me@178 328 // security leak because left valid addresses in it,
Me@178 329 // but don't care for now.
Me@178 330 }
Me@178 331 else
Me@178 332 { //lower is the only of the two that exists and is free,
Me@178 333 //In this case, no adjustment to free-list, just change mem-list.
Me@178 334 // By side-effect, changes size of the lower elem
Me@178 335 nextLowerElem->nextHigherInMem = elemToFree->nextHigherInMem;
Me@178 336 if( elemToFree->nextHigherInMem !=
Me@178 337 _VMSMasterEnv->freeListHead->nextHigherInMem )
Me@178 338 elemToFree->nextHigherInMem->nextLowerInMem = nextLowerElem;
Me@178 339 }
Me@178 340 }
Me@178 341 else
Me@178 342 { //lower either doesn't exist or isn't free, so check higher
Me@178 343 if( higherExistsAndIsFree )
Me@178 344 { //higher exists and is the only of the two free
Me@178 345 //First, in free-list, replace higher elem with the one to free
Me@178 346 elemToFree->nextChunkInFreeList=nextHigherElem->nextChunkInFreeList;
Me@178 347 elemToFree->prevChunkInFreeList=nextHigherElem->prevChunkInFreeList;
Me@178 348 elemToFree->prevChunkInFreeList->nextChunkInFreeList = elemToFree;
Me@178 349 if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list?
Me@178 350 elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree;
Me@178 351 //Now chg mem-list. By side-effect, changes size of elemToFree
Me@178 352 elemToFree->nextHigherInMem = nextHigherElem->nextHigherInMem;
Me@178 353 if( elemToFree->nextHigherInMem !=
Me@178 354 _VMSMasterEnv->freeListHead->nextHigherInMem )
Me@178 355 elemToFree->nextHigherInMem->nextLowerInMem = elemToFree;
Me@178 356 }
Me@178 357 else
Me@178 358 { //neither lower nor higher is availabe to coalesce so add to list
Me@178 359 // this makes prev chunk ptr non-null, which indicates it's free
Me@178 360 elemToFree->nextChunkInFreeList =
Me@178 361 _VMSMasterEnv->freeListHead->nextChunkInFreeList;
Me@178 362 _VMSMasterEnv->freeListHead->nextChunkInFreeList = elemToFree;
Me@178 363 if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list?
Me@178 364 elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree;
Me@178 365 elemToFree->prevChunkInFreeList = _VMSMasterEnv->freeListHead;
Me@178 366 }
Me@178 367 }
Me@178 368 //============================= MEASUREMENT STUFF ========================
Me@178 369 #ifdef MEAS__TIME_MALLOC
Me@178 370 saveLowTimeStampCountInto( endStamp );
Me@178 371 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->freeTimeHist );
Me@178 372 #endif
Me@178 373 //========================================================================
Me@178 374
Me@178 375 }
Me@178 376
Me@178 377
Me@178 378 /*Allocates memory from the external system -- higher overhead
Me@178 379 *
Me@178 380 *Because of Linux's malloc throwing bizarre random faults when malloc is
Me@178 381 * used inside a VMS virtual processor, have to pass this as a request and
Me@178 382 * have the core loop do it when it gets around to it -- will look for these
Me@178 383 * chores leftover from the previous animation of masterVP the next time it
Me@178 384 * goes to animate the masterVP -- so it takes two separate masterVP
Me@178 385 * animations, separated by work, to complete an external malloc or
Me@178 386 * external free request.
Me@178 387 *
Me@178 388 *Thinking core loop accepts signals -- just looks if signal-location is
Me@178 389 * empty or not --
Me@178 390 */
Me@178 391 void *
Me@178 392 VMS__malloc_in_ext( size_t sizeRequested )
Me@178 393 {
Me@178 394 /*
Me@178 395 //This is running in the master, so no chance for multiple cores to be
Me@178 396 // competing for the core's flag.
Me@178 397 if( *(_VMSMasterEnv->coreLoopSignalAddr[ 0 ]) != 0 )
Me@178 398 { //something has already signalled to core loop, so save the signal
Me@178 399 // and look, next time master animated, to see if can send it.
Me@178 400 //Note, the addr to put a signal is in the coreloop's frame, so just
Me@178 401 // checks it each time through -- make it volatile to avoid GCC
Me@178 402 // optimizations -- it's a coreloop local var that only changes
Me@178 403 // after jumping away. The signal includes the addr to send the
Me@178 404 //return to -- even if just empty return completion-signal
Me@178 405 //
Me@178 406 //save the signal in some queue that the master looks at each time
Me@178 407 // it starts up -- one loc says if empty for fast common case --
Me@178 408 //something like that -- want to hide this inside this call -- but
Me@178 409 // think this has to come as a request -- req handler gives procr
Me@178 410 // back to master loop, which gives it back to req handler at point
Me@178 411 // it sees that core loop has sent return signal. Something like
Me@178 412 // that.
Me@178 413 saveTheSignal
Me@178 414
Me@178 415 }
Me@178 416 coreSigData->type = malloc;
Me@178 417 coreSigData->sizeToMalloc = sizeRequested;
Me@178 418 coreSigData->locToSignalCompletion = &figureOut;
Me@178 419 _VMSMasterEnv->coreLoopSignals[ 0 ] = coreSigData;
Me@178 420 */
Me@178 421 //just risk system-stack faults until get this figured out
Me@178 422 return malloc( sizeRequested );
Me@178 423 }
Me@178 424
Me@178 425
Me@178 426 /*Frees memory that was allocated in the external system -- higher overhead
Me@178 427 *
Me@178 428 *As noted in external malloc comment, this is clunky 'cause the free has
Me@178 429 * to be called in the core loop.
Me@178 430 */
Me@178 431 void
Me@178 432 VMS__free_in_ext( void *ptrToFree )
Me@178 433 {
Me@178 434 //just risk system-stack faults until get this figured out
Me@178 435 free( ptrToFree );
Me@178 436
Me@178 437 //TODO: fix this -- so
Me@178 438 }
Me@178 439
Me@178 440
Me@178 441 /*Designed to be called from the main thread outside of VMS, during init
Me@178 442 */
Me@178 443 MallocProlog *
Me@178 444 VMS_ext__create_free_list()
Me@178 445 { MallocProlog *freeListHead, *firstChunk;
Me@178 446
Me@178 447 //Note, this is running in the main thread -- all increases in malloc
Me@178 448 // mem and all frees of it must be done in this thread, with the
Me@178 449 // thread's original stack available
Me@178 450 freeListHead = malloc( sizeof(MallocProlog) );
Me@178 451 firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE );
Me@178 452 if( firstChunk == NULL ) {printf("malloc error\n"); exit(1);}
Me@178 453
Me@178 454 //Touch memory to avoid page faults
Me@178 455 void *ptr,*endPtr;
Me@178 456 endPtr = (void*)firstChunk+MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE;
Me@178 457 for(ptr = firstChunk; ptr < endPtr; ptr+=PAGE_SIZE)
Me@178 458 {
Me@178 459 *(char*)ptr = 0;
Me@178 460 }
Me@178 461
Me@178 462 freeListHead->prevChunkInFreeList = NULL;
Me@178 463 //Use this addr to free the heap when cleanup
Me@178 464 freeListHead->nextLowerInMem = firstChunk;
Me@178 465 //to identify top-of-heap elem, compare this addr to elem's next higher
Me@178 466 freeListHead->nextHigherInMem = (void*)( (uintptr_t)firstChunk +
Me@178 467 MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE);
Me@178 468 freeListHead->nextChunkInFreeList = firstChunk;
Me@178 469
Me@178 470 firstChunk->nextChunkInFreeList = NULL;
Me@178 471 firstChunk->prevChunkInFreeList = freeListHead;
Me@178 472 //next Higher has to be set to top of chunk, so can calc size in malloc
Me@178 473 firstChunk->nextHigherInMem = (void*)( (uintptr_t)firstChunk +
Me@178 474 MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE);
Me@178 475 firstChunk->nextLowerInMem = NULL; //identifies as bott of heap
Me@178 476
Me@178 477 _VMSMasterEnv->amtOfOutstandingMem = 0; //none allocated yet
Me@178 478
Me@178 479 return freeListHead;
Me@178 480 }
Me@178 481
Me@178 482
Me@178 483 /*Designed to be called from the main thread outside of VMS, during cleanup
Me@178 484 */
Me@178 485 void
Me@178 486 VMS_ext__free_free_list( MallocProlog *freeListHead )
Me@178 487 {
Me@178 488 //stashed a ptr to the one and only bug chunk malloc'd from OS in the
Me@178 489 // free list head's next lower in mem pointer
Me@178 490 free( freeListHead->nextLowerInMem );
Me@178 491
Me@178 492 //don't free the head -- it'll be in an array eventually -- free whole
Me@178 493 // array when all the free lists linked from it have already been freed
Me@178 494 }
Me@178 495