Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
comparison vmalloc.c @ 134:a9b72021f053
Distributed memory management w/o free requests working
| author | Merten Sach <msach@mailbox.tu-berlin.de> |
|---|---|
| date | Fri, 16 Sep 2011 16:19:24 +0200 |
| parents | dbfc8382d546 |
| children | 0b49fd35afc1 |
comparison
equal
deleted
inserted
replaced
| 21:2ea90c770565 | 22:0877c22b1191 |
|---|---|
| 10 #include <malloc.h> | 10 #include <malloc.h> |
| 11 #include <inttypes.h> | 11 #include <inttypes.h> |
| 12 #include <stdlib.h> | 12 #include <stdlib.h> |
| 13 #include <stdio.h> | 13 #include <stdio.h> |
| 14 | 14 |
| 15 #include "ProcrContext.h" | 15 #include "VMS.h" |
| 16 #include "Histogram/Histogram.h" | 16 #include "Histogram/Histogram.h" |
| 17 | 17 |
| 18 /*Helper function | 18 /*Helper function |
| 19 *Insert a newly generated free chunk into the first spot on the free list. | 19 *Insert a newly generated free chunk into the first spot on the free list. |
| 20 * The chunk is cast as a MallocProlog, so the various pointers in it are | 20 * The chunk is cast as a MallocProlog, so the various pointers in it are |
| 68 VMS__malloc_on_core( size_t sizeRequested, int procrID) | 68 VMS__malloc_on_core( size_t sizeRequested, int procrID) |
| 69 { MallocProlog *foundElem = NULL, *currElem, *newElem; | 69 { MallocProlog *foundElem = NULL, *currElem, *newElem; |
| 70 MallocPrologAllocated *returnElem; | 70 MallocPrologAllocated *returnElem; |
| 71 ssize_t amountExtra, sizeConsumed,sizeOfFound; | 71 ssize_t amountExtra, sizeConsumed,sizeOfFound; |
| 72 uint32 foundElemIsTopOfHeap; | 72 uint32 foundElemIsTopOfHeap; |
| 73 | |
| 74 printf("Malloc on core %d\n", procrID); | |
| 73 | 75 |
| 74 //============================= MEASUREMENT STUFF ======================== | 76 //============================= MEASUREMENT STUFF ======================== |
| 75 #ifdef MEAS__TIME_MALLOC | 77 #ifdef MEAS__TIME_MALLOC |
| 76 int32 startStamp, endStamp; | 78 int32 startStamp, endStamp; |
| 77 saveLowTimeStampCountInto( startStamp ); | 79 saveLowTimeStampCountInto( startStamp ); |
| 78 #endif | 80 #endif |
| 79 //======================================================================== | 81 //======================================================================== |
| 80 | 82 |
| 81 //step up the size to be aligned at 16-byte boundary, prob better ways | 83 //step up the size to be aligned at 16-byte boundary, prob better ways |
| 82 sizeRequested = (sizeRequested + 16) & ~15; | 84 sizeRequested = (sizeRequested + 16) & ~15; |
| 83 currElem = (_VMSMasterEnv->freeListHead[_VMSMasterEnv->currentMasterProcrID]) | 85 currElem = (_VMSMasterEnv->freeListHead[procrID]) |
| 84 ->nextChunkInFreeList; | 86 ->nextChunkInFreeList; |
| 85 | 87 |
| 86 while( currElem != NULL ) | 88 while( currElem != NULL ) |
| 87 { //check if size of currElem is big enough | 89 { //check if size of currElem is big enough |
| 88 sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); | 90 sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); |
| 103 //Using a kludge to identify the element that is the top chunk in the | 105 //Using a kludge to identify the element that is the top chunk in the |
| 104 // heap -- saving top-of-heap addr in head's nextHigherInMem -- and | 106 // heap -- saving top-of-heap addr in head's nextHigherInMem -- and |
| 105 // save addr of start of heap in head's nextLowerInMem | 107 // save addr of start of heap in head's nextLowerInMem |
| 106 //Will handle top of Heap specially | 108 //Will handle top of Heap specially |
| 107 foundElemIsTopOfHeap = foundElem->nextHigherInMem == | 109 foundElemIsTopOfHeap = foundElem->nextHigherInMem == |
| 108 _VMSMasterEnv->freeListHead->nextHigherInMem; | 110 _VMSMasterEnv->freeListHead[procrID]->nextHigherInMem; |
| 109 | 111 |
| 110 //before shave off and try to insert new elem, remove found elem | 112 //before shave off and try to insert new elem, remove found elem |
| 111 //note, foundElem will never be the head, so always has valid prevChunk | 113 //note, foundElem will never be the head, so always has valid prevChunk |
| 112 foundElem->prevChunkInFreeList->nextChunkInFreeList = | 114 foundElem->prevChunkInFreeList->nextChunkInFreeList = |
| 113 foundElem->nextChunkInFreeList; | 115 foundElem->nextChunkInFreeList; |
| 122 //if enough, turn extra into new elem & insert it | 124 //if enough, turn extra into new elem & insert it |
| 123 if( amountExtra > 64 ) | 125 if( amountExtra > 64 ) |
| 124 { //make new elem by adding to addr of curr elem then casting | 126 { //make new elem by adding to addr of curr elem then casting |
| 125 sizeConsumed = sizeof(MallocProlog) + sizeRequested; | 127 sizeConsumed = sizeof(MallocProlog) + sizeRequested; |
| 126 newElem = (MallocProlog *)( (uintptr_t)returnElem + sizeConsumed ); | 128 newElem = (MallocProlog *)( (uintptr_t)returnElem + sizeConsumed ); |
| 127 newElem->nextLowerInMem = returnElem; //This is evil (but why?) | 129 newElem->nextLowerInMem = (MallocProlog*)returnElem; |
| 128 newElem->nextHigherInMem = returnElem->nextHigherInMem; //This is evil (but why?) | 130 newElem->nextHigherInMem = returnElem->nextHigherInMem; |
| 129 returnElem->nextHigherInMem = newElem; | 131 returnElem->nextHigherInMem = newElem; |
| 130 if( ! foundElemIsTopOfHeap ) | 132 if( ! foundElemIsTopOfHeap ) |
| 131 { //there is no next higher for top of heap, so can't write to it | 133 { //there is no next higher for top of heap, so can't write to it |
| 132 newElem->nextHigherInMem->nextLowerInMem = newElem; | 134 newElem->nextHigherInMem->nextLowerInMem = newElem; |
| 133 } | 135 } |
| 134 add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead ); | 136 add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead[procrID] ); |
| 135 } | 137 } |
| 136 else | 138 else |
| 137 { | 139 { |
| 138 sizeConsumed = sizeOfFound; | 140 sizeConsumed = sizeOfFound; |
| 139 } | 141 } |
| 156 * otherwise it sends a message to the responsible core. | 158 * otherwise it sends a message to the responsible core. |
| 157 */ | 159 */ |
| 158 void | 160 void |
| 159 VMS__free(void *ptrToFree) | 161 VMS__free(void *ptrToFree) |
| 160 { | 162 { |
| 161 MallocPrologAllocated chunk = (MallocPrologAllocated*)ptrToFree - 1; | 163 MallocPrologAllocated *chunk = (MallocPrologAllocated*)ptrToFree - 1; |
| 162 if(chunk->procrID == _VMSMasterEnv->currentMasterProcrID) | 164 if(chunk->procrID == _VMSMasterEnv->currentMasterProcrID) |
| 163 { | 165 { |
| 164 VMS__free_on_core(ptrToFree, _VMSMasterEnv->currentMasterProcrID); | 166 VMS__free_on_core(ptrToFree, _VMSMasterEnv->currentMasterProcrID); |
| 165 } | 167 } |
| 166 else | 168 else |
| 175 * otherwise it sends a message to the responsible core. | 177 * otherwise it sends a message to the responsible core. |
| 176 */ | 178 */ |
| 177 void | 179 void |
| 178 VMS__free_in_lib(void *ptrToFree, VirtProcr *VProc) | 180 VMS__free_in_lib(void *ptrToFree, VirtProcr *VProc) |
| 179 { | 181 { |
| 180 MallocPrologAllocated chunk = (MallocPrologAllocated*)ptrToFree - 1; | 182 MallocPrologAllocated *chunk = (MallocPrologAllocated*)ptrToFree - 1; |
| 183 printf("Free from core %d for core %d\n", VProc->coreAnimatedBy, chunk->procrID); | |
| 181 if(chunk->procrID == VProc->coreAnimatedBy) | 184 if(chunk->procrID == VProc->coreAnimatedBy) |
| 182 { | 185 { |
| 183 VMS__free_on_core(ptrToFree, VProc->coreAnimatedBy); | 186 VMS__free_on_core(ptrToFree, VProc->coreAnimatedBy); |
| 184 } | 187 } |
| 185 else | 188 else |
| 204 #ifdef MEAS__TIME_MALLOC | 207 #ifdef MEAS__TIME_MALLOC |
| 205 int32 startStamp, endStamp; | 208 int32 startStamp, endStamp; |
| 206 saveLowTimeStampCountInto( startStamp ); | 209 saveLowTimeStampCountInto( startStamp ); |
| 207 #endif | 210 #endif |
| 208 //======================================================================== | 211 //======================================================================== |
| 209 | 212 |
| 210 if( ptrToFree < (void*)_VMSMasterEnv->freeListHead->nextLowerInMem || | 213 MallocProlog* masterListHead = _VMSMasterEnv->freeListHead[procrID]; |
| 211 ptrToFree > (void*)_VMSMasterEnv->freeListHead->nextHigherInMem ) | 214 |
| 215 if( ptrToFree < (void*)masterListHead->nextLowerInMem || | |
| 216 ptrToFree > (void*)masterListHead->nextHigherInMem ) | |
| 212 { //outside the range of data owned by VMS's malloc, so do nothing | 217 { //outside the range of data owned by VMS's malloc, so do nothing |
| 213 return; | 218 return; |
| 214 } | 219 } |
| 215 //subtract size of prolog to get pointer to prolog, then cast | 220 //subtract size of prolog to get pointer to prolog, then cast |
| 216 elemToFree = (MallocProlog *)((uintptr_t)ptrToFree - sizeof(MallocProlog)); | 221 elemToFree = (MallocProlog *)((uintptr_t)ptrToFree - sizeof(MallocProlog)); |
| 248 nextHigherElem->prevChunkInFreeList; | 253 nextHigherElem->prevChunkInFreeList; |
| 249 //Now, fix-up sequence-in-mem list -- by side-effect, this also | 254 //Now, fix-up sequence-in-mem list -- by side-effect, this also |
| 250 // changes size of the lower elem, which is still in free-list | 255 // changes size of the lower elem, which is still in free-list |
| 251 nextLowerElem->nextHigherInMem = nextHigherElem->nextHigherInMem; | 256 nextLowerElem->nextHigherInMem = nextHigherElem->nextHigherInMem; |
| 252 if( nextHigherElem->nextHigherInMem != | 257 if( nextHigherElem->nextHigherInMem != |
| 253 _VMSMasterEnv->freeListHead->nextHigherInMem ) | 258 masterListHead->nextHigherInMem ) |
| 254 nextHigherElem->nextHigherInMem->nextLowerInMem = nextLowerElem; | 259 nextHigherElem->nextHigherInMem->nextLowerInMem = nextLowerElem; |
| 255 //notice didn't do anything to elemToFree -- it simply is no | 260 //notice didn't do anything to elemToFree -- it simply is no |
| 256 // longer reachable from any of the lists. Wonder if could be a | 261 // longer reachable from any of the lists. Wonder if could be a |
| 257 // security leak because left valid addresses in it, | 262 // security leak because left valid addresses in it, |
| 258 // but don't care for now. | 263 // but don't care for now. |
| 261 { //lower is the only of the two that exists and is free, | 266 { //lower is the only of the two that exists and is free, |
| 262 //In this case, no adjustment to free-list, just change mem-list. | 267 //In this case, no adjustment to free-list, just change mem-list. |
| 263 // By side-effect, changes size of the lower elem | 268 // By side-effect, changes size of the lower elem |
| 264 nextLowerElem->nextHigherInMem = elemToFree->nextHigherInMem; | 269 nextLowerElem->nextHigherInMem = elemToFree->nextHigherInMem; |
| 265 if( elemToFree->nextHigherInMem != | 270 if( elemToFree->nextHigherInMem != |
| 266 _VMSMasterEnv->freeListHead->nextHigherInMem ) | 271 masterListHead->nextHigherInMem ) |
| 267 elemToFree->nextHigherInMem->nextLowerInMem = nextLowerElem; | 272 elemToFree->nextHigherInMem->nextLowerInMem = nextLowerElem; |
| 268 } | 273 } |
| 269 } | 274 } |
| 270 else | 275 else |
| 271 { //lower either doesn't exist or isn't free, so check higher | 276 { //lower either doesn't exist or isn't free, so check higher |
| 278 if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? | 283 if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? |
| 279 elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; | 284 elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; |
| 280 //Now chg mem-list. By side-effect, changes size of elemToFree | 285 //Now chg mem-list. By side-effect, changes size of elemToFree |
| 281 elemToFree->nextHigherInMem = nextHigherElem->nextHigherInMem; | 286 elemToFree->nextHigherInMem = nextHigherElem->nextHigherInMem; |
| 282 if( elemToFree->nextHigherInMem != | 287 if( elemToFree->nextHigherInMem != |
| 283 _VMSMasterEnv->freeListHead->nextHigherInMem ) | 288 masterListHead->nextHigherInMem ) |
| 284 elemToFree->nextHigherInMem->nextLowerInMem = elemToFree; | 289 elemToFree->nextHigherInMem->nextLowerInMem = elemToFree; |
| 285 } | 290 } |
| 286 else | 291 else |
| 287 { //neither lower nor higher is availabe to coalesce so add to list | 292 { //neither lower nor higher is availabe to coalesce so add to list |
| 288 // this makes prev chunk ptr non-null, which indicates it's free | 293 // this makes prev chunk ptr non-null, which indicates it's free |
| 289 elemToFree->nextChunkInFreeList = | 294 elemToFree->nextChunkInFreeList = |
| 290 _VMSMasterEnv->freeListHead->nextChunkInFreeList; | 295 masterListHead->nextChunkInFreeList; |
| 291 _VMSMasterEnv->freeListHead->nextChunkInFreeList = elemToFree; | 296 masterListHead->nextChunkInFreeList = elemToFree; |
| 292 if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? | 297 if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? |
| 293 elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; | 298 elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; |
| 294 elemToFree->prevChunkInFreeList = _VMSMasterEnv->freeListHead; | 299 elemToFree->prevChunkInFreeList = masterListHead; |
| 295 } | 300 } |
| 296 } | 301 } |
| 297 //============================= MEASUREMENT STUFF ======================== | 302 //============================= MEASUREMENT STUFF ======================== |
| 298 #ifdef MEAS__TIME_MALLOC | 303 #ifdef MEAS__TIME_MALLOC |
| 299 saveLowTimeStampCountInto( endStamp ); | 304 saveLowTimeStampCountInto( endStamp ); |
| 374 { MallocProlog *freeListHead, *firstChunk; | 379 { MallocProlog *freeListHead, *firstChunk; |
| 375 | 380 |
| 376 //Note, this is running in the main thread -- all increases in malloc | 381 //Note, this is running in the main thread -- all increases in malloc |
| 377 // mem and all frees of it must be done in this thread, with the | 382 // mem and all frees of it must be done in this thread, with the |
| 378 // thread's original stack available | 383 // thread's original stack available |
| 384 | |
| 379 freeListHead = malloc( sizeof(MallocProlog) ); | 385 freeListHead = malloc( sizeof(MallocProlog) ); |
| 380 firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE ); | 386 firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE ); |
| 381 if( firstChunk == NULL ) {printf("malloc error\n"); exit(1);} | 387 if( firstChunk == NULL ) {printf("malloc error\n"); exit(1);} |
| 382 | 388 |
| 383 //Touch memory to avoid page faults | 389 //Touch memory to avoid page faults |
| 410 | 416 |
| 411 | 417 |
| 412 /*Designed to be called from the main thread outside of VMS, during cleanup | 418 /*Designed to be called from the main thread outside of VMS, during cleanup |
| 413 */ | 419 */ |
| 414 void | 420 void |
| 415 VMS_ext__free_free_list( MallocProlog *freeListHead ) | 421 VMS_ext__free_free_list( MallocProlog* freeListHeads[] ) |
| 416 { | 422 { |
| 417 //stashed a ptr to the one and only bug chunk malloc'd from OS in the | 423 //stashed a ptr to the one and only bug chunk malloc'd from OS in the |
| 418 // free list head's next lower in mem pointer | 424 // free list head's next lower in mem pointer |
| 419 free( freeListHead->nextLowerInMem ); | 425 int i; |
| 420 | 426 for(i=0; i<NUM_CORES; i++) |
| 427 { | |
| 428 free( freeListHeads[i]->nextLowerInMem ); | |
| 429 } | |
| 421 //don't free the head -- it'll be in an array eventually -- free whole | 430 //don't free the head -- it'll be in an array eventually -- free whole |
| 422 // array when all the free lists linked from it have already been freed | 431 // array when all the free lists linked from it have already been freed |
| 423 } | 432 } |
| 424 | 433 |
