00001
00016 #define MEMPOOL_DEBUG 0
00017
00018 #include "converse.h"
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #if CMK_HAS_MALLOC_H
00023 #include <malloc.h>
00024 #endif
00025
00026 #if CMK_C_INLINE
00027 #define INLINE_KEYWORD inline
00028 #else
00029 #define INLINE_KEYWORD
00030 #endif
00031
00032 #include "mempool.h"
00033 int cutOffPoints[] = {64,128,256,512,1024,2048,4096, 8192,16384,32768,
00034 65536,131072,262144,524288,1048576,2097152,4194304,
00035 8388608,16777216,33554432,67108864,134217728,268435456,
00036 536870912,1073741824};
00037
00038 INLINE_KEYWORD int which_pow2(size_t size)
00039 {
00040 int i;
00041 for(i=0; i<cutOffNum; i++) {
00042 if(size <= cutOffPoints[i]) {
00043 return i;
00044 }
00045 }
00046 return i;
00047 }
00048
00049
00050 INLINE_KEYWORD void fillblock(mempool_type *mptr,block_header *block_head,int pool_size,int expansion)
00051 {
00052 int i,power;
00053 size_t loc,left,prev;
00054 slot_header *head;
00055 void *pool;
00056
00057 for(i=0; i<cutOffNum;i++) {
00058 block_head->freelists[i] = 0;
00059 }
00060
00061 pool = block_head;
00062 if(expansion) {
00063 left = pool_size-sizeof(block_header);
00064 loc = (char*)pool+sizeof(block_header)-(char*)mptr;
00065 } else {
00066 left = pool_size-sizeof(mempool_type);
00067 loc = (char*)pool+sizeof(mempool_type)-(char*)mptr;
00068 }
00069 power = which_pow2(left);
00070 if(left < cutOffPoints[power]) {
00071 power--;
00072 }
00073
00074 if(power == cutOffNum) {
00075 CmiAbort("Mempool-requested slot is more than what mempool can provide as\
00076 one chunk, increase cutOffNum and cutoffPoints in mempool\n");
00077 }
00078
00079 #if MEMPOOL_DEBUG
00080 CmiPrintf("Left is %d, Max power obtained is %d\n",left,power);
00081 #endif
00082
00083 for(i=power; i>=0; i--) {
00084 if(left>=cutOffPoints[i]) {
00085 block_head->freelists[i] = loc;
00086 loc += cutOffPoints[i];
00087 left -= cutOffPoints[i];
00088 }
00089 }
00090
00091 prev = 0;
00092 for(i=power; i>=0; i--) {
00093 if(block_head->freelists[i]) {
00094 head = (slot_header*)((char*)mptr+block_head->freelists[i]);
00095 head->size = i;
00096 head->status = 1;
00097 head->block_ptr = block_head;
00098 head->prev = head->next = 0;
00099 head->gprev = prev;
00100 if(i!=power) {
00101 ((slot_header*)((char*)mptr+prev))->gnext = block_head->freelists[i];
00102 }
00103 prev = block_head->freelists[i];
00104 }
00105 }
00106 head->gnext = 0;
00107 }
00108
00109
00110
00111 int checkblock(mempool_type *mptr,block_header *current,int power)
00112 {
00113 int i,powiter;
00114 size_t prev,loc,gnext;
00115 slot_header *head,*head_free,*head_move,*head_next;
00116 head_free = current->freelists[power]?(slot_header*)((char*)mptr+current->freelists[power]):NULL;
00117
00118
00119
00120 powiter = power+1;
00121 while(head_free==NULL && powiter<cutOffNum) {
00122 if(current->freelists[powiter]) {
00123 head_move = (slot_header*)((char*)mptr+current->freelists[powiter]);
00124 gnext = head_move->gnext;
00125 loc = current->freelists[powiter];
00126 current->freelists[powiter] = head_move->next;
00127 current->freelists[power] = loc;
00128
00129 loc = loc+cutOffPoints[power];
00130 for(i=power+1; i<powiter; i++) {
00131 loc = loc+cutOffPoints[i-1];
00132 current->freelists[i] = loc;
00133 }
00134
00135 head_move->size = power;
00136 prev = current->freelists[power];
00137 head_move->next = prev+cutOffPoints[power];
00138 head = (slot_header*)((char*)head_move+cutOffPoints[power]);
00139 for(i=power; i<powiter; i++) {
00140 if(i!=power) {
00141 head = (slot_header*)((char*)head+cutOffPoints[i-1]);
00142 }
00143 head->size = i;
00144 head->status = 1;
00145 head->block_ptr = current;
00146 head->prev = head->next = 0;
00147 head->gprev = prev;
00148 ((slot_header*)((char*)mptr+prev))->gnext = (char*)head-(char*)mptr;
00149 if(i!=power) {
00150 prev = prev+cutOffPoints[i-1];
00151 } else {
00152 prev = prev+cutOffPoints[i];
00153 }
00154 }
00155 ((slot_header*)((char*)head_move+cutOffPoints[power]))->prev =
00156 current->freelists[power];
00157 head->gnext = gnext;
00158 if(gnext!= 0) {
00159 ((slot_header*)((char*)mptr+gnext))->gprev = prev;
00160 }
00161 if(current->freelists[powiter]) {
00162 head_next = (slot_header*)((char*)mptr+current->freelists[powiter]);
00163 head_next->prev = 0;
00164 }
00165 head_free = (slot_header*)((char*)mptr+current->freelists[power]);
00166 }
00167 powiter++;
00168 }
00169 if(head_free == NULL) {
00170 return 0;
00171 } else {
00172 return 1;
00173 }
00174 }
00175
00176 void removeblocks(mempool_type *mptr)
00177 {
00178 block_header *current,*prev,*tofree,*tail;
00179 mempool_freeblock freefn = mptr->freeblockfn;
00180
00181 if(mptr == NULL)
00182 return;
00183
00184 tail = (block_header*)((char*)mptr+mptr->block_tail);
00185 current = prev = &(mptr->block_head);
00186 current = current->block_next?(block_header *)((char*)mptr+current->block_next):NULL;
00187
00188 while(current != NULL) {
00189 if(current->used <= 0) {
00190 tofree = current;
00191 current = current->block_next?(block_header *)((char*)mptr+current->block_next):NULL;
00192 if(tail == tofree) {
00193 mptr->block_tail = tofree->block_prev;
00194 }
00195 prev->block_next = tofree->block_next;
00196 if(current != NULL) {
00197 current->block_prev = tofree->block_prev;
00198 }
00199 mptr->size -= tofree->size;
00200 freefn(tofree, tofree->mem_hndl);
00201 if(mptr->size < mptr->limit) return;
00202 } else {
00203 prev = current;
00204 current = current->block_next?(block_header *)((char*)mptr+current->block_next):NULL;
00205 }
00206 }
00207 }
00208
00209 mempool_type *mempool_init(size_t pool_size, mempool_newblockfn allocfn, mempool_freeblock freefn, size_t limit)
00210 {
00211 int i,power;
00212 size_t end,left,prev,next;
00213 mempool_type *mptr;
00214 slot_header *head;
00215 mem_handle_t mem_hndl;
00216
00217 void *pool = allocfn(&pool_size, &mem_hndl, 0);
00218 mptr = (mempool_type*)pool;
00219 mptr->newblockfn = allocfn;
00220 mptr->freeblockfn = freefn;
00221 mptr->block_tail = 0;
00222 mptr->limit = limit;
00223 mptr->size = pool_size;
00224 #if CMK_USE_MEMPOOL_ISOMALLOC || (CMK_SMP && CMK_CONVERSE_GEMINI_UGNI)
00225 mptr->mempoolLock = CmiCreateLock();
00226 #endif
00227 mptr->block_head.mptr = pool;
00228 mptr->block_head.mem_hndl = mem_hndl;
00229 mptr->block_head.size = pool_size;
00230 mptr->block_head.used = 0;
00231 mptr->block_head.block_prev = 0;
00232 mptr->block_head.block_next = 0;
00233 #if CMK_CONVERSE_GEMINI_UGNI
00234 mptr->block_head.msgs_in_send= 0;
00235 mptr->block_head.msgs_in_recv= 0;
00236 #endif
00237 fillblock(mptr,&mptr->block_head,pool_size,0);
00238 return mptr;
00239 }
00240
00241 void mempool_destroy(mempool_type *mptr)
00242 {
00243 block_header *current,*tofree;
00244 mempool_freeblock freefn = mptr->freeblockfn;
00245
00246 if(mptr == NULL)
00247 return;
00248
00249 current = tofree = &(mptr->block_head);
00250
00251 while(current != NULL) {
00252 tofree = current;
00253 current = current->block_next?(block_header *)((char*)mptr+current->block_next):NULL;
00254 freefn(tofree, tofree->mem_hndl);
00255 }
00256 }
00257
00258
00259 void* mempool_malloc(mempool_type *mptr, int size, int expand)
00260 {
00261 void *pool;
00262 int i;
00263 size_t expand_size;
00264 int power, bestfit_size;
00265 block_header *current,*tail;
00266 slot_header *head_free,*head_next;
00267 mem_handle_t mem_hndl;
00268
00269 #if CMK_USE_MEMPOOL_ISOMALLOC || (CMK_SMP && CMK_CONVERSE_GEMINI_UGNI)
00270 CmiLock(mptr->mempoolLock);
00271 #endif
00272
00273 bestfit_size = size + sizeof(used_header);
00274 power = which_pow2(bestfit_size);
00275 if(power == cutOffNum) {
00276 CmiAbort("Mempool-requested slot is more than what mempool can provide as\
00277 one chunk, increase cutOffNum and cutoffPoints in mempool\n");
00278 }
00279 bestfit_size = cutOffPoints[power];
00280 #if MEMPOOL_DEBUG
00281 CmiPrintf("Request size is %d, power value is %d, size is %d\n",size,power,cutOffPoints[power]);
00282 #endif
00283
00284 head_free = NULL;
00285 current = &mptr->block_head;
00286 while(current != NULL) {
00287 if(checkblock(mptr,current,power)) {
00288 head_free = current->freelists[power]?(slot_header*)((char*)mptr+current->freelists[power]):NULL;
00289 break;
00290 } else {
00291 current = current->block_next?(block_header *)((char*)mptr+current->block_next):NULL;
00292 }
00293 }
00294
00295
00296 if(head_free==NULL) {
00297 if (!expand) return NULL;
00298
00299 #if MEMPOOL_DEBUG
00300 CmiPrintf("Expanding size %lld limit %lld\n",mptr->size,mptr->limit);
00301 #endif
00302
00303 if((mptr->size > mptr->limit) && (mptr->limit > 0)) {
00304 removeblocks(mptr);
00305 }
00306
00307 tail = (block_header*)((char*)mptr+mptr->block_tail);
00308 expand_size = 2*bestfit_size + sizeof(block_header);
00309 pool = mptr->newblockfn(&expand_size, &mem_hndl, 1);
00310 if(pool==NULL) {
00311 CmiPrintf("Mempool-Did not get memory while expanding\n");
00312 return NULL;
00313 }
00314
00315 mptr->size += expand_size;
00316 current = (block_header*)pool;
00317 tail->block_next = ((char*)current-(char*)mptr);
00318 current->block_prev = mptr->block_tail;
00319 mptr->block_tail = tail->block_next;
00320
00321 current->mptr = mptr;
00322 current->mem_hndl = mem_hndl;
00323 current->used = 0;
00324 current->size = expand_size;
00325 current->block_next = 0;
00326 #if CMK_CONVERSE_GEMINI_UGNI
00327 current->msgs_in_send= 0;
00328 current->msgs_in_recv = 0;
00329 #endif
00330
00331 fillblock(mptr,current,expand_size,1);
00332 if(checkblock(mptr,current,power)) {
00333 head_free = current->freelists[power]?(slot_header*)((char*)mptr+current->freelists[power]):NULL;
00334 } else {
00335 CmiPrintf("Mempool-No free block after expansion, something is broken in mempool\n");
00336 return NULL;
00337 }
00338 }
00339
00340 if(head_free!=NULL) {
00341 head_free->status = 0;
00342 current->freelists[power] = head_free->next;
00343 head_next = current->freelists[power]?(slot_header*)((char*)mptr+current->freelists[power]):NULL;
00344 if(head_next != NULL) {
00345 head_next->prev = 0;
00346 }
00347
00348 head_free->block_ptr = current;
00349 current->used += power;
00350 #if CMK_USE_MEMPOOL_ISOMALLOC || (CMK_SMP && CMK_CONVERSE_GEMINI_UGNI)
00351 CmiUnlock(mptr->mempoolLock);
00352 #endif
00353 return (char*)head_free + sizeof(used_header);
00354 }
00355
00356 CmiPrintf("Mempool-Reached a location which I should never have reached\n");
00357 return NULL;
00358 }
00359
00360 #if CMK_USE_MEMPOOL_ISOMALLOC || (CMK_SMP && CMK_CONVERSE_GEMINI_UGNI)
00361 void mempool_free_thread( void *ptr_free)
00362 {
00363 slot_header *to_free;
00364 mempool_type *mptr;
00365
00366 to_free = (slot_header *)((char*)ptr_free - sizeof(used_header));
00367 mptr = (mempool_type*)(((block_header*)(to_free->block_ptr))->mptr);
00368 CmiLock(mptr->mempoolLock);
00369 mempool_free(mptr, ptr_free);
00370 CmiUnlock(mptr->mempoolLock);
00371 }
00372 #endif
00373
00374 void mempool_free(mempool_type *mptr, void *ptr_free)
00375 {
00376 int i,power;
00377 size_t prev,loc,size,left;
00378 block_header *block_head;
00379 slot_header *to_free, *first, *current;
00380 slot_header *used_next,*temp;
00381
00382 #if MEMPOOL_DEBUG
00383 CmiPrintf("Free request for %lld\n",
00384 ((char*)ptr_free - (char*)mptr - sizeof(used_header)));
00385 #endif
00386
00387 to_free = (slot_header *)((char*)ptr_free - sizeof(used_header));
00388 to_free->status = 1;
00389 block_head = to_free->block_ptr;
00390 block_head->used -= to_free->size;
00391
00392
00393
00394 size = 0;
00395 current = to_free;
00396 while(current->status == 1) {
00397 size += cutOffPoints[current->size];
00398 first = current;
00399 current = current->gprev?(slot_header*)((char*)mptr+current->gprev):NULL;
00400 if(current == NULL)
00401 break;
00402 }
00403
00404 size -= cutOffPoints[to_free->size];
00405 current = to_free;
00406 while(current->status == 1) {
00407 size += cutOffPoints[current->size];
00408 current = current->gnext?(slot_header*)((char*)mptr+current->gnext):NULL;
00409 if(current == NULL)
00410 break;
00411 }
00412 used_next = current;
00413
00414
00415
00416 current = first;
00417 while(current!=used_next) {
00418 if(current!=to_free) {
00419 power = current->size;
00420 temp = current->prev?(slot_header*)((char*)mptr+current->prev):NULL;
00421 if(temp!=NULL) {
00422 temp->next = current->next;
00423 } else {
00424 block_head->freelists[power] = current->next;
00425 }
00426 temp = current->next?(slot_header*)((char*)mptr+current->next):NULL;
00427 if(temp!=NULL) {
00428 temp->prev = current->prev;
00429 }
00430 }
00431 current = current->gnext?(slot_header*)((char*)mptr+current->gnext):NULL;
00432 }
00433
00434
00435 power = which_pow2(size);
00436 if(size < cutOffPoints[power]) {
00437 power--;
00438 }
00439 left = size;
00440
00441 #if MEMPOOL_DEBUG
00442 if(CmiMyPe() == 0)
00443 printf("free was for %lld, merging for %lld, power %lld\n",to_free->size,size,power);
00444 #endif
00445
00446 loc = (char*)first - (char*)mptr;
00447 for(i=power; i>=0; i--) {
00448 if(left>=cutOffPoints[i]) {
00449 current = (slot_header*)((char*)mptr+loc);
00450 current->size = i;
00451 current->status = 1;
00452 current->block_ptr = block_head;
00453 if(i!=power) {
00454 current->gprev = prev;
00455 }
00456 current->gnext = loc + cutOffPoints[i];
00457 current->prev = 0;
00458 if(block_head->freelists[i] == 0) {
00459 current->next = 0;
00460 } else {
00461 current->next = block_head->freelists[i];
00462 temp = (slot_header*)((char*)mptr+block_head->freelists[i]);
00463 temp->prev = loc;
00464 }
00465 block_head->freelists[i] = loc;
00466 prev = loc;
00467 loc += cutOffPoints[i];
00468 left -= cutOffPoints[i];
00469 }
00470 }
00471 if(used_next!=NULL) {
00472 used_next->gprev = (char*)current - (char*)mptr;
00473 } else {
00474 current->gnext = 0;
00475 }
00476 #if MEMPOOL_DEBUG
00477 CmiPrintf("Free done\n");
00478 #endif
00479 }
00480
00481 #if CMK_CONVERSE_GEMINI_UGNI
00482 inline void* getNextRegisteredPool(void *current)
00483 {
00484
00485 }
00486 #endif