Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
diff 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 |
line diff
1.1 --- a/vmalloc.c Thu Oct 06 16:24:17 2011 +0200 1.2 +++ b/vmalloc.c Wed Jan 04 16:10:11 2012 -0800 1.3 @@ -1,495 +1,495 @@ 1.4 -/* 1.5 - * Copyright 2009 OpenSourceCodeStewardshipFoundation.org 1.6 - * Licensed under GNU General Public License version 2 1.7 - * 1.8 - * Author: seanhalle@yahoo.com 1.9 - * 1.10 - * Created on November 14, 2009, 9:07 PM 1.11 - */ 1.12 - 1.13 -#include <malloc.h> 1.14 -#include <inttypes.h> 1.15 -#include <stdlib.h> 1.16 -#include <stdio.h> 1.17 - 1.18 -#include "VMS.h" 1.19 -#include "Histogram/Histogram.h" 1.20 - 1.21 -/*Helper function 1.22 - *Insert a newly generated free chunk into the first spot on the free list. 1.23 - * The chunk is cast as a MallocProlog, so the various pointers in it are 1.24 - * accessed with C's help -- and the size of the prolog is easily added to 1.25 - * the pointer when a chunk is returned to the app -- so C handles changes 1.26 - * in pointer sizes among machines. 1.27 - * 1.28 - *The list head is a normal MallocProlog struct -- identified by its 1.29 - * prevChunkInFreeList being NULL -- the only one. 1.30 - * 1.31 - *The end of the list is identified by next chunk being NULL, as usual. 1.32 - */ 1.33 -void inline 1.34 -add_chunk_to_free_list( MallocProlog *chunk, MallocProlog *listHead ) 1.35 - { 1.36 - chunk->nextChunkInFreeList = listHead->nextChunkInFreeList; 1.37 - if( chunk->nextChunkInFreeList != NULL ) //if not last in free list 1.38 - chunk->nextChunkInFreeList->prevChunkInFreeList = chunk; 1.39 - chunk->prevChunkInFreeList = listHead; 1.40 - listHead->nextChunkInFreeList = chunk; 1.41 - } 1.42 - 1.43 - 1.44 -/*This is sequential code, meant to only be called from the Master, not from 1.45 - * any slave VPs. 1.46 - *Search down list, checking size by the nextHigherInMem pointer, to find 1.47 - * first chunk bigger than size needed. 1.48 - *Shave off the extra and make it into a new free-list element, hook it in 1.49 - * then return the address of the found element plus size of prolog. 1.50 - * 1.51 - *Will find a 1.52 - */ 1.53 -void *VMS__malloc( size_t sizeRequested ) 1.54 - { MallocProlog *foundElem = NULL, *currElem, *newElem; 1.55 - ssize_t amountExtra, sizeConsumed,sizeOfFound; 1.56 - uint32 foundElemIsTopOfHeap; 1.57 - 1.58 - //============================= MEASUREMENT STUFF ======================== 1.59 - #ifdef MEAS__TIME_MALLOC 1.60 - int32 startStamp, endStamp; 1.61 - saveLowTimeStampCountInto( startStamp ); 1.62 - #endif 1.63 - //======================================================================== 1.64 - 1.65 - //step up the size to be aligned at 16-byte boundary, prob better ways 1.66 - sizeRequested = (sizeRequested + 16) & ~15; 1.67 - currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList; 1.68 - 1.69 - while( currElem != NULL ) 1.70 - { //check if size of currElem is big enough 1.71 - sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); 1.72 - amountExtra = sizeOfFound - sizeRequested - sizeof(MallocProlog); 1.73 - if( amountExtra > 0 ) 1.74 - { //found it, get out of loop 1.75 - foundElem = currElem; 1.76 - currElem = NULL; 1.77 - } 1.78 - else 1.79 - currElem = currElem->nextChunkInFreeList; 1.80 - } 1.81 - 1.82 - if( foundElem == NULL ) 1.83 - { ERROR("\nmalloc failed\n") 1.84 - return (void *)NULL; //indicates malloc failed 1.85 - } 1.86 - //Using a kludge to identify the element that is the top chunk in the 1.87 - // heap -- saving top-of-heap addr in head's nextHigherInMem -- and 1.88 - // save addr of start of heap in head's nextLowerInMem 1.89 - //Will handle top of Heap specially 1.90 - foundElemIsTopOfHeap = foundElem->nextHigherInMem == 1.91 - _VMSMasterEnv->freeListHead->nextHigherInMem; 1.92 - 1.93 - //before shave off and try to insert new elem, remove found elem 1.94 - //note, foundElem will never be the head, so always has valid prevChunk 1.95 - foundElem->prevChunkInFreeList->nextChunkInFreeList = 1.96 - foundElem->nextChunkInFreeList; 1.97 - if( foundElem->nextChunkInFreeList != NULL ) 1.98 - { foundElem->nextChunkInFreeList->prevChunkInFreeList = 1.99 - foundElem->prevChunkInFreeList; 1.100 - } 1.101 - foundElem->prevChunkInFreeList = NULL;//indicates elem currently allocated 1.102 - 1.103 - //if enough, turn extra into new elem & insert it 1.104 - if( amountExtra > 64 ) 1.105 - { //make new elem by adding to addr of curr elem then casting 1.106 - sizeConsumed = sizeof(MallocProlog) + sizeRequested; 1.107 - newElem = (MallocProlog *)( (uintptr_t)foundElem + sizeConsumed ); 1.108 - newElem->nextLowerInMem = foundElem; //This is evil (but why?) 1.109 - newElem->nextHigherInMem = foundElem->nextHigherInMem; //This is evil (but why?) 1.110 - foundElem->nextHigherInMem = newElem; 1.111 - if( ! foundElemIsTopOfHeap ) 1.112 - { //there is no next higher for top of heap, so can't write to it 1.113 - newElem->nextHigherInMem->nextLowerInMem = newElem; 1.114 - } 1.115 - add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead ); 1.116 - } 1.117 - else 1.118 - { 1.119 - sizeConsumed = sizeOfFound; 1.120 - } 1.121 - _VMSMasterEnv->amtOfOutstandingMem += sizeConsumed; 1.122 - 1.123 - //============================= MEASUREMENT STUFF ======================== 1.124 - #ifdef MEAS__TIME_MALLOC 1.125 - saveLowTimeStampCountInto( endStamp ); 1.126 - addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist ); 1.127 - #endif 1.128 - //======================================================================== 1.129 - 1.130 - //skip over the prolog by adding its size to the pointer return 1.131 - return (void*)((uintptr_t)foundElem + sizeof(MallocProlog)); 1.132 - } 1.133 - 1.134 -/*This is sequential code, meant to only be called from the Master, not from 1.135 - * any slave VPs. 1.136 - *Search down list, checking size by the nextHigherInMem pointer, to find 1.137 - * first chunk bigger than size needed. 1.138 - *Shave off the extra and make it into a new free-list element, hook it in 1.139 - * then return the address of the found element plus size of prolog. 1.140 - * 1.141 - * The difference to the regular malloc is, that all the allocated chunks are 1.142 - * aligned and padded to the size of a CACHE_LINE. Thus creating a new chunk 1.143 - * before the aligned chunk. 1.144 - */ 1.145 -void *VMS__malloc_aligned( size_t sizeRequested ) 1.146 - { MallocProlog *foundElem = NULL, *currElem, *newElem; 1.147 - ssize_t amountExtra, sizeConsumed,sizeOfFound,prevAmount; 1.148 - uint32 foundElemIsTopOfHeap; 1.149 - 1.150 - //============================= MEASUREMENT STUFF ======================== 1.151 - #ifdef MEAS__TIME_MALLOC 1.152 - uint32 startStamp, endStamp; 1.153 - saveLowTimeStampCountInto( startStamp ); 1.154 - #endif 1.155 - //======================================================================== 1.156 - 1.157 - //step up the size to be multiple of the cache line size 1.158 - sizeRequested = (sizeRequested + CACHE_LINE) & ~(CACHE_LINE-1); 1.159 - currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList; 1.160 - 1.161 - while( currElem != NULL ) 1.162 - { //check if size of currElem is big enough 1.163 - sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); 1.164 - amountExtra = sizeOfFound - sizeRequested - sizeof(MallocProlog); 1.165 - if( amountExtra > 0 ) 1.166 - { 1.167 - //look if the found element is already aligned 1.168 - if((((uintptr_t)currElem+sizeof(MallocProlog)) & (uintptr_t)(CACHE_LINE-1)) == 0){ 1.169 - //found it, get out of loop 1.170 - foundElem = currElem; 1.171 - break; 1.172 - }else{ 1.173 - //find first aligned address and check if it's still big enough 1.174 - //check also if the space before the aligned address is big enough 1.175 - //for a new element 1.176 - void *firstAlignedAddr = (void*)(((uintptr_t)currElem + 2*CACHE_LINE) & ~((uintptr_t)(CACHE_LINE-1))); 1.177 - prevAmount = (uintptr_t)firstAlignedAddr - (uintptr_t)currElem; 1.178 - sizeOfFound=(uintptr_t)currElem->nextHigherInMem -(uintptr_t)firstAlignedAddr + sizeof(MallocProlog); 1.179 - amountExtra= sizeOfFound - sizeRequested - sizeof(MallocProlog); 1.180 - if(prevAmount > 2*sizeof(MallocProlog) && amountExtra > 0 ){ 1.181 - //found suitable element 1.182 - //create new previous element and exit loop 1.183 - MallocProlog *newAlignedElem = (MallocProlog*)firstAlignedAddr - 1; 1.184 - 1.185 - //insert new element into free list 1.186 - if(currElem->nextChunkInFreeList != NULL) 1.187 - currElem->nextChunkInFreeList->prevChunkInFreeList = newAlignedElem; 1.188 - newAlignedElem->prevChunkInFreeList = currElem; 1.189 - newAlignedElem->nextChunkInFreeList = currElem->nextChunkInFreeList; 1.190 - currElem->nextChunkInFreeList = newAlignedElem; 1.191 - 1.192 - //set higherInMem and lowerInMem 1.193 - newAlignedElem->nextHigherInMem = currElem->nextHigherInMem; 1.194 - foundElemIsTopOfHeap = currElem->nextHigherInMem == 1.195 - _VMSMasterEnv->freeListHead->nextHigherInMem; 1.196 - if(!foundElemIsTopOfHeap) 1.197 - currElem->nextHigherInMem->nextLowerInMem = newAlignedElem; 1.198 - currElem->nextHigherInMem = newAlignedElem; 1.199 - newAlignedElem->nextLowerInMem = currElem; 1.200 - 1.201 - //Found new element leaving loop 1.202 - foundElem = newAlignedElem; 1.203 - break; 1.204 - } 1.205 - } 1.206 - 1.207 - } 1.208 - currElem = currElem->nextChunkInFreeList; 1.209 - } 1.210 - 1.211 - if( foundElem == NULL ) 1.212 - { ERROR("\nmalloc failed\n") 1.213 - return (void *)NULL; //indicates malloc failed 1.214 - } 1.215 - //Using a kludge to identify the element that is the top chunk in the 1.216 - // heap -- saving top-of-heap addr in head's nextHigherInMem -- and 1.217 - // save addr of start of heap in head's nextLowerInMem 1.218 - //Will handle top of Heap specially 1.219 - foundElemIsTopOfHeap = foundElem->nextHigherInMem == 1.220 - _VMSMasterEnv->freeListHead->nextHigherInMem; 1.221 - 1.222 - //before shave off and try to insert new elem, remove found elem 1.223 - //note, foundElem will never be the head, so always has valid prevChunk 1.224 - foundElem->prevChunkInFreeList->nextChunkInFreeList = 1.225 - foundElem->nextChunkInFreeList; 1.226 - if( foundElem->nextChunkInFreeList != NULL ) 1.227 - { foundElem->nextChunkInFreeList->prevChunkInFreeList = 1.228 - foundElem->prevChunkInFreeList; 1.229 - } 1.230 - foundElem->prevChunkInFreeList = NULL;//indicates elem currently allocated 1.231 - 1.232 - //if enough, turn extra into new elem & insert it 1.233 - if( amountExtra > 64 ) 1.234 - { //make new elem by adding to addr of curr elem then casting 1.235 - sizeConsumed = sizeof(MallocProlog) + sizeRequested; 1.236 - newElem = (MallocProlog *)( (uintptr_t)foundElem + sizeConsumed ); 1.237 - newElem->nextHigherInMem = foundElem->nextHigherInMem; 1.238 - newElem->nextLowerInMem = foundElem; 1.239 - foundElem->nextHigherInMem = newElem; 1.240 - 1.241 - if( ! foundElemIsTopOfHeap ) 1.242 - { //there is no next higher for top of heap, so can't write to it 1.243 - newElem->nextHigherInMem->nextLowerInMem = newElem; 1.244 - } 1.245 - add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead ); 1.246 - } 1.247 - else 1.248 - { 1.249 - sizeConsumed = sizeOfFound; 1.250 - } 1.251 - _VMSMasterEnv->amtOfOutstandingMem += sizeConsumed; 1.252 - 1.253 - //============================= MEASUREMENT STUFF ======================== 1.254 - #ifdef MEAS__TIME_MALLOC 1.255 - saveLowTimeStampCountInto( endStamp ); 1.256 - addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist ); 1.257 - #endif 1.258 - //======================================================================== 1.259 - 1.260 - //skip over the prolog by adding its size to the pointer return 1.261 - return (void*)((uintptr_t)foundElem + sizeof(MallocProlog)); 1.262 - } 1.263 - 1.264 - 1.265 -/*This is sequential code -- only to be called from the Master 1.266 - * When free, subtract the size of prolog from pointer, then cast it to a 1.267 - * MallocProlog. Then check the nextLower and nextHigher chunks to see if 1.268 - * one or both are also free, and coalesce if so, and if neither free, then 1.269 - * add this one to free-list. 1.270 - */ 1.271 -void 1.272 -VMS__free( void *ptrToFree ) 1.273 - { MallocProlog *elemToFree, *nextLowerElem, *nextHigherElem; 1.274 - size_t sizeOfElem; 1.275 - uint32 lowerExistsAndIsFree, higherExistsAndIsFree; 1.276 - 1.277 - //============================= MEASUREMENT STUFF ======================== 1.278 - #ifdef MEAS__TIME_MALLOC 1.279 - int32 startStamp, endStamp; 1.280 - saveLowTimeStampCountInto( startStamp ); 1.281 - #endif 1.282 - //======================================================================== 1.283 - 1.284 - if( ptrToFree < (void*)_VMSMasterEnv->freeListHead->nextLowerInMem || 1.285 - ptrToFree > (void*)_VMSMasterEnv->freeListHead->nextHigherInMem ) 1.286 - { //outside the range of data owned by VMS's malloc, so do nothing 1.287 - return; 1.288 - } 1.289 - //subtract size of prolog to get pointer to prolog, then cast 1.290 - elemToFree = (MallocProlog *)((uintptr_t)ptrToFree - sizeof(MallocProlog)); 1.291 - sizeOfElem =(size_t)((uintptr_t)elemToFree->nextHigherInMem-(uintptr_t)elemToFree); 1.292 - 1.293 - if( elemToFree->prevChunkInFreeList != NULL ) 1.294 - { printf( "error: freeing same element twice!" ); exit(1); 1.295 - } 1.296 - 1.297 - _VMSMasterEnv->amtOfOutstandingMem -= sizeOfElem; 1.298 - 1.299 - nextLowerElem = elemToFree->nextLowerInMem; 1.300 - nextHigherElem = elemToFree->nextHigherInMem; 1.301 - 1.302 - if( nextHigherElem == NULL ) 1.303 - higherExistsAndIsFree = FALSE; 1.304 - else //okay exists, now check if in the free-list by checking back ptr 1.305 - higherExistsAndIsFree = (nextHigherElem->prevChunkInFreeList != NULL); 1.306 - 1.307 - if( nextLowerElem == NULL ) 1.308 - lowerExistsAndIsFree = FALSE; 1.309 - else //okay, it exists, now check if it's free 1.310 - lowerExistsAndIsFree = (nextLowerElem->prevChunkInFreeList != NULL); 1.311 - 1.312 - 1.313 - //now, know what exists and what's free 1.314 - if( lowerExistsAndIsFree ) 1.315 - { if( higherExistsAndIsFree ) 1.316 - { //both exist and are free, so coalesce all three 1.317 - //First, remove higher from free-list 1.318 - nextHigherElem->prevChunkInFreeList->nextChunkInFreeList = 1.319 - nextHigherElem->nextChunkInFreeList; 1.320 - if( nextHigherElem->nextChunkInFreeList != NULL ) //end-of-list? 1.321 - nextHigherElem->nextChunkInFreeList->prevChunkInFreeList = 1.322 - nextHigherElem->prevChunkInFreeList; 1.323 - //Now, fix-up sequence-in-mem list -- by side-effect, this also 1.324 - // changes size of the lower elem, which is still in free-list 1.325 - nextLowerElem->nextHigherInMem = nextHigherElem->nextHigherInMem; 1.326 - if( nextHigherElem->nextHigherInMem != 1.327 - _VMSMasterEnv->freeListHead->nextHigherInMem ) 1.328 - nextHigherElem->nextHigherInMem->nextLowerInMem = nextLowerElem; 1.329 - //notice didn't do anything to elemToFree -- it simply is no 1.330 - // longer reachable from any of the lists. Wonder if could be a 1.331 - // security leak because left valid addresses in it, 1.332 - // but don't care for now. 1.333 - } 1.334 - else 1.335 - { //lower is the only of the two that exists and is free, 1.336 - //In this case, no adjustment to free-list, just change mem-list. 1.337 - // By side-effect, changes size of the lower elem 1.338 - nextLowerElem->nextHigherInMem = elemToFree->nextHigherInMem; 1.339 - if( elemToFree->nextHigherInMem != 1.340 - _VMSMasterEnv->freeListHead->nextHigherInMem ) 1.341 - elemToFree->nextHigherInMem->nextLowerInMem = nextLowerElem; 1.342 - } 1.343 - } 1.344 - else 1.345 - { //lower either doesn't exist or isn't free, so check higher 1.346 - if( higherExistsAndIsFree ) 1.347 - { //higher exists and is the only of the two free 1.348 - //First, in free-list, replace higher elem with the one to free 1.349 - elemToFree->nextChunkInFreeList=nextHigherElem->nextChunkInFreeList; 1.350 - elemToFree->prevChunkInFreeList=nextHigherElem->prevChunkInFreeList; 1.351 - elemToFree->prevChunkInFreeList->nextChunkInFreeList = elemToFree; 1.352 - if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? 1.353 - elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; 1.354 - //Now chg mem-list. By side-effect, changes size of elemToFree 1.355 - elemToFree->nextHigherInMem = nextHigherElem->nextHigherInMem; 1.356 - if( elemToFree->nextHigherInMem != 1.357 - _VMSMasterEnv->freeListHead->nextHigherInMem ) 1.358 - elemToFree->nextHigherInMem->nextLowerInMem = elemToFree; 1.359 - } 1.360 - else 1.361 - { //neither lower nor higher is availabe to coalesce so add to list 1.362 - // this makes prev chunk ptr non-null, which indicates it's free 1.363 - elemToFree->nextChunkInFreeList = 1.364 - _VMSMasterEnv->freeListHead->nextChunkInFreeList; 1.365 - _VMSMasterEnv->freeListHead->nextChunkInFreeList = elemToFree; 1.366 - if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? 1.367 - elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; 1.368 - elemToFree->prevChunkInFreeList = _VMSMasterEnv->freeListHead; 1.369 - } 1.370 - } 1.371 - //============================= MEASUREMENT STUFF ======================== 1.372 - #ifdef MEAS__TIME_MALLOC 1.373 - saveLowTimeStampCountInto( endStamp ); 1.374 - addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->freeTimeHist ); 1.375 - #endif 1.376 - //======================================================================== 1.377 - 1.378 - } 1.379 - 1.380 - 1.381 -/*Allocates memory from the external system -- higher overhead 1.382 - * 1.383 - *Because of Linux's malloc throwing bizarre random faults when malloc is 1.384 - * used inside a VMS virtual processor, have to pass this as a request and 1.385 - * have the core loop do it when it gets around to it -- will look for these 1.386 - * chores leftover from the previous animation of masterVP the next time it 1.387 - * goes to animate the masterVP -- so it takes two separate masterVP 1.388 - * animations, separated by work, to complete an external malloc or 1.389 - * external free request. 1.390 - * 1.391 - *Thinking core loop accepts signals -- just looks if signal-location is 1.392 - * empty or not -- 1.393 - */ 1.394 -void * 1.395 -VMS__malloc_in_ext( size_t sizeRequested ) 1.396 - { 1.397 - /* 1.398 - //This is running in the master, so no chance for multiple cores to be 1.399 - // competing for the core's flag. 1.400 - if( *(_VMSMasterEnv->coreLoopSignalAddr[ 0 ]) != 0 ) 1.401 - { //something has already signalled to core loop, so save the signal 1.402 - // and look, next time master animated, to see if can send it. 1.403 - //Note, the addr to put a signal is in the coreloop's frame, so just 1.404 - // checks it each time through -- make it volatile to avoid GCC 1.405 - // optimizations -- it's a coreloop local var that only changes 1.406 - // after jumping away. The signal includes the addr to send the 1.407 - //return to -- even if just empty return completion-signal 1.408 - // 1.409 - //save the signal in some queue that the master looks at each time 1.410 - // it starts up -- one loc says if empty for fast common case -- 1.411 - //something like that -- want to hide this inside this call -- but 1.412 - // think this has to come as a request -- req handler gives procr 1.413 - // back to master loop, which gives it back to req handler at point 1.414 - // it sees that core loop has sent return signal. Something like 1.415 - // that. 1.416 - saveTheSignal 1.417 - 1.418 - } 1.419 - coreSigData->type = malloc; 1.420 - coreSigData->sizeToMalloc = sizeRequested; 1.421 - coreSigData->locToSignalCompletion = &figureOut; 1.422 - _VMSMasterEnv->coreLoopSignals[ 0 ] = coreSigData; 1.423 - */ 1.424 - //just risk system-stack faults until get this figured out 1.425 - return malloc( sizeRequested ); 1.426 - } 1.427 - 1.428 - 1.429 -/*Frees memory that was allocated in the external system -- higher overhead 1.430 - * 1.431 - *As noted in external malloc comment, this is clunky 'cause the free has 1.432 - * to be called in the core loop. 1.433 - */ 1.434 -void 1.435 -VMS__free_in_ext( void *ptrToFree ) 1.436 - { 1.437 - //just risk system-stack faults until get this figured out 1.438 - free( ptrToFree ); 1.439 - 1.440 - //TODO: fix this -- so 1.441 - } 1.442 - 1.443 - 1.444 -/*Designed to be called from the main thread outside of VMS, during init 1.445 - */ 1.446 -MallocProlog * 1.447 -VMS_ext__create_free_list() 1.448 - { MallocProlog *freeListHead, *firstChunk; 1.449 - 1.450 - //Note, this is running in the main thread -- all increases in malloc 1.451 - // mem and all frees of it must be done in this thread, with the 1.452 - // thread's original stack available 1.453 - freeListHead = malloc( sizeof(MallocProlog) ); 1.454 - firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE ); 1.455 - if( firstChunk == NULL ) {printf("malloc error\n"); exit(1);} 1.456 - 1.457 - //Touch memory to avoid page faults 1.458 - void *ptr,*endPtr; 1.459 - endPtr = (void*)firstChunk+MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE; 1.460 - for(ptr = firstChunk; ptr < endPtr; ptr+=PAGE_SIZE) 1.461 - { 1.462 - *(char*)ptr = 0; 1.463 - } 1.464 - 1.465 - freeListHead->prevChunkInFreeList = NULL; 1.466 - //Use this addr to free the heap when cleanup 1.467 - freeListHead->nextLowerInMem = firstChunk; 1.468 - //to identify top-of-heap elem, compare this addr to elem's next higher 1.469 - freeListHead->nextHigherInMem = (void*)( (uintptr_t)firstChunk + 1.470 - MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE); 1.471 - freeListHead->nextChunkInFreeList = firstChunk; 1.472 - 1.473 - firstChunk->nextChunkInFreeList = NULL; 1.474 - firstChunk->prevChunkInFreeList = freeListHead; 1.475 - //next Higher has to be set to top of chunk, so can calc size in malloc 1.476 - firstChunk->nextHigherInMem = (void*)( (uintptr_t)firstChunk + 1.477 - MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE); 1.478 - firstChunk->nextLowerInMem = NULL; //identifies as bott of heap 1.479 - 1.480 - _VMSMasterEnv->amtOfOutstandingMem = 0; //none allocated yet 1.481 - 1.482 - return freeListHead; 1.483 - } 1.484 - 1.485 - 1.486 -/*Designed to be called from the main thread outside of VMS, during cleanup 1.487 - */ 1.488 -void 1.489 -VMS_ext__free_free_list( MallocProlog *freeListHead ) 1.490 - { 1.491 - //stashed a ptr to the one and only bug chunk malloc'd from OS in the 1.492 - // free list head's next lower in mem pointer 1.493 - free( freeListHead->nextLowerInMem ); 1.494 - 1.495 - //don't free the head -- it'll be in an array eventually -- free whole 1.496 - // array when all the free lists linked from it have already been freed 1.497 - } 1.498 - 1.499 +/* 1.500 + * Copyright 2009 OpenSourceCodeStewardshipFoundation.org 1.501 + * Licensed under GNU General Public License version 2 1.502 + * 1.503 + * Author: seanhalle@yahoo.com 1.504 + * 1.505 + * Created on November 14, 2009, 9:07 PM 1.506 + */ 1.507 + 1.508 +#include <malloc.h> 1.509 +#include <inttypes.h> 1.510 +#include <stdlib.h> 1.511 +#include <stdio.h> 1.512 + 1.513 +#include "VMS.h" 1.514 +#include "Histogram/Histogram.h" 1.515 + 1.516 +/*Helper function 1.517 + *Insert a newly generated free chunk into the first spot on the free list. 1.518 + * The chunk is cast as a MallocProlog, so the various pointers in it are 1.519 + * accessed with C's help -- and the size of the prolog is easily added to 1.520 + * the pointer when a chunk is returned to the app -- so C handles changes 1.521 + * in pointer sizes among machines. 1.522 + * 1.523 + *The list head is a normal MallocProlog struct -- identified by its 1.524 + * prevChunkInFreeList being NULL -- the only one. 1.525 + * 1.526 + *The end of the list is identified by next chunk being NULL, as usual. 1.527 + */ 1.528 +void inline 1.529 +add_chunk_to_free_list( MallocProlog *chunk, MallocProlog *listHead ) 1.530 + { 1.531 + chunk->nextChunkInFreeList = listHead->nextChunkInFreeList; 1.532 + if( chunk->nextChunkInFreeList != NULL ) //if not last in free list 1.533 + chunk->nextChunkInFreeList->prevChunkInFreeList = chunk; 1.534 + chunk->prevChunkInFreeList = listHead; 1.535 + listHead->nextChunkInFreeList = chunk; 1.536 + } 1.537 + 1.538 + 1.539 +/*This is sequential code, meant to only be called from the Master, not from 1.540 + * any slave VPs. 1.541 + *Search down list, checking size by the nextHigherInMem pointer, to find 1.542 + * first chunk bigger than size needed. 1.543 + *Shave off the extra and make it into a new free-list element, hook it in 1.544 + * then return the address of the found element plus size of prolog. 1.545 + * 1.546 + *Will find a 1.547 + */ 1.548 +void *VMS__malloc( size_t sizeRequested ) 1.549 + { MallocProlog *foundElem = NULL, *currElem, *newElem; 1.550 + ssize_t amountExtra, sizeConsumed,sizeOfFound; 1.551 + uint32 foundElemIsTopOfHeap; 1.552 + 1.553 + //============================= MEASUREMENT STUFF ======================== 1.554 + #ifdef MEAS__TIME_MALLOC 1.555 + int32 startStamp, endStamp; 1.556 + saveLowTimeStampCountInto( startStamp ); 1.557 + #endif 1.558 + //======================================================================== 1.559 + 1.560 + //step up the size to be aligned at 16-byte boundary, prob better ways 1.561 + sizeRequested = (sizeRequested + 16) & ~15; 1.562 + currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList; 1.563 + 1.564 + while( currElem != NULL ) 1.565 + { //check if size of currElem is big enough 1.566 + sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); 1.567 + amountExtra = sizeOfFound - sizeRequested - sizeof(MallocProlog); 1.568 + if( amountExtra > 0 ) 1.569 + { //found it, get out of loop 1.570 + foundElem = currElem; 1.571 + currElem = NULL; 1.572 + } 1.573 + else 1.574 + currElem = currElem->nextChunkInFreeList; 1.575 + } 1.576 + 1.577 + if( foundElem == NULL ) 1.578 + { ERROR("\nmalloc failed\n") 1.579 + return (void *)NULL; //indicates malloc failed 1.580 + } 1.581 + //Using a kludge to identify the element that is the top chunk in the 1.582 + // heap -- saving top-of-heap addr in head's nextHigherInMem -- and 1.583 + // save addr of start of heap in head's nextLowerInMem 1.584 + //Will handle top of Heap specially 1.585 + foundElemIsTopOfHeap = foundElem->nextHigherInMem == 1.586 + _VMSMasterEnv->freeListHead->nextHigherInMem; 1.587 + 1.588 + //before shave off and try to insert new elem, remove found elem 1.589 + //note, foundElem will never be the head, so always has valid prevChunk 1.590 + foundElem->prevChunkInFreeList->nextChunkInFreeList = 1.591 + foundElem->nextChunkInFreeList; 1.592 + if( foundElem->nextChunkInFreeList != NULL ) 1.593 + { foundElem->nextChunkInFreeList->prevChunkInFreeList = 1.594 + foundElem->prevChunkInFreeList; 1.595 + } 1.596 + foundElem->prevChunkInFreeList = NULL;//indicates elem currently allocated 1.597 + 1.598 + //if enough, turn extra into new elem & insert it 1.599 + if( amountExtra > 64 ) 1.600 + { //make new elem by adding to addr of curr elem then casting 1.601 + sizeConsumed = sizeof(MallocProlog) + sizeRequested; 1.602 + newElem = (MallocProlog *)( (uintptr_t)foundElem + sizeConsumed ); 1.603 + newElem->nextLowerInMem = foundElem; //This is evil (but why?) 1.604 + newElem->nextHigherInMem = foundElem->nextHigherInMem; //This is evil (but why?) 1.605 + foundElem->nextHigherInMem = newElem; 1.606 + if( ! foundElemIsTopOfHeap ) 1.607 + { //there is no next higher for top of heap, so can't write to it 1.608 + newElem->nextHigherInMem->nextLowerInMem = newElem; 1.609 + } 1.610 + add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead ); 1.611 + } 1.612 + else 1.613 + { 1.614 + sizeConsumed = sizeOfFound; 1.615 + } 1.616 + _VMSMasterEnv->amtOfOutstandingMem += sizeConsumed; 1.617 + 1.618 + //============================= MEASUREMENT STUFF ======================== 1.619 + #ifdef MEAS__TIME_MALLOC 1.620 + saveLowTimeStampCountInto( endStamp ); 1.621 + addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist ); 1.622 + #endif 1.623 + //======================================================================== 1.624 + 1.625 + //skip over the prolog by adding its size to the pointer return 1.626 + return (void*)((uintptr_t)foundElem + sizeof(MallocProlog)); 1.627 + } 1.628 + 1.629 +/*This is sequential code, meant to only be called from the Master, not from 1.630 + * any slave VPs. 1.631 + *Search down list, checking size by the nextHigherInMem pointer, to find 1.632 + * first chunk bigger than size needed. 1.633 + *Shave off the extra and make it into a new free-list element, hook it in 1.634 + * then return the address of the found element plus size of prolog. 1.635 + * 1.636 + * The difference to the regular malloc is, that all the allocated chunks are 1.637 + * aligned and padded to the size of a CACHE_LINE. Thus creating a new chunk 1.638 + * before the aligned chunk. 1.639 + */ 1.640 +void *VMS__malloc_aligned( size_t sizeRequested ) 1.641 + { MallocProlog *foundElem = NULL, *currElem, *newElem; 1.642 + ssize_t amountExtra, sizeConsumed,sizeOfFound,prevAmount; 1.643 + uint32 foundElemIsTopOfHeap; 1.644 + 1.645 + //============================= MEASUREMENT STUFF ======================== 1.646 + #ifdef MEAS__TIME_MALLOC 1.647 + uint32 startStamp, endStamp; 1.648 + saveLowTimeStampCountInto( startStamp ); 1.649 + #endif 1.650 + //======================================================================== 1.651 + 1.652 + //step up the size to be multiple of the cache line size 1.653 + sizeRequested = (sizeRequested + CACHE_LINE) & ~(CACHE_LINE-1); 1.654 + currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList; 1.655 + 1.656 + while( currElem != NULL ) 1.657 + { //check if size of currElem is big enough 1.658 + sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); 1.659 + amountExtra = sizeOfFound - sizeRequested - sizeof(MallocProlog); 1.660 + if( amountExtra > 0 ) 1.661 + { 1.662 + //look if the found element is already aligned 1.663 + if((((uintptr_t)currElem+sizeof(MallocProlog)) & (uintptr_t)(CACHE_LINE-1)) == 0){ 1.664 + //found it, get out of loop 1.665 + foundElem = currElem; 1.666 + break; 1.667 + }else{ 1.668 + //find first aligned address and check if it's still big enough 1.669 + //check also if the space before the aligned address is big enough 1.670 + //for a new element 1.671 + void *firstAlignedAddr = (void*)(((uintptr_t)currElem + 2*CACHE_LINE) & ~((uintptr_t)(CACHE_LINE-1))); 1.672 + prevAmount = (uintptr_t)firstAlignedAddr - (uintptr_t)currElem; 1.673 + sizeOfFound=(uintptr_t)currElem->nextHigherInMem -(uintptr_t)firstAlignedAddr + sizeof(MallocProlog); 1.674 + amountExtra= sizeOfFound - sizeRequested - sizeof(MallocProlog); 1.675 + if(prevAmount > 2*sizeof(MallocProlog) && amountExtra > 0 ){ 1.676 + //found suitable element 1.677 + //create new previous element and exit loop 1.678 + MallocProlog *newAlignedElem = (MallocProlog*)firstAlignedAddr - 1; 1.679 + 1.680 + //insert new element into free list 1.681 + if(currElem->nextChunkInFreeList != NULL) 1.682 + currElem->nextChunkInFreeList->prevChunkInFreeList = newAlignedElem; 1.683 + newAlignedElem->prevChunkInFreeList = currElem; 1.684 + newAlignedElem->nextChunkInFreeList = currElem->nextChunkInFreeList; 1.685 + currElem->nextChunkInFreeList = newAlignedElem; 1.686 + 1.687 + //set higherInMem and lowerInMem 1.688 + newAlignedElem->nextHigherInMem = currElem->nextHigherInMem; 1.689 + foundElemIsTopOfHeap = currElem->nextHigherInMem == 1.690 + _VMSMasterEnv->freeListHead->nextHigherInMem; 1.691 + if(!foundElemIsTopOfHeap) 1.692 + currElem->nextHigherInMem->nextLowerInMem = newAlignedElem; 1.693 + currElem->nextHigherInMem = newAlignedElem; 1.694 + newAlignedElem->nextLowerInMem = currElem; 1.695 + 1.696 + //Found new element leaving loop 1.697 + foundElem = newAlignedElem; 1.698 + break; 1.699 + } 1.700 + } 1.701 + 1.702 + } 1.703 + currElem = currElem->nextChunkInFreeList; 1.704 + } 1.705 + 1.706 + if( foundElem == NULL ) 1.707 + { ERROR("\nmalloc failed\n") 1.708 + return (void *)NULL; //indicates malloc failed 1.709 + } 1.710 + //Using a kludge to identify the element that is the top chunk in the 1.711 + // heap -- saving top-of-heap addr in head's nextHigherInMem -- and 1.712 + // save addr of start of heap in head's nextLowerInMem 1.713 + //Will handle top of Heap specially 1.714 + foundElemIsTopOfHeap = foundElem->nextHigherInMem == 1.715 + _VMSMasterEnv->freeListHead->nextHigherInMem; 1.716 + 1.717 + //before shave off and try to insert new elem, remove found elem 1.718 + //note, foundElem will never be the head, so always has valid prevChunk 1.719 + foundElem->prevChunkInFreeList->nextChunkInFreeList = 1.720 + foundElem->nextChunkInFreeList; 1.721 + if( foundElem->nextChunkInFreeList != NULL ) 1.722 + { foundElem->nextChunkInFreeList->prevChunkInFreeList = 1.723 + foundElem->prevChunkInFreeList; 1.724 + } 1.725 + foundElem->prevChunkInFreeList = NULL;//indicates elem currently allocated 1.726 + 1.727 + //if enough, turn extra into new elem & insert it 1.728 + if( amountExtra > 64 ) 1.729 + { //make new elem by adding to addr of curr elem then casting 1.730 + sizeConsumed = sizeof(MallocProlog) + sizeRequested; 1.731 + newElem = (MallocProlog *)( (uintptr_t)foundElem + sizeConsumed ); 1.732 + newElem->nextHigherInMem = foundElem->nextHigherInMem; 1.733 + newElem->nextLowerInMem = foundElem; 1.734 + foundElem->nextHigherInMem = newElem; 1.735 + 1.736 + if( ! foundElemIsTopOfHeap ) 1.737 + { //there is no next higher for top of heap, so can't write to it 1.738 + newElem->nextHigherInMem->nextLowerInMem = newElem; 1.739 + } 1.740 + add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead ); 1.741 + } 1.742 + else 1.743 + { 1.744 + sizeConsumed = sizeOfFound; 1.745 + } 1.746 + _VMSMasterEnv->amtOfOutstandingMem += sizeConsumed; 1.747 + 1.748 + //============================= MEASUREMENT STUFF ======================== 1.749 + #ifdef MEAS__TIME_MALLOC 1.750 + saveLowTimeStampCountInto( endStamp ); 1.751 + addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist ); 1.752 + #endif 1.753 + //======================================================================== 1.754 + 1.755 + //skip over the prolog by adding its size to the pointer return 1.756 + return (void*)((uintptr_t)foundElem + sizeof(MallocProlog)); 1.757 + } 1.758 + 1.759 + 1.760 +/*This is sequential code -- only to be called from the Master 1.761 + * When free, subtract the size of prolog from pointer, then cast it to a 1.762 + * MallocProlog. Then check the nextLower and nextHigher chunks to see if 1.763 + * one or both are also free, and coalesce if so, and if neither free, then 1.764 + * add this one to free-list. 1.765 + */ 1.766 +void 1.767 +VMS__free( void *ptrToFree ) 1.768 + { MallocProlog *elemToFree, *nextLowerElem, *nextHigherElem; 1.769 + size_t sizeOfElem; 1.770 + uint32 lowerExistsAndIsFree, higherExistsAndIsFree; 1.771 + 1.772 + //============================= MEASUREMENT STUFF ======================== 1.773 + #ifdef MEAS__TIME_MALLOC 1.774 + int32 startStamp, endStamp; 1.775 + saveLowTimeStampCountInto( startStamp ); 1.776 + #endif 1.777 + //======================================================================== 1.778 + 1.779 + if( ptrToFree < (void*)_VMSMasterEnv->freeListHead->nextLowerInMem || 1.780 + ptrToFree > (void*)_VMSMasterEnv->freeListHead->nextHigherInMem ) 1.781 + { //outside the range of data owned by VMS's malloc, so do nothing 1.782 + return; 1.783 + } 1.784 + //subtract size of prolog to get pointer to prolog, then cast 1.785 + elemToFree = (MallocProlog *)((uintptr_t)ptrToFree - sizeof(MallocProlog)); 1.786 + sizeOfElem =(size_t)((uintptr_t)elemToFree->nextHigherInMem-(uintptr_t)elemToFree); 1.787 + 1.788 + if( elemToFree->prevChunkInFreeList != NULL ) 1.789 + { printf( "error: freeing same element twice!" ); exit(1); 1.790 + } 1.791 + 1.792 + _VMSMasterEnv->amtOfOutstandingMem -= sizeOfElem; 1.793 + 1.794 + nextLowerElem = elemToFree->nextLowerInMem; 1.795 + nextHigherElem = elemToFree->nextHigherInMem; 1.796 + 1.797 + if( nextHigherElem == NULL ) 1.798 + higherExistsAndIsFree = FALSE; 1.799 + else //okay exists, now check if in the free-list by checking back ptr 1.800 + higherExistsAndIsFree = (nextHigherElem->prevChunkInFreeList != NULL); 1.801 + 1.802 + if( nextLowerElem == NULL ) 1.803 + lowerExistsAndIsFree = FALSE; 1.804 + else //okay, it exists, now check if it's free 1.805 + lowerExistsAndIsFree = (nextLowerElem->prevChunkInFreeList != NULL); 1.806 + 1.807 + 1.808 + //now, know what exists and what's free 1.809 + if( lowerExistsAndIsFree ) 1.810 + { if( higherExistsAndIsFree ) 1.811 + { //both exist and are free, so coalesce all three 1.812 + //First, remove higher from free-list 1.813 + nextHigherElem->prevChunkInFreeList->nextChunkInFreeList = 1.814 + nextHigherElem->nextChunkInFreeList; 1.815 + if( nextHigherElem->nextChunkInFreeList != NULL ) //end-of-list? 1.816 + nextHigherElem->nextChunkInFreeList->prevChunkInFreeList = 1.817 + nextHigherElem->prevChunkInFreeList; 1.818 + //Now, fix-up sequence-in-mem list -- by side-effect, this also 1.819 + // changes size of the lower elem, which is still in free-list 1.820 + nextLowerElem->nextHigherInMem = nextHigherElem->nextHigherInMem; 1.821 + if( nextHigherElem->nextHigherInMem != 1.822 + _VMSMasterEnv->freeListHead->nextHigherInMem ) 1.823 + nextHigherElem->nextHigherInMem->nextLowerInMem = nextLowerElem; 1.824 + //notice didn't do anything to elemToFree -- it simply is no 1.825 + // longer reachable from any of the lists. Wonder if could be a 1.826 + // security leak because left valid addresses in it, 1.827 + // but don't care for now. 1.828 + } 1.829 + else 1.830 + { //lower is the only of the two that exists and is free, 1.831 + //In this case, no adjustment to free-list, just change mem-list. 1.832 + // By side-effect, changes size of the lower elem 1.833 + nextLowerElem->nextHigherInMem = elemToFree->nextHigherInMem; 1.834 + if( elemToFree->nextHigherInMem != 1.835 + _VMSMasterEnv->freeListHead->nextHigherInMem ) 1.836 + elemToFree->nextHigherInMem->nextLowerInMem = nextLowerElem; 1.837 + } 1.838 + } 1.839 + else 1.840 + { //lower either doesn't exist or isn't free, so check higher 1.841 + if( higherExistsAndIsFree ) 1.842 + { //higher exists and is the only of the two free 1.843 + //First, in free-list, replace higher elem with the one to free 1.844 + elemToFree->nextChunkInFreeList=nextHigherElem->nextChunkInFreeList; 1.845 + elemToFree->prevChunkInFreeList=nextHigherElem->prevChunkInFreeList; 1.846 + elemToFree->prevChunkInFreeList->nextChunkInFreeList = elemToFree; 1.847 + if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? 1.848 + elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; 1.849 + //Now chg mem-list. By side-effect, changes size of elemToFree 1.850 + elemToFree->nextHigherInMem = nextHigherElem->nextHigherInMem; 1.851 + if( elemToFree->nextHigherInMem != 1.852 + _VMSMasterEnv->freeListHead->nextHigherInMem ) 1.853 + elemToFree->nextHigherInMem->nextLowerInMem = elemToFree; 1.854 + } 1.855 + else 1.856 + { //neither lower nor higher is availabe to coalesce so add to list 1.857 + // this makes prev chunk ptr non-null, which indicates it's free 1.858 + elemToFree->nextChunkInFreeList = 1.859 + _VMSMasterEnv->freeListHead->nextChunkInFreeList; 1.860 + _VMSMasterEnv->freeListHead->nextChunkInFreeList = elemToFree; 1.861 + if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? 1.862 + elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; 1.863 + elemToFree->prevChunkInFreeList = _VMSMasterEnv->freeListHead; 1.864 + } 1.865 + } 1.866 + //============================= MEASUREMENT STUFF ======================== 1.867 + #ifdef MEAS__TIME_MALLOC 1.868 + saveLowTimeStampCountInto( endStamp ); 1.869 + addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->freeTimeHist ); 1.870 + #endif 1.871 + //======================================================================== 1.872 + 1.873 + } 1.874 + 1.875 + 1.876 +/*Allocates memory from the external system -- higher overhead 1.877 + * 1.878 + *Because of Linux's malloc throwing bizarre random faults when malloc is 1.879 + * used inside a VMS virtual processor, have to pass this as a request and 1.880 + * have the core loop do it when it gets around to it -- will look for these 1.881 + * chores leftover from the previous animation of masterVP the next time it 1.882 + * goes to animate the masterVP -- so it takes two separate masterVP 1.883 + * animations, separated by work, to complete an external malloc or 1.884 + * external free request. 1.885 + * 1.886 + *Thinking core loop accepts signals -- just looks if signal-location is 1.887 + * empty or not -- 1.888 + */ 1.889 +void * 1.890 +VMS__malloc_in_ext( size_t sizeRequested ) 1.891 + { 1.892 + /* 1.893 + //This is running in the master, so no chance for multiple cores to be 1.894 + // competing for the core's flag. 1.895 + if( *(_VMSMasterEnv->coreLoopSignalAddr[ 0 ]) != 0 ) 1.896 + { //something has already signalled to core loop, so save the signal 1.897 + // and look, next time master animated, to see if can send it. 1.898 + //Note, the addr to put a signal is in the coreloop's frame, so just 1.899 + // checks it each time through -- make it volatile to avoid GCC 1.900 + // optimizations -- it's a coreloop local var that only changes 1.901 + // after jumping away. The signal includes the addr to send the 1.902 + //return to -- even if just empty return completion-signal 1.903 + // 1.904 + //save the signal in some queue that the master looks at each time 1.905 + // it starts up -- one loc says if empty for fast common case -- 1.906 + //something like that -- want to hide this inside this call -- but 1.907 + // think this has to come as a request -- req handler gives procr 1.908 + // back to master loop, which gives it back to req handler at point 1.909 + // it sees that core loop has sent return signal. Something like 1.910 + // that. 1.911 + saveTheSignal 1.912 + 1.913 + } 1.914 + coreSigData->type = malloc; 1.915 + coreSigData->sizeToMalloc = sizeRequested; 1.916 + coreSigData->locToSignalCompletion = &figureOut; 1.917 + _VMSMasterEnv->coreLoopSignals[ 0 ] = coreSigData; 1.918 + */ 1.919 + //just risk system-stack faults until get this figured out 1.920 + return malloc( sizeRequested ); 1.921 + } 1.922 + 1.923 + 1.924 +/*Frees memory that was allocated in the external system -- higher overhead 1.925 + * 1.926 + *As noted in external malloc comment, this is clunky 'cause the free has 1.927 + * to be called in the core loop. 1.928 + */ 1.929 +void 1.930 +VMS__free_in_ext( void *ptrToFree ) 1.931 + { 1.932 + //just risk system-stack faults until get this figured out 1.933 + free( ptrToFree ); 1.934 + 1.935 + //TODO: fix this -- so 1.936 + } 1.937 + 1.938 + 1.939 +/*Designed to be called from the main thread outside of VMS, during init 1.940 + */ 1.941 +MallocProlog * 1.942 +VMS_ext__create_free_list() 1.943 + { MallocProlog *freeListHead, *firstChunk; 1.944 + 1.945 + //Note, this is running in the main thread -- all increases in malloc 1.946 + // mem and all frees of it must be done in this thread, with the 1.947 + // thread's original stack available 1.948 + freeListHead = malloc( sizeof(MallocProlog) ); 1.949 + firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE ); 1.950 + if( firstChunk == NULL ) {printf("malloc error\n"); exit(1);} 1.951 + 1.952 + //Touch memory to avoid page faults 1.953 + void *ptr,*endPtr; 1.954 + endPtr = (void*)firstChunk+MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE; 1.955 + for(ptr = firstChunk; ptr < endPtr; ptr+=PAGE_SIZE) 1.956 + { 1.957 + *(char*)ptr = 0; 1.958 + } 1.959 + 1.960 + freeListHead->prevChunkInFreeList = NULL; 1.961 + //Use this addr to free the heap when cleanup 1.962 + freeListHead->nextLowerInMem = firstChunk; 1.963 + //to identify top-of-heap elem, compare this addr to elem's next higher 1.964 + freeListHead->nextHigherInMem = (void*)( (uintptr_t)firstChunk + 1.965 + MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE); 1.966 + freeListHead->nextChunkInFreeList = firstChunk; 1.967 + 1.968 + firstChunk->nextChunkInFreeList = NULL; 1.969 + firstChunk->prevChunkInFreeList = freeListHead; 1.970 + //next Higher has to be set to top of chunk, so can calc size in malloc 1.971 + firstChunk->nextHigherInMem = (void*)( (uintptr_t)firstChunk + 1.972 + MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE); 1.973 + firstChunk->nextLowerInMem = NULL; //identifies as bott of heap 1.974 + 1.975 + _VMSMasterEnv->amtOfOutstandingMem = 0; //none allocated yet 1.976 + 1.977 + return freeListHead; 1.978 + } 1.979 + 1.980 + 1.981 +/*Designed to be called from the main thread outside of VMS, during cleanup 1.982 + */ 1.983 +void 1.984 +VMS_ext__free_free_list( MallocProlog *freeListHead ) 1.985 + { 1.986 + //stashed a ptr to the one and only bug chunk malloc'd from OS in the 1.987 + // free list head's next lower in mem pointer 1.988 + free( freeListHead->nextLowerInMem ); 1.989 + 1.990 + //don't free the head -- it'll be in an array eventually -- free whole 1.991 + // array when all the free lists linked from it have already been freed 1.992 + } 1.993 +
