Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
diff vmalloc.c @ 101:ca154ebe2b6c
Basic malloc without small chunks
| author | Merten Sach <msach@mailbox.tu-berlin.de> |
|---|---|
| date | Tue, 02 Aug 2011 15:44:28 +0200 |
| parents | 21c95d402fe6 |
| children | def70e32cf2c |
line diff
1.1 --- a/vmalloc.c Tue Jul 26 16:14:30 2011 +0200 1.2 +++ b/vmalloc.c Tue Aug 02 15:44:28 2011 +0200 1.3 @@ -11,46 +11,188 @@ 1.4 #include <inttypes.h> 1.5 #include <stdlib.h> 1.6 #include <stdio.h> 1.7 +#include <string.h> 1.8 +#include <math.h> 1.9 1.10 #include "VMS.h" 1.11 #include "Histogram/Histogram.h" 1.12 1.13 -/*Helper function 1.14 - *Insert a newly generated free chunk into the first spot on the free list. 1.15 - * The chunk is cast as a MallocProlog, so the various pointers in it are 1.16 - * accessed with C's help -- and the size of the prolog is easily added to 1.17 - * the pointer when a chunk is returned to the app -- so C handles changes 1.18 - * in pointer sizes among machines. 1.19 - * 1.20 - *The list head is a normal MallocProlog struct -- identified by its 1.21 - * prevChunkInFreeList being NULL -- the only one. 1.22 - * 1.23 - *The end of the list is identified by next chunk being NULL, as usual. 1.24 +/* 1.25 + * This calculates the container which fits the given size. 1.26 */ 1.27 -void inline 1.28 -add_chunk_to_free_list( MallocProlog *chunk, MallocProlog *listHead ) 1.29 - { 1.30 - chunk->nextChunkInFreeList = listHead->nextChunkInFreeList; 1.31 - if( chunk->nextChunkInFreeList != NULL ) //if not last in free list 1.32 - chunk->nextChunkInFreeList->prevChunkInFreeList = chunk; 1.33 - chunk->prevChunkInFreeList = listHead; 1.34 - listHead->nextChunkInFreeList = chunk; 1.35 +inline 1.36 +uint32 getContainer(size_t size) 1.37 +{ 1.38 + return floor((log10(size)-LOG128)/LOG54); 1.39 +} 1.40 + 1.41 +/* 1.42 + * This calculates the size of a given container 1.43 + */ 1.44 +inline 1.45 +size_t getContainerSize(uint32 idx) 1.46 +{ 1.47 + return pow(CHUNK_INCREASE_RATE,idx)*LOWER_BOUND; 1.48 +} 1.49 + 1.50 +/* 1.51 + * Removes the first chunk of a freeList 1.52 + * The chunk is removed but not set as free. There is no check if 1.53 + * the free list is empty, so make sure this is not the case. 1.54 + */ 1.55 +inline 1.56 +MallocProlog *removeChunk(MallocProlog** container) 1.57 +{ 1.58 + MallocProlog *removedChunk = *container; 1.59 + *container = removedChunk->nextChunkInFreeList; 1.60 + 1.61 + if(removedChunk->nextChunkInFreeList) 1.62 + removedChunk->nextChunkInFreeList->prevChunkInFreeList = 1.63 + (MallocProlog*)container; 1.64 + 1.65 + return removedChunk; 1.66 +} 1.67 + 1.68 +/* 1.69 + * Removes a chunk from a free list. 1.70 + */ 1.71 +inline 1.72 +MallocProlog *extractChunk(MallocProlog* chunk) 1.73 +{ 1.74 + 1.75 +} 1.76 + 1.77 +/* 1.78 + * Merges two chunks. 1.79 + * Chunk A has to be before chunk B in memory. 1.80 + */ 1.81 +inline 1.82 +MallocProlog *mergeChunks(MallocProlog* chunkA, MallocProlog* chunkB) 1.83 +{ 1.84 + 1.85 +} 1.86 +/* 1.87 + * Inserts a chunk into a free list. 1.88 + */ 1.89 +inline 1.90 +void insertChunk(MallocProlog* chunk, MallocProlog** container) 1.91 +{ 1.92 + chunk->nextChunkInFreeList = *container; 1.93 + chunk->prevChunkInFreeList = (MallocProlog*)container; 1.94 + if(*container) 1.95 + (*container)->prevChunkInFreeList = chunk; 1.96 + *container = chunk; 1.97 +} 1.98 + 1.99 +/* 1.100 + * Divides the chunk that a new chunk of newSize is created. 1.101 + * There is no size check, so make sure the size value is valid. 1.102 + */ 1.103 +inline 1.104 +MallocProlog *divideChunk(MallocProlog* chunk, size_t newSize) 1.105 +{ 1.106 + MallocProlog* newChunk = (MallocProlog*)((uintptr_t)chunk->nextHigherInMem - 1.107 + newSize - sizeof(MallocProlog)); 1.108 + 1.109 + newChunk->nextLowerInMem = chunk; 1.110 + newChunk->nextHigherInMem = chunk->nextHigherInMem; 1.111 + 1.112 + chunk->nextHigherInMem = newChunk; 1.113 + chunk->nextHigherInMem->nextLowerInMem = newChunk; 1.114 + 1.115 + return newChunk; 1.116 +} 1.117 + 1.118 +inline 1.119 +size_t getChunkSize(MallocProlog* chunk) 1.120 +{ 1.121 + return (uintptr_t)chunk->nextHigherInMem - 1.122 + (uintptr_t)chunk - sizeof(MallocProlog); 1.123 +} 1.124 + 1.125 +/* 1.126 + * This is sequential code, meant to only be called from the Master, not from 1.127 + * any slave VPs. 1.128 + */ 1.129 +void *VMS__malloc( size_t sizeRequested ) 1.130 + { 1.131 + //============================= MEASUREMENT STUFF ======================== 1.132 + #ifdef MEAS__TIME_MALLOC 1.133 + int32 startStamp, endStamp; 1.134 + saveLowTimeStampCountInto( startStamp ); 1.135 + #endif 1.136 + //======================================================================== 1.137 + 1.138 + MallocArrays* freeList = _VMSMasterEnv->freeLists; 1.139 + 1.140 + //Return a small chunk if the requested size is smaller than 128B 1.141 + //TODO: for now set size to 129B 1.142 + if(sizeRequested < 128) 1.143 + sizeRequested = 129; 1.144 + 1.145 + //Calculate the expected container. Start one higher to have a Chunk that's 1.146 + //always big enough. 1.147 + uint32 targetContainerIdx = getContainer(sizeRequested); 1.148 + uint32 containerIdx = targetContainerIdx + 1; 1.149 + 1.150 + MallocProlog* foundChunk; 1.151 + if(freeList->bigChunks[containerIdx] == NULL) 1.152 + { 1.153 + while(freeList->bigChunks[containerIdx] == NULL) 1.154 + { 1.155 + containerIdx++; 1.156 + if(containerIdx > freeList->containerCount) 1.157 + { 1.158 + printf("VMS malloc failed: low memory"); 1.159 + exit(1); 1.160 + } 1.161 + } 1.162 + 1.163 + foundChunk = removeChunk(&freeList->bigChunks[containerIdx]); 1.164 + //Found bigger Element, so we have to divide until it fits the 1.165 + //requested size 1.166 + containerIdx--; 1.167 + size_t containerSize = getContainerSize(containerIdx); 1.168 + size_t chunkSize = getChunkSize(foundChunk); 1.169 + 1.170 + while(containerIdx > targetContainerIdx) 1.171 + { 1.172 + if(chunkSize > containerSize + sizeRequested + sizeof(MallocProlog)) 1.173 + { 1.174 + MallocProlog *newChunk = divideChunk(foundChunk,containerSize); 1.175 + insertChunk(newChunk,&freeList->bigChunks[containerIdx]); 1.176 + chunkSize = getChunkSize(foundChunk); 1.177 + } 1.178 + containerIdx--; 1.179 + containerSize /= CHUNK_INCREASE_RATE; 1.180 + } 1.181 + } 1.182 + else 1.183 + { 1.184 + foundChunk = removeChunk(&freeList->bigChunks[containerIdx]); 1.185 + } 1.186 + 1.187 + //Mark as allocated 1.188 + foundChunk->prevChunkInFreeList = NULL; 1.189 + 1.190 + //============================= MEASUREMENT STUFF ======================== 1.191 + #ifdef MEAS__TIME_MALLOC 1.192 + saveLowTimeStampCountInto( endStamp ); 1.193 + addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist ); 1.194 + #endif 1.195 + //======================================================================== 1.196 + 1.197 + //skip over the prolog by adding its size to the pointer return 1.198 + return (void*)((uintptr_t)foundChunk + sizeof(MallocProlog)); 1.199 } 1.200 1.201 - 1.202 -/*This is sequential code, meant to only be called from the Master, not from 1.203 +/* 1.204 + * This is sequential code, meant to only be called from the Master, not from 1.205 * any slave VPs. 1.206 - *Search down list, checking size by the nextHigherInMem pointer, to find 1.207 - * first chunk bigger than size needed. 1.208 - *Shave off the extra and make it into a new free-list element, hook it in 1.209 - * then return the address of the found element plus size of prolog. 1.210 - * 1.211 - *Will find a 1.212 */ 1.213 -void *VMS__malloc( size_t sizeRequested ) 1.214 - { MallocProlog *foundElem = NULL, *currElem, *newElem; 1.215 - ssize_t amountExtra, sizeConsumed,sizeOfFound; 1.216 - uint32 foundElemIsTopOfHeap; 1.217 +void 1.218 +VMS__free( void *ptrToFree ) 1.219 + { 1.220 1.221 //============================= MEASUREMENT STUFF ======================== 1.222 #ifdef MEAS__TIME_MALLOC 1.223 @@ -59,312 +201,17 @@ 1.224 #endif 1.225 //======================================================================== 1.226 1.227 - //step up the size to be aligned at 16-byte boundary, prob better ways 1.228 - sizeRequested = (sizeRequested + 16) & ~15; 1.229 - currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList; 1.230 - 1.231 - while( currElem != NULL ) 1.232 - { //check if size of currElem is big enough 1.233 - sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); 1.234 - amountExtra = sizeOfFound - sizeRequested - sizeof(MallocProlog); 1.235 - if( amountExtra > 0 ) 1.236 - { //found it, get out of loop 1.237 - foundElem = currElem; 1.238 - currElem = NULL; 1.239 + MallocArrays* freeList = _VMSMasterEnv->freeLists; 1.240 + MallocProlog *chunkToFree = (MallocProlog*)ptrToFree - 1; 1.241 + 1.242 + //Check for free neighbors 1.243 + if(chunkToFree->nextLowerInMem) 1.244 + { 1.245 + if(chunkToFree->nextLowerInMem->prevChunkInFreeList != NULL) 1.246 + {//Chunk is not allocated 1.247 + mergeChunks() 1.248 } 1.249 - else 1.250 - currElem = currElem->nextChunkInFreeList; 1.251 - } 1.252 - 1.253 - if( foundElem == NULL ) 1.254 - { ERROR("\nmalloc failed\n") 1.255 - return (void *)NULL; //indicates malloc failed 1.256 - } 1.257 - //Using a kludge to identify the element that is the top chunk in the 1.258 - // heap -- saving top-of-heap addr in head's nextHigherInMem -- and 1.259 - // save addr of start of heap in head's nextLowerInMem 1.260 - //Will handle top of Heap specially 1.261 - foundElemIsTopOfHeap = foundElem->nextHigherInMem == 1.262 - _VMSMasterEnv->freeListHead->nextHigherInMem; 1.263 - 1.264 - //before shave off and try to insert new elem, remove found elem 1.265 - //note, foundElem will never be the head, so always has valid prevChunk 1.266 - foundElem->prevChunkInFreeList->nextChunkInFreeList = 1.267 - foundElem->nextChunkInFreeList; 1.268 - if( foundElem->nextChunkInFreeList != NULL ) 1.269 - { foundElem->nextChunkInFreeList->prevChunkInFreeList = 1.270 - foundElem->prevChunkInFreeList; 1.271 - } 1.272 - foundElem->prevChunkInFreeList = NULL;//indicates elem currently allocated 1.273 - 1.274 - //if enough, turn extra into new elem & insert it 1.275 - if( amountExtra > 64 ) 1.276 - { //make new elem by adding to addr of curr elem then casting 1.277 - sizeConsumed = sizeof(MallocProlog) + sizeRequested; 1.278 - newElem = (MallocProlog *)( (uintptr_t)foundElem + sizeConsumed ); 1.279 - newElem->nextLowerInMem = foundElem; //This is evil (but why?) 1.280 - newElem->nextHigherInMem = foundElem->nextHigherInMem; //This is evil (but why?) 1.281 - foundElem->nextHigherInMem = newElem; 1.282 - if( ! foundElemIsTopOfHeap ) 1.283 - { //there is no next higher for top of heap, so can't write to it 1.284 - newElem->nextHigherInMem->nextLowerInMem = newElem; 1.285 - } 1.286 - add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead ); 1.287 - } 1.288 - else 1.289 - { 1.290 - sizeConsumed = sizeOfFound; 1.291 - } 1.292 - _VMSMasterEnv->amtOfOutstandingMem += sizeConsumed; 1.293 - 1.294 - //============================= MEASUREMENT STUFF ======================== 1.295 - #ifdef MEAS__TIME_MALLOC 1.296 - saveLowTimeStampCountInto( endStamp ); 1.297 - addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist ); 1.298 - #endif 1.299 - //======================================================================== 1.300 - 1.301 - //skip over the prolog by adding its size to the pointer return 1.302 - return (void*)((uintptr_t)foundElem + sizeof(MallocProlog)); 1.303 - } 1.304 - 1.305 -/*This is sequential code, meant to only be called from the Master, not from 1.306 - * any slave VPs. 1.307 - *Search down list, checking size by the nextHigherInMem pointer, to find 1.308 - * first chunk bigger than size needed. 1.309 - *Shave off the extra and make it into a new free-list element, hook it in 1.310 - * then return the address of the found element plus size of prolog. 1.311 - * 1.312 - * The difference to the regular malloc is, that all the allocated chunks are 1.313 - * aligned and padded to the size of a CACHE_LINE. Thus creating a new chunk 1.314 - * before the aligned chunk. 1.315 - */ 1.316 -void *VMS__malloc_aligned( size_t sizeRequested ) 1.317 - { MallocProlog *foundElem = NULL, *currElem, *newElem; 1.318 - ssize_t amountExtra, sizeConsumed,sizeOfFound,prevAmount; 1.319 - uint32 foundElemIsTopOfHeap; 1.320 - 1.321 - //============================= MEASUREMENT STUFF ======================== 1.322 - #ifdef MEAS__TIME_MALLOC 1.323 - uint32 startStamp, endStamp; 1.324 - saveLowTimeStampCountInto( startStamp ); 1.325 - #endif 1.326 - //======================================================================== 1.327 - 1.328 - //step up the size to be multiple of the cache line size 1.329 - sizeRequested = (sizeRequested + CACHE_LINE) & ~(CACHE_LINE-1); 1.330 - currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList; 1.331 - 1.332 - while( currElem != NULL ) 1.333 - { //check if size of currElem is big enough 1.334 - sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); 1.335 - amountExtra = sizeOfFound - sizeRequested - sizeof(MallocProlog); 1.336 - if( amountExtra > 0 ) 1.337 - { 1.338 - //look if the found element is already aligned 1.339 - if((((uintptr_t)currElem+sizeof(MallocProlog)) & (uintptr_t)(CACHE_LINE-1)) == 0){ 1.340 - //found it, get out of loop 1.341 - foundElem = currElem; 1.342 - break; 1.343 - }else{ 1.344 - //find first aligned address and check if it's still big enough 1.345 - //check also if the space before the aligned address is big enough 1.346 - //for a new element 1.347 - void *firstAlignedAddr = (void*)(((uintptr_t)currElem + 2*CACHE_LINE) & ~((uintptr_t)(CACHE_LINE-1))); 1.348 - prevAmount = (uintptr_t)firstAlignedAddr - (uintptr_t)currElem; 1.349 - sizeOfFound=(uintptr_t)currElem->nextHigherInMem -(uintptr_t)firstAlignedAddr + sizeof(MallocProlog); 1.350 - amountExtra= sizeOfFound - sizeRequested - sizeof(MallocProlog); 1.351 - if(prevAmount > 2*sizeof(MallocProlog) && amountExtra > 0 ){ 1.352 - //found suitable element 1.353 - //create new previous element and exit loop 1.354 - MallocProlog *newAlignedElem = (MallocProlog*)firstAlignedAddr - 1; 1.355 - 1.356 - //insert new element into free list 1.357 - if(currElem->nextChunkInFreeList != NULL) 1.358 - currElem->nextChunkInFreeList->prevChunkInFreeList = newAlignedElem; 1.359 - newAlignedElem->prevChunkInFreeList = currElem; 1.360 - newAlignedElem->nextChunkInFreeList = currElem->nextChunkInFreeList; 1.361 - currElem->nextChunkInFreeList = newAlignedElem; 1.362 - 1.363 - //set higherInMem and lowerInMem 1.364 - newAlignedElem->nextHigherInMem = currElem->nextHigherInMem; 1.365 - foundElemIsTopOfHeap = currElem->nextHigherInMem == 1.366 - _VMSMasterEnv->freeListHead->nextHigherInMem; 1.367 - if(!foundElemIsTopOfHeap) 1.368 - currElem->nextHigherInMem->nextLowerInMem = newAlignedElem; 1.369 - currElem->nextHigherInMem = newAlignedElem; 1.370 - newAlignedElem->nextLowerInMem = currElem; 1.371 - 1.372 - //Found new element leaving loop 1.373 - foundElem = newAlignedElem; 1.374 - break; 1.375 - } 1.376 - } 1.377 - 1.378 - } 1.379 - currElem = currElem->nextChunkInFreeList; 1.380 - } 1.381 - 1.382 - if( foundElem == NULL ) 1.383 - { ERROR("\nmalloc failed\n") 1.384 - return (void *)NULL; //indicates malloc failed 1.385 - } 1.386 - //Using a kludge to identify the element that is the top chunk in the 1.387 - // heap -- saving top-of-heap addr in head's nextHigherInMem -- and 1.388 - // save addr of start of heap in head's nextLowerInMem 1.389 - //Will handle top of Heap specially 1.390 - foundElemIsTopOfHeap = foundElem->nextHigherInMem == 1.391 - _VMSMasterEnv->freeListHead->nextHigherInMem; 1.392 - 1.393 - //before shave off and try to insert new elem, remove found elem 1.394 - //note, foundElem will never be the head, so always has valid prevChunk 1.395 - foundElem->prevChunkInFreeList->nextChunkInFreeList = 1.396 - foundElem->nextChunkInFreeList; 1.397 - if( foundElem->nextChunkInFreeList != NULL ) 1.398 - { foundElem->nextChunkInFreeList->prevChunkInFreeList = 1.399 - foundElem->prevChunkInFreeList; 1.400 - } 1.401 - foundElem->prevChunkInFreeList = NULL;//indicates elem currently allocated 1.402 - 1.403 - //if enough, turn extra into new elem & insert it 1.404 - if( amountExtra > 64 ) 1.405 - { //make new elem by adding to addr of curr elem then casting 1.406 - sizeConsumed = sizeof(MallocProlog) + sizeRequested; 1.407 - newElem = (MallocProlog *)( (uintptr_t)foundElem + sizeConsumed ); 1.408 - newElem->nextHigherInMem = foundElem->nextHigherInMem; 1.409 - newElem->nextLowerInMem = foundElem; 1.410 - foundElem->nextHigherInMem = newElem; 1.411 - 1.412 - if( ! foundElemIsTopOfHeap ) 1.413 - { //there is no next higher for top of heap, so can't write to it 1.414 - newElem->nextHigherInMem->nextLowerInMem = newElem; 1.415 - } 1.416 - add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead ); 1.417 - } 1.418 - else 1.419 - { 1.420 - sizeConsumed = sizeOfFound; 1.421 - } 1.422 - _VMSMasterEnv->amtOfOutstandingMem += sizeConsumed; 1.423 - 1.424 - //============================= MEASUREMENT STUFF ======================== 1.425 - #ifdef MEAS__TIME_MALLOC 1.426 - saveLowTimeStampCountInto( endStamp ); 1.427 - addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist ); 1.428 - #endif 1.429 - //======================================================================== 1.430 - 1.431 - //skip over the prolog by adding its size to the pointer return 1.432 - return (void*)((uintptr_t)foundElem + sizeof(MallocProlog)); 1.433 - } 1.434 - 1.435 - 1.436 -/*This is sequential code -- only to be called from the Master 1.437 - * When free, subtract the size of prolog from pointer, then cast it to a 1.438 - * MallocProlog. Then check the nextLower and nextHigher chunks to see if 1.439 - * one or both are also free, and coalesce if so, and if neither free, then 1.440 - * add this one to free-list. 1.441 - */ 1.442 -void 1.443 -VMS__free( void *ptrToFree ) 1.444 - { MallocProlog *elemToFree, *nextLowerElem, *nextHigherElem; 1.445 - size_t sizeOfElem; 1.446 - uint32 lowerExistsAndIsFree, higherExistsAndIsFree; 1.447 - 1.448 - //============================= MEASUREMENT STUFF ======================== 1.449 - #ifdef MEAS__TIME_MALLOC 1.450 - int32 startStamp, endStamp; 1.451 - saveLowTimeStampCountInto( startStamp ); 1.452 - #endif 1.453 - //======================================================================== 1.454 - 1.455 - if( ptrToFree < (void*)_VMSMasterEnv->freeListHead->nextLowerInMem || 1.456 - ptrToFree > (void*)_VMSMasterEnv->freeListHead->nextHigherInMem ) 1.457 - { //outside the range of data owned by VMS's malloc, so do nothing 1.458 - return; 1.459 - } 1.460 - //subtract size of prolog to get pointer to prolog, then cast 1.461 - elemToFree = (MallocProlog *)((uintptr_t)ptrToFree - sizeof(MallocProlog)); 1.462 - sizeOfElem =(size_t)((uintptr_t)elemToFree->nextHigherInMem-(uintptr_t)elemToFree); 1.463 - 1.464 - if( elemToFree->prevChunkInFreeList != NULL ) 1.465 - { printf( "error: freeing same element twice!" ); exit(1); 1.466 - } 1.467 - 1.468 - _VMSMasterEnv->amtOfOutstandingMem -= sizeOfElem; 1.469 - 1.470 - nextLowerElem = elemToFree->nextLowerInMem; 1.471 - nextHigherElem = elemToFree->nextHigherInMem; 1.472 - 1.473 - if( nextHigherElem == NULL ) 1.474 - higherExistsAndIsFree = FALSE; 1.475 - else //okay exists, now check if in the free-list by checking back ptr 1.476 - higherExistsAndIsFree = (nextHigherElem->prevChunkInFreeList != NULL); 1.477 - 1.478 - if( nextLowerElem == NULL ) 1.479 - lowerExistsAndIsFree = FALSE; 1.480 - else //okay, it exists, now check if it's free 1.481 - lowerExistsAndIsFree = (nextLowerElem->prevChunkInFreeList != NULL); 1.482 - 1.483 - 1.484 - //now, know what exists and what's free 1.485 - if( lowerExistsAndIsFree ) 1.486 - { if( higherExistsAndIsFree ) 1.487 - { //both exist and are free, so coalesce all three 1.488 - //First, remove higher from free-list 1.489 - nextHigherElem->prevChunkInFreeList->nextChunkInFreeList = 1.490 - nextHigherElem->nextChunkInFreeList; 1.491 - if( nextHigherElem->nextChunkInFreeList != NULL ) //end-of-list? 1.492 - nextHigherElem->nextChunkInFreeList->prevChunkInFreeList = 1.493 - nextHigherElem->prevChunkInFreeList; 1.494 - //Now, fix-up sequence-in-mem list -- by side-effect, this also 1.495 - // changes size of the lower elem, which is still in free-list 1.496 - nextLowerElem->nextHigherInMem = nextHigherElem->nextHigherInMem; 1.497 - if( nextHigherElem->nextHigherInMem != 1.498 - _VMSMasterEnv->freeListHead->nextHigherInMem ) 1.499 - nextHigherElem->nextHigherInMem->nextLowerInMem = nextLowerElem; 1.500 - //notice didn't do anything to elemToFree -- it simply is no 1.501 - // longer reachable from any of the lists. Wonder if could be a 1.502 - // security leak because left valid addresses in it, 1.503 - // but don't care for now. 1.504 - } 1.505 - else 1.506 - { //lower is the only of the two that exists and is free, 1.507 - //In this case, no adjustment to free-list, just change mem-list. 1.508 - // By side-effect, changes size of the lower elem 1.509 - nextLowerElem->nextHigherInMem = elemToFree->nextHigherInMem; 1.510 - if( elemToFree->nextHigherInMem != 1.511 - _VMSMasterEnv->freeListHead->nextHigherInMem ) 1.512 - elemToFree->nextHigherInMem->nextLowerInMem = nextLowerElem; 1.513 - } 1.514 - } 1.515 - else 1.516 - { //lower either doesn't exist or isn't free, so check higher 1.517 - if( higherExistsAndIsFree ) 1.518 - { //higher exists and is the only of the two free 1.519 - //First, in free-list, replace higher elem with the one to free 1.520 - elemToFree->nextChunkInFreeList=nextHigherElem->nextChunkInFreeList; 1.521 - elemToFree->prevChunkInFreeList=nextHigherElem->prevChunkInFreeList; 1.522 - elemToFree->prevChunkInFreeList->nextChunkInFreeList = elemToFree; 1.523 - if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? 1.524 - elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; 1.525 - //Now chg mem-list. By side-effect, changes size of elemToFree 1.526 - elemToFree->nextHigherInMem = nextHigherElem->nextHigherInMem; 1.527 - if( elemToFree->nextHigherInMem != 1.528 - _VMSMasterEnv->freeListHead->nextHigherInMem ) 1.529 - elemToFree->nextHigherInMem->nextLowerInMem = elemToFree; 1.530 - } 1.531 - else 1.532 - { //neither lower nor higher is availabe to coalesce so add to list 1.533 - // this makes prev chunk ptr non-null, which indicates it's free 1.534 - elemToFree->nextChunkInFreeList = 1.535 - _VMSMasterEnv->freeListHead->nextChunkInFreeList; 1.536 - _VMSMasterEnv->freeListHead->nextChunkInFreeList = elemToFree; 1.537 - if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? 1.538 - elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; 1.539 - elemToFree->prevChunkInFreeList = _VMSMasterEnv->freeListHead; 1.540 - } 1.541 - } 1.542 + } 1.543 //============================= MEASUREMENT STUFF ======================== 1.544 #ifdef MEAS__TIME_MALLOC 1.545 saveLowTimeStampCountInto( endStamp ); 1.546 @@ -440,43 +287,47 @@ 1.547 1.548 /*Designed to be called from the main thread outside of VMS, during init 1.549 */ 1.550 -MallocProlog * 1.551 +MallocArrays * 1.552 VMS_ext__create_free_list() 1.553 - { MallocProlog *freeListHead, *firstChunk; 1.554 - 1.555 - //Note, this is running in the main thread -- all increases in malloc 1.556 - // mem and all frees of it must be done in this thread, with the 1.557 - // thread's original stack available 1.558 - freeListHead = malloc( sizeof(MallocProlog) ); 1.559 - firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE ); 1.560 +{ 1.561 + //Initialize containers for small chunks and fill with zeros 1.562 + _VMSMasterEnv->freeLists = (MallocArrays*)malloc( sizeof(MallocArrays) ); 1.563 + MallocArrays *freeLists = _VMSMasterEnv->freeLists; 1.564 + 1.565 + freeLists->smallChunks = 1.566 + (MallocProlog**)malloc(SMALL_CHUNK_COUNT*sizeof(MallocProlog*)); 1.567 + memset((void*)freeLists->smallChunks, 1.568 + 0,SMALL_CHUNK_COUNT*sizeof(MallocProlog*)); 1.569 + 1.570 + //Calculate number of containers for big chunks 1.571 + uint32 container = getContainer(MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE)+1; 1.572 + 1.573 + freeLists->bigChunks = (MallocProlog**)malloc(container*sizeof(MallocProlog*)); 1.574 + memset((void*)freeLists->bigChunks,0,container*sizeof(MallocProlog*)); 1.575 + freeLists->containerCount = container; 1.576 + 1.577 + //Create first element in lastContainer 1.578 + MallocProlog *firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE ); 1.579 if( firstChunk == NULL ) {printf("malloc error\n"); exit(1);} 1.580 1.581 - //Touch memory to avoid page faults 1.582 - void *ptr,*endPtr; 1.583 - endPtr = (void*)firstChunk+MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE; 1.584 - for(ptr = firstChunk; ptr < endPtr; ptr+=PAGE_SIZE) 1.585 - { 1.586 - *(char*)ptr = 0; 1.587 - } 1.588 - 1.589 - freeListHead->prevChunkInFreeList = NULL; 1.590 - //Use this addr to free the heap when cleanup 1.591 - freeListHead->nextLowerInMem = firstChunk; 1.592 - //to identify top-of-heap elem, compare this addr to elem's next higher 1.593 - freeListHead->nextHigherInMem = (void*)( (uintptr_t)firstChunk + 1.594 - MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE); 1.595 - freeListHead->nextChunkInFreeList = firstChunk; 1.596 - 1.597 - firstChunk->nextChunkInFreeList = NULL; 1.598 - firstChunk->prevChunkInFreeList = freeListHead; 1.599 - //next Higher has to be set to top of chunk, so can calc size in malloc 1.600 - firstChunk->nextHigherInMem = (void*)( (uintptr_t)firstChunk + 1.601 - MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE); 1.602 - firstChunk->nextLowerInMem = NULL; //identifies as bott of heap 1.603 + firstChunk->nextLowerInMem = NULL; 1.604 + firstChunk->nextHigherInMem = (MallocProlog*)((uintptr_t)firstChunk + 1.605 + MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE - sizeof(MallocProlog*)); 1.606 + firstChunk->nextChunkInFreeList = NULL; 1.607 + //previous element in the queue is the container 1.608 + firstChunk->prevChunkInFreeList = freeLists->bigChunks[container-1]; 1.609 1.610 - _VMSMasterEnv->amtOfOutstandingMem = 0; //none allocated yet 1.611 - 1.612 - return freeListHead; 1.613 + freeLists->bigChunks[container-1] = firstChunk; 1.614 + 1.615 + //Create dummy chunk to mark the top of stack this is of course 1.616 + //never freed 1.617 + MallocProlog *dummyChunk = firstChunk->nextHigherInMem; 1.618 + dummyChunk->nextHigherInMem = dummyChunk+1; 1.619 + dummyChunk->nextLowerInMem = NULL; 1.620 + dummyChunk->nextChunkInFreeList = NULL; 1.621 + dummyChunk->prevChunkInFreeList = NULL; 1.622 + 1.623 + return freeLists; 1.624 } 1.625 1.626
