annotate vmalloc.c @ 208:eaf7e4c58c9e

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