Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
comparison vmalloc.c @ 78:521c75d64cef
Version before optimization
| author | Merten Sach <msach@mailbox.tu-berlin.de> |
|---|---|
| date | Mon, 04 Jul 2011 19:45:43 +0200 |
| parents | 9ddbb071142d |
| children | 97e26095c01f |
comparison
equal
deleted
inserted
replaced
| 8:2f2ee79fea94 | 9:56c0a8ace56a |
|---|---|
| 58 saveLowTimeStampCountInto( startStamp ); | 58 saveLowTimeStampCountInto( startStamp ); |
| 59 #endif | 59 #endif |
| 60 //======================================================================== | 60 //======================================================================== |
| 61 | 61 |
| 62 //step up the size to be aligned at 16-byte boundary, prob better ways | 62 //step up the size to be aligned at 16-byte boundary, prob better ways |
| 63 sizeRequested = ((sizeRequested + 16) >> 4) << 4; | 63 sizeRequested = (sizeRequested + 16) & ~15; |
| 64 currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList; | 64 currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList; |
| 65 | 65 |
| 66 while( currElem != NULL ) | 66 while( currElem != NULL ) |
| 67 { //check if size of currElem is big enough | 67 { //check if size of currElem is big enough |
| 68 sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); | 68 sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); |
| 72 foundElem = currElem; | 72 foundElem = currElem; |
| 73 currElem = NULL; | 73 currElem = NULL; |
| 74 } | 74 } |
| 75 else | 75 else |
| 76 currElem = currElem->nextChunkInFreeList; | 76 currElem = currElem->nextChunkInFreeList; |
| 77 } | |
| 78 | |
| 79 if( foundElem == NULL ) | |
| 80 { ERROR("\nmalloc failed\n") | |
| 81 return (void *)NULL; //indicates malloc failed | |
| 82 } | |
| 83 //Using a kludge to identify the element that is the top chunk in the | |
| 84 // heap -- saving top-of-heap addr in head's nextHigherInMem -- and | |
| 85 // save addr of start of heap in head's nextLowerInMem | |
| 86 //Will handle top of Heap specially | |
| 87 foundElemIsTopOfHeap = foundElem->nextHigherInMem == | |
| 88 _VMSMasterEnv->freeListHead->nextHigherInMem; | |
| 89 | |
| 90 //before shave off and try to insert new elem, remove found elem | |
| 91 //note, foundElem will never be the head, so always has valid prevChunk | |
| 92 foundElem->prevChunkInFreeList->nextChunkInFreeList = | |
| 93 foundElem->nextChunkInFreeList; | |
| 94 if( foundElem->nextChunkInFreeList != NULL ) | |
| 95 { foundElem->nextChunkInFreeList->prevChunkInFreeList = | |
| 96 foundElem->prevChunkInFreeList; | |
| 97 } | |
| 98 foundElem->prevChunkInFreeList = NULL;//indicates elem currently allocated | |
| 99 | |
| 100 //if enough, turn extra into new elem & insert it | |
| 101 if( amountExtra > 64 ) | |
| 102 { //make new elem by adding to addr of curr elem then casting | |
| 103 sizeConsumed = sizeof(MallocProlog) + sizeRequested; | |
| 104 newElem = (MallocProlog *)( (uintptr_t)foundElem + sizeConsumed ); | |
| 105 newElem->nextLowerInMem = foundElem; //This is evil (but why?) | |
| 106 newElem->nextHigherInMem = foundElem->nextHigherInMem; //This is evil (but why?) | |
| 107 foundElem->nextHigherInMem = newElem; | |
| 108 if( ! foundElemIsTopOfHeap ) | |
| 109 { //there is no next higher for top of heap, so can't write to it | |
| 110 newElem->nextHigherInMem->nextLowerInMem = newElem; | |
| 111 } | |
| 112 add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead ); | |
| 113 } | |
| 114 else | |
| 115 { | |
| 116 sizeConsumed = sizeOfFound; | |
| 117 } | |
| 118 _VMSMasterEnv->amtOfOutstandingMem += sizeConsumed; | |
| 119 | |
| 120 //============================= MEASUREMENT STUFF ======================== | |
| 121 #ifdef MEAS__TIME_MALLOC | |
| 122 saveLowTimeStampCountInto( endStamp ); | |
| 123 addIntervalToHist( startStamp, endStamp, _VMSMasterEnv->mallocTimeHist ); | |
| 124 #endif | |
| 125 //======================================================================== | |
| 126 | |
| 127 //skip over the prolog by adding its size to the pointer return | |
| 128 return (void*)((uintptr_t)foundElem + sizeof(MallocProlog)); | |
| 129 } | |
| 130 | |
| 131 /*This is sequential code, meant to only be called from the Master, not from | |
| 132 * any slave VPs. | |
| 133 *Search down list, checking size by the nextHigherInMem pointer, to find | |
| 134 * first chunk bigger than size needed. | |
| 135 *Shave off the extra and make it into a new free-list element, hook it in | |
| 136 * then return the address of the found element plus size of prolog. | |
| 137 * | |
| 138 * The difference to the regular malloc is, that all the allocated chunks are | |
| 139 * aligned and padded to the size of a CACHE_LINE. Thus creating a new chunk | |
| 140 * before the aligned chunk. | |
| 141 */ | |
| 142 void *VMS__malloc_aligned( size_t sizeRequested ) | |
| 143 { MallocProlog *foundElem = NULL, *currElem, *newElem; | |
| 144 ssize_t amountExtra, sizeConsumed,sizeOfFound,prevAmount; | |
| 145 uint32 foundElemIsTopOfHeap; | |
| 146 | |
| 147 //============================= MEASUREMENT STUFF ======================== | |
| 148 #ifdef MEAS__TIME_MALLOC | |
| 149 uint32 startStamp, endStamp; | |
| 150 saveLowTimeStampCountInto( startStamp ); | |
| 151 #endif | |
| 152 //======================================================================== | |
| 153 | |
| 154 //step up the size to be multiple of the cache line size | |
| 155 sizeRequested = (sizeRequested + CACHE_LINE) & ~(CACHE_LINE-1); | |
| 156 currElem = (_VMSMasterEnv->freeListHead)->nextChunkInFreeList; | |
| 157 | |
| 158 while( currElem != NULL ) | |
| 159 { //check if size of currElem is big enough | |
| 160 sizeOfFound=(size_t)((uintptr_t)currElem->nextHigherInMem -(uintptr_t)currElem); | |
| 161 amountExtra = sizeOfFound - sizeRequested - sizeof(MallocProlog); | |
| 162 if( amountExtra > 0 ) | |
| 163 { | |
| 164 //look if the found element is already aligned | |
| 165 if((((uintptr_t)currElem+sizeof(MallocProlog)) & (uintptr_t)(CACHE_LINE-1)) == 0){ | |
| 166 //found it, get out of loop | |
| 167 foundElem = currElem; | |
| 168 break; | |
| 169 }else{ | |
| 170 //find first aligned address and check if it's still big enough | |
| 171 //check also if the space before the aligned address is big enough | |
| 172 //for a new element | |
| 173 void *firstAlignedAddr = (void*)(((uintptr_t)currElem + 2*CACHE_LINE) & ~((uintptr_t)(CACHE_LINE-1))); | |
| 174 prevAmount = (uintptr_t)firstAlignedAddr - (uintptr_t)currElem; | |
| 175 sizeOfFound=(uintptr_t)currElem->nextHigherInMem -(uintptr_t)firstAlignedAddr + sizeof(MallocProlog); | |
| 176 amountExtra= sizeOfFound - sizeRequested - sizeof(MallocProlog); | |
| 177 if(prevAmount > 2*sizeof(MallocProlog) && amountExtra > 0 ){ | |
| 178 //found suitable element | |
| 179 //create new previous element and exit loop | |
| 180 MallocProlog *newAlignedElem = (MallocProlog*)firstAlignedAddr - 1; | |
| 181 | |
| 182 //insert new element into free list | |
| 183 if(currElem->nextChunkInFreeList != NULL) | |
| 184 currElem->nextChunkInFreeList->prevChunkInFreeList = newAlignedElem; | |
| 185 newAlignedElem->prevChunkInFreeList = currElem; | |
| 186 newAlignedElem->nextChunkInFreeList = currElem->nextChunkInFreeList; | |
| 187 currElem->nextChunkInFreeList = newAlignedElem; | |
| 188 | |
| 189 //set higherInMem and lowerInMem | |
| 190 newAlignedElem->nextHigherInMem = currElem->nextHigherInMem; | |
| 191 foundElemIsTopOfHeap = currElem->nextHigherInMem == | |
| 192 _VMSMasterEnv->freeListHead->nextHigherInMem; | |
| 193 if(!foundElemIsTopOfHeap) | |
| 194 currElem->nextHigherInMem->nextLowerInMem = newAlignedElem; | |
| 195 currElem->nextHigherInMem = newAlignedElem; | |
| 196 newAlignedElem->nextLowerInMem = currElem; | |
| 197 | |
| 198 //Found new element leaving loop | |
| 199 foundElem = newAlignedElem; | |
| 200 break; | |
| 201 } | |
| 202 } | |
| 203 | |
| 204 } | |
| 205 currElem = currElem->nextChunkInFreeList; | |
| 77 } | 206 } |
| 78 | 207 |
| 79 if( foundElem == NULL ) | 208 if( foundElem == NULL ) |
| 80 { ERROR("\nmalloc failed\n") | 209 { ERROR("\nmalloc failed\n") |
| 81 return (void *)NULL; //indicates malloc failed | 210 return (void *)NULL; //indicates malloc failed |
