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