00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "converse.h"
00038 #include "memory-isomalloc.h"
00039
00040 #define ISOMALLOC_DEBUG 0
00041
00042 #if ISOMALLOC_DEBUG
00043 #define DEBUG_PRINT(...) CmiPrintf(__VA_ARGS__)
00044 #else
00045 #define DEBUG_PRINT(...)
00046 #endif
00047
00048
00049 #define TREE_NODE_SIZE 128
00050 #define TREE_NODE_MID 63
00051
00052
00053 #define LIST_ARRAY_SIZE 64
00054
00055 #include <fcntl.h>
00056 #include <stdio.h>
00057 #include <stdlib.h>
00058 #include <errno.h>
00059 #include <unistd.h>
00060
00061 #ifdef _WIN32
00062 # include <io.h>
00063 # define open _open
00064 # define close _close
00065 # define read _read
00066 # define write _write
00067 #endif
00068
00069 #if CMK_HAS_ADDR_NO_RANDOMIZE
00070 #include <sys/personality.h>
00071 #endif
00072
00073 #if CMK_USE_MEMPOOL_ISOMALLOC
00074 #include "mempool.h"
00075 extern int cutOffPoints[cutOffNum];
00076 #endif
00077
00078 int _sync_iso = 0;
00079 #if __FAULT__
00080 static int _restart = 0;
00081 #endif
00082 static int _mmap_probe = 0;
00083
00084 static int read_randomflag(void)
00085 {
00086 FILE *fp;
00087 int random_flag;
00088 fp = fopen("/proc/sys/kernel/randomize_va_space", "r");
00089 if (fp != NULL) {
00090 if (fscanf(fp, "%d", &random_flag) != 1) {
00091 CmiAbort("Isomalloc> fscanf failed reading /proc/sys/kernel/randomize_va_space!");
00092 }
00093 fclose(fp);
00094 if(random_flag) random_flag = 1;
00095 #if CMK_HAS_ADDR_NO_RANDOMIZE
00096 if(random_flag)
00097 {
00098 int persona = personality(0xffffffff);
00099 if(persona & ADDR_NO_RANDOMIZE)
00100 random_flag = 0;
00101 }
00102 #endif
00103 }
00104 else {
00105 random_flag = -1;
00106 }
00107 return random_flag;
00108 }
00109
00110
00111
00112
00113
00114
00115 struct CmiIsomallocBlock {
00116 CmiInt8 slot;
00117 CmiInt8 length;
00118 CmiInt8 align;
00119 CmiInt8 alignoffset;
00120 };
00121 typedef struct CmiIsomallocBlock CmiIsomallocBlock;
00122
00123
00124 static void *block2pointer(CmiIsomallocBlock *blockHeader) {
00125 return (void *)(blockHeader+1);
00126 }
00127 static CmiIsomallocBlock *pointer2block(void *heapBlock) {
00128 return ((CmiIsomallocBlock *)heapBlock)-1;
00129 }
00130
00131
00132 typedef size_t memRange_t;
00133
00134
00135 static size_t slotsize;
00136 static size_t regionSize;
00137
00138
00139 static CmiInt8 numslots=0;
00140
00141
00142
00143
00144 static char *isomallocStart=NULL;
00145 static char *isomallocEnd=NULL;
00146
00147
00148 static void *slot2addr(CmiInt8 slot) {
00149 return isomallocStart+((memRange_t)slotsize)*((memRange_t)slot);
00150 }
00151 static int slot2pe(CmiInt8 slot) {
00152 return (int)(slot/numslots);
00153 }
00154 static CmiInt8 pe2slot(int pe) {
00155 return pe*numslots;
00156 }
00157
00158 #if CMK_USE_MEMPOOL_ISOMALLOC
00159 static size_t length2slots(size_t nBytes) {
00160 return (nBytes+slotsize-1)/slotsize;
00161 }
00162 #else
00163 static size_t length2slots(size_t nBytes) {
00164 return (sizeof(CmiIsomallocBlock)+nBytes+slotsize-1)/slotsize;
00165 }
00166 #endif
00167
00168
00169 struct _dllnode {
00170 struct _dllnode *previous;
00171 struct _slotblock *sb;
00172 struct _dllnode *next;
00173 };
00174
00175
00176 struct _slotblock {
00177 CmiInt8 startslot;
00178 CmiInt8 nslots;
00179 struct _dllnode *listblock;
00180 };
00181
00182 typedef struct _dllnode dllnode;
00183 typedef struct _slotblock slotblock;
00184
00185
00186 struct _btreenode {
00187 int num_blocks;
00188 slotblock blocks[TREE_NODE_SIZE];
00189 struct _btreenode *child[TREE_NODE_SIZE + 1];
00190 };
00191 typedef struct _btreenode btreenode;
00192
00193
00194 typedef struct _slotset {
00195 btreenode *btree_root;
00196 dllnode *list_array[LIST_ARRAY_SIZE];
00197 } slotset;
00198
00199
00200 typedef struct _insert_ret_val {
00201 slotblock sb;
00202 btreenode *btn;
00203 } insert_ret_val;
00204
00205
00206
00207
00208
00209
00210
00211 static int find_list_bin(CmiInt8 nslots)
00212 {
00213 int list_bin = 32;
00214 CmiInt8 comp_num = 0x100000000LL;
00215 int inc = 16;
00216
00217 while (1)
00218 {
00219 if ((comp_num >> 1) < nslots && nslots <= comp_num)
00220 {
00221
00222 return list_bin;
00223 }
00224 else if (nslots < comp_num)
00225 {
00226
00227 list_bin -= inc;
00228 comp_num >>= inc;
00229 if ((inc >>= 1) == 0)
00230 inc = 1;
00231 }
00232 else
00233 {
00234
00235 list_bin += inc;
00236 comp_num <<= inc;
00237 if ((inc >>= 1) == 0)
00238 inc = 1;
00239 }
00240 }
00241 }
00242
00243
00244
00245
00246
00247
00248
00249 static dllnode *list_insert(slotset *ss, slotblock *sb)
00250 {
00251
00252 int list_bin = find_list_bin(sb->nslots);
00253
00254
00255 auto new_dlln = (dllnode *)malloc_reentrant(sizeof(dllnode));
00256
00257
00258 dllnode *& bin = ss->list_array[list_bin];
00259 new_dlln->previous = NULL;
00260 new_dlln->next = bin;
00261 new_dlln->sb = sb;
00262 if (bin != NULL)
00263 bin->previous = new_dlln;
00264 bin = new_dlln;
00265
00266 return new_dlln;
00267 }
00268
00269
00270
00271
00272
00273
00274 static void list_delete(slotset *ss, slotblock *sb)
00275 {
00276 dllnode * listblock = sb->listblock;
00277
00278
00279 if (listblock->next != NULL)
00280 listblock->next->previous = listblock->previous;
00281
00282 if (listblock->previous != NULL)
00283 listblock->previous->next = listblock->next;
00284 else
00285 ss->list_array[find_list_bin(sb->nslots)] = listblock->next;
00286
00287
00288 free_reentrant(listblock);
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 static void list_move(slotset *ss, dllnode *dlln, CmiInt8 old_nslots)
00300 {
00301
00302 int old_bin = find_list_bin(old_nslots);
00303
00304
00305 int new_bin = find_list_bin(dlln->sb->nslots);
00306
00307
00308 if (new_bin != old_bin)
00309 {
00310 if (dlln->next != NULL)
00311 dlln->next->previous = dlln->previous;
00312
00313
00314 if (dlln->previous == NULL)
00315 ss->list_array[old_bin] = dlln->next;
00316 else
00317 dlln->previous->next = dlln->next;
00318
00319
00320 dlln->next = ss->list_array[new_bin];
00321 dlln->previous = NULL;
00322 if (dlln->next != NULL)
00323 dlln->next->previous = dlln;
00324
00325 ss->list_array[new_bin] = dlln;
00326 }
00327 }
00328
00329
00330
00331
00332
00333 static btreenode *create_btree_node()
00334 {
00335 auto btn = (btreenode *)malloc_reentrant(sizeof(btreenode));
00336 btn->num_blocks = 0;
00337
00338 for (slotblock * b = btn->blocks, * const b_end = b + TREE_NODE_SIZE; b < b_end; ++b)
00339 b->listblock = NULL;
00340
00341 for (btreenode ** c = btn->child, ** const c_end = c + TREE_NODE_SIZE + 1; c < c_end; ++c)
00342 *c = NULL;
00343
00344 return btn;
00345 }
00346
00347
00348
00349
00350
00351
00352 static slotblock *find_btree_slotblock(btreenode *node, CmiInt8 startslot)
00353 {
00354
00355 if (node == NULL || startslot < 0 || node->num_blocks == 0)
00356 {
00357 return NULL;
00358 }
00359 else
00360 {
00361
00362
00363
00364 int index = node->num_blocks >> 1;
00365 int inc = (index >> 1) + (node->num_blocks & 0x1);
00366
00367
00368 while (1)
00369 {
00370 slotblock & block = node->blocks[index];
00371 const CmiInt8 endslot = block.startslot + block.nslots - 1;
00372
00373
00374 if (block.startslot <= startslot && startslot <= endslot)
00375 {
00376 return █
00377 }
00378 else if (startslot < block.startslot)
00379 {
00380
00381 if (index == 0)
00382 {
00383 return find_btree_slotblock(node->child[index], startslot);
00384 }
00385 else
00386 {
00387 slotblock & leftblock = node->blocks[index-1];
00388 const CmiInt8 leftblock_endslot = leftblock.startslot + leftblock.nslots - 1;
00389
00390
00391
00392 if (startslot > leftblock_endslot)
00393 {
00394 return find_btree_slotblock(node->child[index], startslot);
00395 }
00396 else
00397 {
00398 index -= inc;
00399 if ((inc >>= 1) == 0)
00400 inc = 1;
00401 }
00402 }
00403 }
00404 else
00405 {
00406
00407 if (index == node->num_blocks-1)
00408 {
00409 return find_btree_slotblock(node->child[index+1], startslot);
00410 }
00411 else
00412 {
00413
00414
00415 if (startslot < node->blocks[index+1].startslot)
00416 {
00417 return find_btree_slotblock(node->child[index+1], startslot);
00418 }
00419 else
00420 {
00421 index += inc;
00422 if ((inc >>= 1) == 0)
00423 inc = 1;
00424 }
00425 }
00426 }
00427 }
00428 }
00429 }
00430
00431 static void copy_slotblock(slotblock & dst, const slotblock & src)
00432 {
00433 dst = src;
00434 dst.listblock->sb = &dst;
00435 }
00436
00437 static void insert_slotblock(slotblock & block, slotset *ss, CmiInt8 startslot, CmiInt8 nslots)
00438 {
00439 block.startslot = startslot;
00440 block.nslots = nslots;
00441 block.listblock = list_insert(ss, &block);
00442 }
00443
00444
00445
00446
00447
00448
00449 static insert_ret_val btree_insert_int(slotset *ss, btreenode *node,
00450 CmiInt8 startslot, CmiInt8 nslots)
00451 {
00452
00453
00454 auto helper = [&](const int index) -> insert_ret_val
00455 {
00456 if (node->child[index] != NULL)
00457 {
00458 insert_ret_val irv = btree_insert_int(ss, node->child[index], startslot, nslots);
00459 if (irv.btn != NULL)
00460 {
00461
00462 for (int i = node->num_blocks; i > index; i--)
00463 {
00464 copy_slotblock(node->blocks[i], node->blocks[i-1]);
00465 node->child[i+1] = node->child[i];
00466 }
00467
00468 copy_slotblock(node->blocks[index], irv.sb);
00469 node->child[index+1] = irv.btn;
00470 node->num_blocks++;
00471
00472 if (node->num_blocks == TREE_NODE_SIZE)
00473 {
00474
00475 btreenode *new_node = create_btree_node();
00476
00477 for (int i = TREE_NODE_MID+1; i < TREE_NODE_SIZE; i++)
00478 {
00479 int j = i - (TREE_NODE_MID+1);
00480 copy_slotblock(new_node->blocks[j], node->blocks[i]);
00481 }
00482
00483 for (int i = TREE_NODE_MID+1; i <= TREE_NODE_SIZE; i++)
00484 new_node->child[i-(TREE_NODE_MID+1)] = node->child[i];
00485
00486 node->num_blocks = TREE_NODE_MID;
00487 new_node->num_blocks = TREE_NODE_SIZE - TREE_NODE_MID - 1;
00488
00489 irv.sb = node->blocks[TREE_NODE_MID];
00490 irv.btn = new_node;
00491 }
00492 else
00493 {
00494 irv.btn = NULL;
00495 }
00496 }
00497
00498 return irv;
00499 }
00500 else
00501 {
00502 insert_ret_val irv{};
00503
00504 for (int i = node->num_blocks; i > index; i--)
00505 copy_slotblock(node->blocks[i], node->blocks[i-1]);
00506
00507 insert_slotblock(node->blocks[index], ss, startslot, nslots);
00508 node->num_blocks++;
00509
00510 if (node->num_blocks == TREE_NODE_SIZE)
00511 {
00512
00513 btreenode *new_node = create_btree_node();
00514
00515 for (int i = TREE_NODE_MID+1; i < TREE_NODE_SIZE; i++)
00516 {
00517 int j = i - (TREE_NODE_MID+1);
00518 copy_slotblock(new_node->blocks[j], node->blocks[i]);
00519 }
00520
00521 node->num_blocks = TREE_NODE_MID;
00522 new_node->num_blocks = TREE_NODE_SIZE - TREE_NODE_MID - 1;
00523
00524 irv.sb = node->blocks[TREE_NODE_MID];
00525 irv.btn = new_node;
00526 }
00527 else
00528 {
00529 irv.btn = NULL;
00530 }
00531
00532 return irv;
00533 }
00534 };
00535
00536
00537 int index = node->num_blocks >> 1;
00538 int inc = (index >> 1) + (node->num_blocks & 0x1);
00539
00540
00541 while (1)
00542 {
00543 if (startslot < node->blocks[index].startslot)
00544 {
00545 if (index == 0 || startslot > node->blocks[index-1].startslot)
00546 {
00547 return helper(index);
00548 }
00549 else
00550 {
00551 index -= inc;
00552 if ((inc >>= 1) == 0)
00553 inc = 1;
00554 }
00555 }
00556 else
00557 {
00558 if (index == node->num_blocks-1 || startslot < node->blocks[index+1].startslot)
00559 {
00560 return helper(index+1);
00561 }
00562 else
00563 {
00564 index += inc;
00565 if ((inc >>= 1) == 0)
00566 inc = 1;
00567 }
00568 }
00569 }
00570 }
00571
00572 static btreenode *btree_insert(slotset *ss, btreenode *node,
00573 CmiInt8 startslot, CmiInt8 nslots)
00574 {
00575
00576
00577 if (node->num_blocks == 0)
00578 {
00579 node->num_blocks = 1;
00580 insert_slotblock(node->blocks[0], ss, startslot, nslots);
00581 }
00582 else
00583 {
00584
00585 insert_ret_val irv = btree_insert_int(ss, node, startslot, nslots);
00586
00587
00588 if (irv.btn != NULL)
00589 {
00590 btreenode *new_root = create_btree_node();
00591 new_root->num_blocks = 1;
00592 copy_slotblock(new_root->blocks[0], irv.sb);
00593 new_root->child[0] = node;
00594 new_root->child[1] = irv.btn;
00595 node = new_root;
00596 }
00597 }
00598
00599 return node;
00600 }
00601
00602
00603
00604
00605
00606 static void btree_delete_int(slotset *ss, btreenode *node,
00607 CmiInt8 startslot, slotblock *sb)
00608 {
00609 int index;
00610
00611
00612
00613
00614
00615
00616 if (sb != NULL)
00617 {
00618 if (node->child[0] != NULL)
00619 {
00620 btree_delete_int(ss, node->child[0], startslot, sb);
00621 index = 0;
00622 }
00623 else
00624 {
00625
00626
00627
00628
00629 list_delete(ss, sb);
00630 copy_slotblock(*sb, node->blocks[0]);
00631
00632
00633 for (int i = 0; i < (node->num_blocks - 1); i++)
00634 copy_slotblock(node->blocks[i], node->blocks[i+1]);
00635
00636 node->num_blocks--;
00637
00638 return;
00639 }
00640 }
00641 else
00642 {
00643
00644
00645
00646 index = node->num_blocks >> 1;
00647 int inc = (index >> 1) + (node->num_blocks & 0x1);
00648
00649
00650 while (1)
00651 {
00652 if (startslot == node->blocks[index].startslot)
00653 {
00654 if (node->child[index+1] != NULL)
00655 {
00656 btree_delete_int(ss, node->child[index+1],
00657 startslot, &(node->blocks[index]));
00658 break;
00659 }
00660 else
00661 {
00662
00663 list_delete(ss, &(node->blocks[index]));
00664 for (int i = index; i < (node->num_blocks - 1); i++)
00665 copy_slotblock(node->blocks[i], node->blocks[i+1]);
00666
00667 node->num_blocks--;
00668 return;
00669 }
00670 }
00671 else
00672 {
00673 if (startslot < node->blocks[index].startslot)
00674 {
00675 if (index == 0 || startslot > node->blocks[index-1].startslot)
00676 {
00677
00678 btree_delete_int(ss, node->child[index], startslot, sb);
00679 break;
00680 }
00681 else
00682 {
00683 index -= inc;
00684 if ((inc >>= 1) == 0)
00685 inc = 1;
00686 }
00687 }
00688 else
00689 {
00690 if (index == node->num_blocks - 1 || startslot < node->blocks[index+1].startslot)
00691 {
00692
00693 btree_delete_int(ss, node->child[index+1], startslot, sb);
00694 break;
00695 }
00696 else
00697 {
00698 index += inc;
00699 if ((inc >>= 1) == 0)
00700 inc = 1;
00701 }
00702 }
00703 }
00704 }
00705 }
00706
00707
00708
00709
00710
00711 int def_child = -1;
00712
00713
00714 if (node->child[index]->num_blocks < TREE_NODE_MID)
00715 def_child = index;
00716 else if (node->child[index+1]->num_blocks < TREE_NODE_MID)
00717 def_child = index+1;
00718
00719 if (def_child >= 0)
00720 {
00721 btreenode * dc = node->child[def_child];
00722
00723
00724
00725 if (def_child != 0 &&
00726 node->child[def_child-1] != NULL &&
00727 node->child[def_child-1]->num_blocks > TREE_NODE_MID)
00728 {
00729 btreenode * const dcleft = node->child[def_child-1];
00730 slotblock & leftblock = node->blocks[def_child-1];
00731
00732
00733 for (int i = dc->num_blocks; i > 0; i--)
00734 copy_slotblock(dc->blocks[i], dc->blocks[i-1]);
00735 for (int i = dc->num_blocks + 1; i > 0; i--)
00736 dc->child[i] = dc->child[i-1];
00737
00738
00739 copy_slotblock(dc->blocks[0], leftblock);
00740 dc->num_blocks++;
00741
00742
00743
00744 int j = dcleft->num_blocks;
00745 dc->child[0] = dcleft->child[j];
00746
00747
00748 j--;
00749 copy_slotblock(leftblock, dcleft->blocks[j]);
00750 dcleft->num_blocks--;
00751
00752 }
00753
00754
00755 else if ((def_child+1) <= node->num_blocks &&
00756 node->child[def_child+1] != NULL &&
00757 node->child[def_child+1]->num_blocks > TREE_NODE_MID)
00758 {
00759 btreenode * const dcright = node->child[def_child+1];
00760 slotblock & rightblock = node->blocks[def_child];
00761
00762
00763 int j = dc->num_blocks;
00764 copy_slotblock(dc->blocks[j], rightblock);
00765 dc->num_blocks++;
00766
00767
00768
00769 j++;
00770 dc->child[j] = dcright->child[0];
00771
00772
00773 copy_slotblock(rightblock, dcright->blocks[0]);
00774 dcright->num_blocks--;
00775
00776
00777 for (int i = 0; i < dcright->num_blocks; i++)
00778 copy_slotblock(dcright->blocks[i], dcright->blocks[i+1]);
00779 for (int i = 0; i < dcright->num_blocks + 1; i++)
00780 dcright->child[i] = dcright->child[i+1];
00781 }
00782
00783
00784
00785 else
00786 {
00787 btreenode * const left = node->child[index];
00788 btreenode *& right = node->child[index+1];
00789
00790
00791 int j = left->num_blocks;
00792 copy_slotblock(left->blocks[j], node->blocks[index]);
00793 left->num_blocks++;
00794
00795
00796
00797 int num_left = left->num_blocks;
00798 int num_right = right->num_blocks;
00799 for (int left_pos = num_left, right_pos = 0; left_pos < num_left + num_right; left_pos++, right_pos++)
00800 copy_slotblock(left->blocks[left_pos], right->blocks[right_pos]);
00801 for (int left_pos = num_left, right_pos = 0; left_pos < num_left + num_right + 1; left_pos++, right_pos++)
00802 left->child[left_pos] = right->child[right_pos];
00803
00804 left->num_blocks = num_left + num_right;
00805
00806
00807 free_reentrant(right);
00808 right = NULL;
00809
00810
00811 node->num_blocks--;
00812 for (int i = index; i < node->num_blocks; i++)
00813 {
00814 copy_slotblock(node->blocks[i], node->blocks[i+1]);
00815 node->child[i+1] = node->child[i+2];
00816 }
00817 }
00818 }
00819 }
00820
00821 static btreenode *btree_delete(slotset *ss, btreenode *node, CmiInt8 startslot)
00822 {
00823
00824 btree_delete_int(ss, node, startslot, NULL);
00825
00826
00827
00828
00829
00830 if (node->num_blocks == 0)
00831 {
00832 if (node->child[0] != NULL)
00833 {
00834 btreenode *new_root = node->child[0];
00835 free_reentrant(node);
00836 node = new_root;
00837 }
00838 }
00839
00840 return node;
00841 }
00842
00843
00844
00845
00846
00847
00848 static slotset *new_slotset(CmiInt8 startslot, CmiInt8 nslots)
00849 {
00850
00851 auto ss = (slotset *)malloc_reentrant(sizeof(slotset));
00852
00853
00854 ss->btree_root = create_btree_node();
00855
00856
00857 ss->btree_root->num_blocks = 1;
00858 slotblock & block = ss->btree_root->blocks[0];
00859 block.startslot = startslot;
00860 block.nslots = nslots;
00861
00862
00863 for (int i = 0; i < LIST_ARRAY_SIZE; i++)
00864 ss->list_array[i] = NULL;
00865
00866 auto bin = (dllnode *)malloc_reentrant(sizeof(dllnode));
00867 bin->previous = NULL;
00868 bin->next = NULL;
00869 bin->sb = █
00870
00871 int list_bin = find_list_bin(nslots);
00872 ss->list_array[list_bin] = bin;
00873 block.listblock = bin;
00874
00875 return ss;
00876 }
00877
00878
00879
00880
00881
00882
00883
00884 static CmiInt8 get_slots(slotset *ss, CmiInt8 nslots)
00885 {
00886
00887 int start_list = find_list_bin(nslots);
00888
00889
00890 for (int i = start_list; i < LIST_ARRAY_SIZE; i++)
00891 {
00892 dllnode *dlln = ss->list_array[i];
00893 while (dlln != NULL)
00894 {
00895 if (dlln->sb->nslots >= nslots)
00896 return dlln->sb->startslot;
00897
00898 dlln = dlln->next;
00899 }
00900 }
00901
00902
00903 return -1;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914 static void grab_slots(slotset *ss, CmiInt8 sslot, CmiInt8 nslots)
00915 {
00916 slotblock *sb = find_btree_slotblock(ss->btree_root, sslot);
00917
00918 if (sb == NULL)
00919 CmiAbort("requested a non-existent slotblock\n");
00920
00921 if (sb->startslot == sslot)
00922 {
00923
00924 if (sb->nslots == nslots)
00925 {
00926 ss->btree_root = btree_delete(ss, ss->btree_root, sslot);
00927 }
00928
00929 else
00930 {
00931 CmiInt8 old_nslots = sb->nslots;
00932 sb->startslot += nslots;
00933 sb->nslots -= nslots;
00934 list_move(ss, sb->listblock, old_nslots);
00935 }
00936 }
00937 else
00938 {
00939
00940 CmiInt8 endslot = sb->startslot + sb->nslots - 1;
00941 if (endslot == (sslot + nslots - 1))
00942 {
00943 CmiInt8 old_nslots = sb->nslots;
00944 sb->nslots -= nslots;
00945 list_move(ss, sb->listblock, old_nslots);
00946 }
00947
00948
00949
00950 else
00951 {
00952 CmiInt8 old_nslots = sb->nslots;
00953 sb->nslots = sslot - sb->startslot;
00954 list_move(ss, sb->listblock, old_nslots);
00955 ss->btree_root = btree_insert(ss, ss->btree_root, sslot + nslots,
00956 endslot - (sslot + nslots) + 1);
00957 }
00958 }
00959 }
00960
00961
00962
00963
00964
00965
00966
00967 static void free_slots(slotset *ss, CmiInt8 sslot, CmiInt8 nslots)
00968 {
00969 slotblock *sb_low = find_btree_slotblock(ss->btree_root, sslot - 1);
00970 slotblock *sb_high = find_btree_slotblock(ss->btree_root, sslot + nslots);
00971
00972 if (sb_low == NULL)
00973 {
00974 if (sb_high == NULL)
00975 {
00976
00977
00978 ss->btree_root = btree_insert(ss, ss->btree_root, sslot, nslots);
00979 }
00980 else
00981 {
00982
00983 CmiInt8 old_nslots = sb_high->nslots;
00984 sb_high->startslot = sslot;
00985 sb_high->nslots += nslots;
00986 list_move(ss, sb_high->listblock, old_nslots);
00987 }
00988 }
00989 else
00990 {
00991 if (sb_high == NULL)
00992 {
00993
00994 CmiInt8 old_nslots = sb_low->nslots;
00995 sb_low->nslots += nslots;
00996 list_move(ss, sb_low->listblock, old_nslots);
00997 }
00998 else
00999 {
01000
01001
01002
01003
01004 CmiInt8 old_nslots = sb_low->nslots;
01005 sb_low->nslots = sb_low->nslots + nslots + sb_high->nslots;
01006 list_move(ss, sb_low->listblock, old_nslots);
01007 ss->btree_root = btree_delete(ss, ss->btree_root, sb_high->startslot);
01008 }
01009 }
01010 }
01011
01012
01013
01014
01015
01016 static void delete_btree(btreenode *node)
01017 {
01018 for (int i = 0; i <= node->num_blocks; i++)
01019 {
01020 if (node->child[i] != NULL)
01021 {
01022 delete_btree(node->child[i]);
01023 free_reentrant(node->child[i]);
01024 }
01025 else
01026 {
01027 return;
01028 }
01029 }
01030 }
01031
01032
01033
01034
01035
01036 static void delete_list_array(slotset *ss)
01037 {
01038 for (int i = 0; i < LIST_ARRAY_SIZE; i++)
01039 {
01040 dllnode *dlln = ss->list_array[i];
01041 if (dlln != NULL)
01042 {
01043 while (dlln->next != NULL)
01044 {
01045 dlln = dlln->next;
01046 }
01047 while (dlln->previous != NULL)
01048 {
01049 dlln = dlln->previous;
01050 free_reentrant(dlln->next);
01051 }
01052 free_reentrant(dlln);
01053 }
01054 }
01055 }
01056
01057
01058
01059
01060
01061 static void delete_slotset(slotset *ss)
01062 {
01063 delete_btree(ss->btree_root);
01064 delete_list_array(ss);
01065 free_reentrant(ss->btree_root);
01066 free_reentrant(ss);
01067 }
01068
01069
01070
01071
01072
01073
01074
01075 static void print_btree_node(btreenode *node, int node_num)
01076 {
01077 int i;
01078 CmiPrintf("Node %2d: ", node_num);
01079 for (i = 0; i < node->num_blocks; i++)
01080 CmiPrintf("%d:[%lld,%lld] ", i, node->blocks[i].startslot, node->blocks[i].nslots);
01081 CmiPrintf("\n");
01082 }
01083
01084
01085 static int print_btree_level(btreenode *node, int level, int current_level, int node_num)
01086 {
01087 int another_level;
01088 for (int i = 0; i <= node->num_blocks; i++)
01089 {
01090 if (current_level == level)
01091 {
01092 print_btree_node(node, node_num);
01093 return node->child[0] != NULL;
01094 }
01095 else
01096 {
01097 another_level = print_btree_level(node->child[i], level,
01098 current_level + 1, i);
01099 }
01100 }
01101 return another_level;
01102 }
01103
01104 static void print_btree_top_down(btreenode *node)
01105 {
01106 int level = 0;
01107 int another_level;
01108 do
01109 {
01110 CmiPrintf("B-tree Level %d\n", level);
01111 CmiPrintf("---------------\n");
01112 another_level = print_btree_level(node, level, 0, 0);
01113 level++;
01114 CmiPrintf("\n\n");
01115 } while (another_level);
01116 }
01117
01118
01119
01120
01121
01122 static void print_list_array(slotset *ss)
01123 {
01124 CmiPrintf("List Array\n");
01125 CmiPrintf("----------\n");
01126 for (int i = 0; i < LIST_ARRAY_SIZE; i++)
01127 {
01128 CmiPrintf("List %2d: ", i);
01129 dllnode *dlln = ss->list_array[i];
01130 while (dlln != NULL)
01131 {
01132 if (dlln->previous != NULL)
01133 CmiPrintf("<->");
01134 else
01135 CmiPrintf(" ->");
01136
01137 CmiPrintf("[%lld,%lld]", dlln->sb->startslot, dlln->sb->nslots);
01138 dlln = dlln->next;
01139 }
01140 CmiPrintf("\n");
01141 }
01142 }
01143
01144 #if ISOMALLOC_DEBUG
01145 static void print_slots(slotset *ss)
01146 {
01147 print_btree_top_down(ss->btree_root);
01148 print_list_array(ss);
01149 }
01150 #else
01151 # define print_slots(ss)
01152 #endif
01153
01154
01155
01156 static int disabled_map_warned=0;
01157 static void *disabled_map(int nBytes)
01158 {
01159 if (!disabled_map_warned) {
01160 disabled_map_warned=1;
01161 if (CmiMyPe()==0)
01162 CmiError("Charm++> Warning: Isomalloc is uninitialized."
01163 " You won't be able to migrate threads.\n");
01164 }
01165 return malloc(nBytes);
01166 }
01167 static void disabled_unmap(void *bk) {
01168 free(bk);
01169 }
01170
01171
01172 static void disable_isomalloc(const char *why)
01173 {
01174 isomallocStart=NULL;
01175 isomallocEnd=NULL;
01176 if (CmiMyPe() == 0)
01177 CmiPrintf("Charm++> Disabling isomalloc because %s.\n", why);
01178 }
01179
01180 #if ! CMK_HAS_MMAP
01181
01182 static void *call_mmap_fixed(void *addr,size_t len) {
01183 CmiAbort("isomalloc.C: mmap_fixed should never be called here.");
01184 return NULL;
01185 }
01186 static void *call_mmap_anywhere(size_t len) {
01187 CmiAbort("isomalloc.C: mmap_anywhere should never be called here.");
01188 return NULL;
01189 }
01190 static void call_munmap(void *addr,size_t len) {
01191 CmiAbort("isomalloc.C: munmap should never be called here.");
01192 }
01193
01194 static int
01195 init_map(char **argv)
01196 {
01197 return 0;
01198 }
01199 #else
01200
01201 #include <sys/types.h>
01202 #include <sys/mman.h>
01203 #include <sys/stat.h>
01204 #include <fcntl.h>
01205
01206 #if !CMK_HAS_MMAP_ANON
01207 CpvStaticDeclare(int, zerofd);
01208 #endif
01209
01213 static void *call_mmap(void *addr,size_t len, int flags) {
01214 void *ret=mmap(addr, len, PROT_READ|PROT_WRITE,
01215 #if CMK_HAS_MMAP_ANON
01216 flags|MAP_PRIVATE|MAP_ANON,-1,
01217 #else
01218 flags|MAP_PRIVATE,CpvAccess(zerofd),
01219 #endif
01220 0);
01221 if (ret==((void*)(-1))) return (void *)0;
01222 else return ret;
01223 }
01224 static void *call_mmap_fixed(void *addr,size_t len) {
01225 return call_mmap(addr,len,MAP_FIXED);
01226 }
01227 static void *call_mmap_anywhere(size_t len) {
01228 return call_mmap((void *)0,len,0);
01229 }
01230
01231
01232 static void call_munmap(void *addr,size_t len) {
01233 int retval;
01234 if (addr == 0) return;
01235 retval = munmap(addr, len);
01236 if (retval==(-1))
01237 CmiAbort("munmap call failed to deallocate requested memory.\n");
01238 }
01239
01240 static int
01241 init_map(char **argv)
01242 {
01243 #if CMK_HAS_MMAP_ANON
01244
01245 #else
01246 CpvInitialize(int, zerofd);
01247 CpvAccess(zerofd) = open("/dev/zero", O_RDWR);
01248 if(CpvAccess(zerofd)<0)
01249 return 0;
01250 #endif
01251 return 1;
01252 }
01253
01254 #endif
01255
01259 static CmiIsomallocBlock *
01260 map_slots(CmiInt8 slot, CmiInt8 nslots)
01261 {
01262 void *pa;
01263 void *addr=slot2addr(slot);
01264 pa = call_mmap_fixed(addr, slotsize*nslots);
01265
01266 if (pa==NULL)
01267 {
01268 DEBUG_PRINT("[%d] tried to mmap %p, but encountered error\n",CmiMyPe(),addr);
01269 return NULL;
01270 }
01271 if (pa != addr)
01272 {
01273 DEBUG_PRINT("[%d] tried to mmap %p, but got %p back\n",CmiMyPe(),addr,pa);
01274 call_munmap(addr,slotsize*nslots);
01275 return NULL;
01276 }
01277 DEBUG_PRINT("[%d] mmap'd slots %ld-%ld to address %p\n",CmiMyPe(),slot,slot+nslots-1,addr);
01278 return (CmiIsomallocBlock *)pa;
01279 }
01280
01281
01282
01283
01284 static void
01285 unmap_slots(CmiInt8 slot, CmiInt8 nslots)
01286 {
01287 void *addr=slot2addr(slot);
01288 call_munmap(addr, slotsize*nslots);
01289 DEBUG_PRINT("[%d] munmap'd slots %ld-%ld from address %p\n",CmiMyPe(),slot,slot+nslots-1,addr);
01290 }
01291
01292 static void map_failed(CmiInt8 s,CmiInt8 n)
01293 {
01294 void *addr=slot2addr(s);
01295 CmiError("Charm++> Isomalloc map failed to allocate %d bytes at %p, errno: %d.\n",
01296 slotsize*n, addr, errno);
01297 CmiAbort("Exiting\n");
01298 }
01299
01300
01301
01302
01303
01304 CpvStaticDeclare(slotset *, myss);
01305
01306 #if CMK_USE_MEMPOOL_ISOMALLOC
01307 CtvDeclare(mempool_type *, threadpool);
01308
01309
01310 void * isomallocfn (size_t *size, mem_handle_t *mem_hndl, int expand_flag)
01311 {
01312 CmiInt8 s,n,i;
01313 void *newaddr;
01314 n=length2slots(*size);
01315
01316 s=get_slots(CpvAccess(myss),n);
01317 if (s==-1) {
01318 CmiError("Not enough address space left on processor %d to isomalloc %d bytes!\n",
01319 CmiMyPe(),*size);
01320 CmiAbort("Out of virtual address space for isomalloc");
01321 }
01322 grab_slots(CpvAccess(myss),s,n);
01323 for (i=0; i<5; i++) {
01324 newaddr=map_slots(s,n);
01325 if (newaddr!=NULL) break;
01326 #if CMK_HAS_USLEEP
01327 if (errno == ENOMEM) { usleep(rand()%1000); continue; }
01328 else break;
01329 #endif
01330 }
01331 if (!newaddr) map_failed(s,n);
01332 *((CmiInt8 *)mem_hndl) = s;
01333 *size = n*slotsize;
01334 return newaddr;
01335 }
01336
01337
01338 void isofreefn(void *ptr, mem_handle_t mem_hndl)
01339 {
01340 call_munmap(ptr, ((block_header *)ptr)->size);
01341 }
01342 #endif
01343
01344
01345 typedef struct {
01346 char *start;
01347 memRange_t len;
01348 const char *type;
01349 } memRegion_t;
01350
01351
01352 static void *__cur_stack_frame(void)
01353 {
01354 char __dummy = 'A';
01355 void *top_of_stack=(void *)&__dummy;
01356 return top_of_stack;
01357 }
01358
01359 static void *__static_data_loc(void)
01360 {
01361 static char __dummy;
01362 return (void *)&__dummy;
01363 }
01364
01365
01366
01367
01368 static int pointer_lt(const char *a,const char *b) {
01369 return ((memRange_t)a)<((memRange_t)b);
01370 }
01371 static int pointer_ge(const char *a,const char *b) {
01372 return ((memRange_t)a)>=((memRange_t)b);
01373 }
01374
01375 static char *pmin(char *a,char *b) {return pointer_lt(a,b)?a:b;}
01376 static char *pmax(char *a,char *b) {return pointer_lt(a,b)?b:a;}
01377
01378 const static memRange_t meg=1024u*1024u;
01379 const static memRange_t gig=1024u*1024u*1024u;
01380
01381
01382
01383
01384 static int bad_location(char *loc) {
01385 void *addr;
01386 addr=call_mmap_fixed(loc,slotsize);
01387 if (addr==NULL || addr!=loc) {
01388 DEBUG_PRINT("[%d] Skipping unmappable space at %p\n",CmiMyPe(),loc);
01389 return 1;
01390 }
01391 call_munmap(addr,slotsize);
01392 return 0;
01393 }
01394
01395
01396 static memRange_t divide_range(memRange_t len,int n) {
01397 return (len+1)/n;
01398 }
01399
01400
01401 static int partially_good(char *start,memRange_t len,int n) {
01402 int i;
01403 memRange_t quant=divide_range(len,n);
01404 CmiAssert (quant > 0);
01405 for (i=0;i<n;i++)
01406 if (!bad_location(start+i*quant)) return 1;
01407 return 0;
01408 }
01409
01410
01411
01412 static int good_range(char *start,memRange_t len,int n) {
01413 int i;
01414 memRange_t quant=divide_range(len,n);
01415 DEBUG_PRINT("good_range: %lld, %d\n", quant, n);
01416 CmiAssert (quant > 0);
01417
01418 for (i=0;i<n;i++)
01419 if (bad_location(start+i*quant)) return 0;
01420
01421 return 1;
01422 }
01423
01424
01425
01426
01427 static void check_range(char *start,char *end,memRegion_t *max)
01428 {
01429 memRange_t len;
01430 CmiUInt8 tb = (CmiUInt8)gig*1024ul;
01431 CmiUInt8 vm_limit = tb*256ul;
01432
01433 if (start>=end) return;
01434 len=(memRange_t)end-(memRange_t)start;
01435
01436 #if 0
01437
01438 if (len/gig>64u) {
01439 start+=16u*gig;
01440 end=start+32u*gig;
01441 len=(memRange_t)end-(memRange_t)start;
01442 }
01443 #else
01444
01445
01446 if (len/tb>10u) {
01447 const memRange_t other_libs=16ul*gig;
01448 start+=other_libs;
01449 end=pmin(start+vm_limit-2*other_libs, end-other_libs);
01450 len=(memRange_t)end-(memRange_t)start;
01451 }
01452 #endif
01453 if (len<=max->len) return;
01454 DEBUG_PRINT("[%d] Checking at %p - %p\n",CmiMyPe(),start,end);
01455
01456
01457 if (!good_range(start,len,256)) {
01458
01459 int i,n=2;
01460 DEBUG_PRINT("[%d] Trying to split bad address space at %p - %p...\n",CmiMyPe(),start,end);
01461 len=divide_range(len,n);
01462 for (i=0;i<n;i++) {
01463 char *cur=start+i*len;
01464 if (partially_good(cur,len,16))
01465 check_range(cur,cur+len,max);
01466 }
01467 return;
01468 }
01469 else
01470 {
01471 DEBUG_PRINT("[%d] Address space at %p - %p is largest\n",CmiMyPe(),start,end);
01472
01473
01474 max->len=len;
01475 max->start=start;
01476 max->type="Unused";
01477 }
01478 }
01479
01480
01481
01482
01483 static memRegion_t find_free_region(memRegion_t *used,int nUsed,int atLeast)
01484 {
01485 memRegion_t max;
01486 int i,j;
01487
01488 max.start=0;
01489 max.len=atLeast;
01490
01491 for (i=0;i<nUsed;i++) {
01492
01493 char *holeStart=used[i].start+used[i].len;
01494 char *holeEnd=(char *)(intptr_t)-1;
01495
01496
01497 for (j=0;j<nUsed && pointer_lt(holeStart,holeEnd);j++) {
01498 if (pointer_lt(used[j].start,holeStart))
01499 holeStart=pmax(holeStart,used[j].start+used[j].len);
01500 else if (pointer_lt(used[j].start,holeEnd))
01501 holeEnd=pmin(holeEnd,used[j].start);
01502 }
01503
01504 check_range(holeStart,holeEnd,&max);
01505 }
01506
01507 return max;
01508 }
01509
01510
01511
01512
01513
01514 static int find_largest_free_region(memRegion_t *destRegion) {
01515 char *staticData =(char *) __static_data_loc();
01516 char *code = (char *)&find_free_region;
01517 char *threadData = (char *)&errno;
01518 char *codeDll = (char *)fprintf;
01519 char *heapLil = (char*) malloc(1);
01520 char *heapBig = (char*) malloc(6*meg);
01521 char *stack = (char *)__cur_stack_frame();
01522 size_t mmapAnyLen = 1*meg;
01523 char *mmapAny = (char*) call_mmap_anywhere(mmapAnyLen);
01524
01525 int i,nRegions=0;
01526 memRegion_t regions[10];
01527 memRegion_t freeRegion;
01528
01529
01530 regions[nRegions].type="NULL";
01531 regions[nRegions].start=NULL;
01532 #if CMK_POWER7 && CMK_64BIT
01533 regions[nRegions++].len=2u*gig;
01534 #else
01535 regions[nRegions++].len=16u*meg;
01536 #endif
01537
01538 regions[nRegions].type="Static program data";
01539 regions[nRegions].start=staticData; regions[nRegions++].len=256u*meg;
01540
01541 regions[nRegions].type="Program executable code";
01542 regions[nRegions].start=code; regions[nRegions++].len=256u*meg;
01543
01544 regions[nRegions].type="Heap (small blocks)";
01545 regions[nRegions].start=heapLil; regions[nRegions++].len=1u*gig;
01546
01547 regions[nRegions].type="Heap (large blocks)";
01548 regions[nRegions].start=heapBig; regions[nRegions++].len=1u*gig;
01549
01550 regions[nRegions].type="Stack space";
01551 regions[nRegions].start=stack; regions[nRegions++].len=256u*meg;
01552
01553 regions[nRegions].type="Program dynamically linked code";
01554 regions[nRegions].start=codeDll; regions[nRegions++].len=256u*meg;
01555
01556 regions[nRegions].type="Result of a non-fixed call to mmap";
01557 regions[nRegions].start=mmapAny; regions[nRegions++].len=2u*gig;
01558
01559 regions[nRegions].type="Thread private data";
01560 regions[nRegions].start=threadData; regions[nRegions++].len=256u*meg;
01561
01562 _MEMCHECK(heapBig); free(heapBig);
01563 _MEMCHECK(heapLil); free(heapLil);
01564 call_munmap(mmapAny,mmapAnyLen);
01565
01566
01567 for (i=0;i<nRegions;i++) {
01568 memRegion_t old=regions[i];
01569 memRange_t p=(memRange_t)regions[i].start;
01570 p&=~(regions[i].len-1);
01571 regions[i].start=(char *)p;
01572 DEBUG_PRINT("[%d] Memory map: %p - %p (len: %lu => %lu) %s \n",CmiMyPe(),
01573 regions[i].start,regions[i].start+regions[i].len,
01574 old.len, regions[i].len, regions[i].type);
01575 }
01576
01577
01578 freeRegion=find_free_region(regions,nRegions,(512u)*meg);
01579
01580 if (freeRegion.start==0)
01581 {
01582 return 0;
01583 }
01584 else
01585 {
01586 *destRegion=freeRegion;
01587
01588 return 1;
01589 }
01590 }
01591
01592 static int try_largest_mmap_region(memRegion_t *destRegion)
01593 {
01594 void *bad_alloc=(void*)(-1);
01595 void *range, *good_range=NULL;
01596 double shrink = 1.5;
01597 static int count = 0;
01598 size_t size=((size_t)(-1l)), good_size=0;
01599 int retry = 0;
01600 if (sizeof(size_t) >= 8) size = size>>2;
01601 while (1) {
01602 #if CMK_HAS_MMAP
01603 range=mmap(NULL,size,PROT_READ|PROT_WRITE,
01604 MAP_PRIVATE
01605 #if CMK_HAS_MMAP_ANON
01606 |MAP_ANON
01607 #endif
01608 #if CMK_HAS_MMAP_NORESERVE
01609 |MAP_NORESERVE
01610 #endif
01611 ,-1,0);
01612 #else
01613 range = bad_alloc;
01614 #endif
01615 if (range == bad_alloc) {
01616 #if CMK_HAS_USLEEP
01617 if (retry++ < 5) { usleep(rand()%10000); continue; }
01618 else retry = 0;
01619 #endif
01620 size=(double)size/shrink;
01621 if (size<=0) return 0;
01622 }
01623 else {
01624 DEBUG_PRINT("[%d] available: %p, %lld\n", CmiMyPe(), range, size);
01625 call_munmap(range,size);
01626 if (size > good_size) {
01627 good_range = range;
01628 good_size = size;
01629 size=((double)size)*1.1;
01630 continue;
01631 }
01632 break;
01633 }
01634 }
01635 CmiAssert(good_range!=NULL);
01636 destRegion->start = (char *)good_range;
01637 destRegion->len=good_size;
01638 #if ISOMALLOC_DEBUG
01639 pid_t pid = getpid();
01640 {
01641 char s[128];
01642 sprintf(s, "cat /proc/%d/maps", pid);
01643 system(s);
01644 }
01645 DEBUG_PRINT("[%d] try_largest_mmap_region: %p, %lld\n", CmiMyPe(), good_range, good_size);
01646 #endif
01647 return 1;
01648 }
01649
01650 #ifndef CMK_CPV_IS_SMP
01651 #define CMK_CPV_IS_SMP
01652 #endif
01653
01654 static void init_ranges(char **argv)
01655 {
01656 memRegion_t freeRegion;
01657
01658 memRange_t intMax=(((memRange_t)1)<<(sizeof(int)*8-1))-1;
01659 int pagesize = 0;
01660 if (CmiMyRank()==0 && numslots==0)
01661 {
01662
01663 #if CMK_USE_MEMPOOL_ISOMALLOC
01664 slotsize=1024*1024;
01665 #else
01666 slotsize=16*1024;
01667 #endif
01668 pagesize = CmiGetPageSize();
01669 slotsize=(slotsize+pagesize-1) & ~(pagesize-1);
01670
01671 #if ISOMALLOC_DEBUG
01672 if (CmiMyPe() == 0)
01673 DEBUG_PRINT("[%d] Using slotsize of %d\n", CmiMyPe(), slotsize);
01674 #endif
01675 freeRegion.len=0u;
01676
01677 #ifdef CMK_MMAP_START_ADDRESS
01678 freeRegion.start=CMK_MMAP_START_ADDRESS;
01679 freeRegion.len=CMK_MMAP_LENGTH_MEGS*meg;
01680 #endif
01681
01682 if (freeRegion.len==0u) {
01683 if (_mmap_probe == 1) {
01684 if (try_largest_mmap_region(&freeRegion)) _sync_iso = 1;
01685 }
01686 else {
01687 if (freeRegion.len==0u) find_largest_free_region(&freeRegion);
01688 }
01689 }
01690
01691 #if 0
01692
01693 if (freeRegion.len/slotsize>intMax)
01694 freeRegion.len=intMax*slotsize;
01695 #endif
01696
01697 if (freeRegion.len==0u) {
01698 disable_isomalloc("no free virtual address space");
01699 }
01700 else
01701 {
01702 DEBUG_PRINT("[%d] Isomalloc memory region: %p - %p (%d megs)\n",CmiMyPe(),
01703 freeRegion.start,freeRegion.start+freeRegion.len,freeRegion.len/meg);
01704 }
01705 }
01706
01707 CmiNodeAllBarrier();
01708
01709
01710
01711
01712
01713
01714 if (_sync_iso == 1)
01715 {
01716 #ifdef __FAULT__
01717 if(_restart == 1){
01718 CmiUInt8 s = (CmiUInt8)freeRegion.start;
01719 CmiUInt8 e = (CmiUInt8)(freeRegion.start+freeRegion.len);
01720 CmiUInt8 ss, ee;
01721 int try_count, fd;
01722 char fname[128];
01723 sprintf(fname,".isomalloc");
01724 try_count = 0;
01725 while ((fd = open(fname, O_RDONLY)) == -1 && try_count<10000){
01726 try_count++;
01727 }
01728 if (fd == -1) {
01729 CmiAbort("isomalloc_sync failed during restart, make sure you have a shared file system.");
01730 }
01731 if (read(fd, &ss, sizeof(CmiUInt8)) != sizeof(CmiUInt8)) {
01732 CmiAbort("Isomalloc> call to read() failed during restart!");
01733 }
01734 if (read(fd, &ee, sizeof(CmiUInt8)) != sizeof(CmiUInt8)) {
01735 CmiAbort("Isomalloc> call to read() failed during restart!");
01736 }
01737 close(fd);
01738 if (ss < s || ee > e)
01739 CmiAbort("isomalloc_sync failed during restart, virtual memory regions do not overlap.");
01740 else {
01741 freeRegion.start = (char *)ss;
01742 freeRegion.len = (char *)ee -(char *)ss;
01743 }
01744 CmiPrintf("Charm++> Consolidated Isomalloc memory region at restart: %p - %p (%d MB).\n",freeRegion.start,freeRegion.start+freeRegion.len,freeRegion.len/meg);
01745 goto AFTER_SYNC;
01746 }
01747 #endif
01748 if (CmiMyRank() == 0 && freeRegion.len > 0u) {
01749 if (CmiBarrier() == -1 && CmiMyPe()==0)
01750 CmiAbort("Charm++ Error> +isomalloc_sync requires CmiBarrier() implemented.\n");
01751 else {
01752
01753 uintptr_t s = (uintptr_t)freeRegion.start;
01754
01755 uintptr_t e = (uintptr_t)freeRegion.start+freeRegion.len;
01756 int fd, i;
01757 char fname[128];
01758
01759 if (CmiMyNode() == 0)
01760 CmiPrintf("Charm++> Synchronizing isomalloc memory region...\n");
01761
01762 sprintf(fname,".isomalloc.%d", CmiMyNode());
01763
01764
01765 unlink(fname);
01766 #if CMK_HAS_SYNC && ! CMK_DISABLE_SYNC
01767 if (system("sync") == -1) {
01768 CmiAbort("Isomalloc> call to system(\"sync\") failed while synchronizing memory regions!");
01769 }
01770 #endif
01771
01772 CmiBarrier();
01773
01774
01775 while ((fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0644)) == -1)
01776 #ifndef __MINGW_H
01777 CMK_CPV_IS_SMP
01778 #endif
01779 ;
01780 if (write(fd, &s, sizeof(CmiUInt8)) != sizeof(CmiUInt8)) {
01781 CmiAbort("Isomalloc> call to write() failed while synchronizing memory regions!");
01782 }
01783 if (write(fd, &e, sizeof(CmiUInt8)) != sizeof(CmiUInt8)) {
01784 CmiAbort("Isomalloc> call to write() failed while synchronizing memory regions!");
01785 }
01786 close(fd);
01787
01788 #if CMK_HAS_SYNC && ! CMK_DISABLE_SYNC
01789 if (system("sync") == -1) {
01790 CmiAbort("Isomalloc> call to system(\"sync\") failed while synchronizing memory regions!");
01791 }
01792 #endif
01793
01794 CmiBarrier();
01795
01796 for (i=0; i<CmiNumNodes(); i++) {
01797 CmiUInt8 ss, ee;
01798 int try_count;
01799 char fname[128];
01800 if (i==CmiMyNode()) continue;
01801 sprintf(fname,".isomalloc.%d", i);
01802 try_count = 0;
01803 while ((fd = open(fname, O_RDONLY)) == -1 && try_count<10000)
01804 {
01805 try_count++;
01806 #ifndef __MINGW_H
01807 CMK_CPV_IS_SMP
01808 #endif
01809 ;
01810 }
01811 if (fd == -1) {
01812 CmiAbort("isomalloc_sync failed, make sure you have a shared file system.");
01813 }
01814 if (read(fd, &ss, sizeof(CmiUInt8)) != sizeof(CmiUInt8)) {
01815 CmiAbort("Isomalloc> call to read() failed while synchronizing memory regions!");
01816 }
01817 if (read(fd, &ee, sizeof(CmiUInt8)) != sizeof(CmiUInt8)) {
01818 CmiAbort("Isomalloc> call to read() failed while synchronizing memory regions!");
01819 }
01820 #if ISOMALLOC_DEBUG
01821 if (CmiMyPe() == 0)
01822 DEBUG_PRINT("[%d] load node %d isomalloc region: %lx %lx.\n", CmiMyPe(), i, ss, ee);
01823 #endif
01824 close(fd);
01825 if (ss>s) s = ss;
01826 if (ee<e) e = ee;
01827 }
01828
01829 CmiBarrier();
01830
01831 unlink(fname);
01832 #if CMK_HAS_SYNC && ! CMK_DISABLE_SYNC
01833 if (system("sync") == -1) {
01834 CmiAbort("Isomalloc> call to system(\"sync\") failed while synchronizing memory regions!");
01835 }
01836 #endif
01837
01838
01839 if (s > e) {
01840 if (CmiMyPe()==0) CmiPrintf("[%d] Invalid isomalloc region: %lx - %lx.\n", CmiMyPe(), s, e);
01841 CmiAbort("Isomalloc> failed to find consolidated isomalloc region!");
01842 }
01843 freeRegion.start = (char *)(uintptr_t)s;
01844 freeRegion.len = (char *)(uintptr_t)e -(char *)(uintptr_t)s;
01845
01846 if (CmiMyPe() == 0)
01847 CmiPrintf("Charm++> Consolidated Isomalloc memory region: %p - %p (%d MB).\n",
01848 freeRegion.start,freeRegion.start+freeRegion.len,
01849 freeRegion.len/meg);
01850 #if __FAULT__
01851 if(CmiMyPe() == 0){
01852 int fd;
01853 char fname[128];
01854 CmiUInt8 s = (CmiUInt8)freeRegion.start;
01855 CmiUInt8 e = (CmiUInt8)(freeRegion.start+freeRegion.len);
01856 sprintf(fname,".isomalloc");
01857 while ((fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0644)) == -1);
01858 if (write(fd, &s, sizeof(CmiUInt8)) != sizeof(CmiUInt8)) {
01859 CmiAbort("Isomalloc> call to write() failed while synchronizing memory regions!");
01860 }
01861 if (write(fd, &e, sizeof(CmiUInt8)) != sizeof(CmiUInt8)) {
01862 CmiAbort("Isomalloc> call to write() failed while synchronizing memory regions!");
01863 }
01864 close(fd);
01865 }
01866 #endif
01867 }
01868 }
01869 else {
01870 CmiBarrier();
01871 CmiBarrier();
01872 CmiBarrier();
01873 CmiBarrier();
01874 }
01875 }
01876
01877 #ifdef __FAULT__
01878 AFTER_SYNC:
01879 #endif
01880
01881 if (CmiMyRank() == 0 && freeRegion.len > 0u)
01882 {
01883
01884 isomallocStart=freeRegion.start;
01885 isomallocEnd=freeRegion.start+freeRegion.len;
01886 numslots=(freeRegion.len/slotsize)/CmiNumPes();
01887
01888 DEBUG_PRINT("[%d] Can isomalloc up to %lu MB per PE\n",CmiMyPe(),
01889 ((memRange_t)numslots)*slotsize/meg);
01890 }
01891
01892
01893 CmiNodeAllBarrier();
01894
01895 CpvInitialize(slotset *, myss);
01896 CpvAccess(myss) = NULL;
01897
01898 #if CMK_USE_MEMPOOL_ISOMALLOC
01899 CmiLock(_smp_mutex);
01900 CtvInitialize(mempool_type *, threadpool);
01901 CtvAccess(threadpool) = NULL;
01902 CmiUnlock(_smp_mutex);
01903 #endif
01904
01905 if (isomallocStart!=NULL) {
01906 CpvAccess(myss) = new_slotset(pe2slot(CmiMyPe()), numslots);
01907 }
01908 }
01909
01910
01911
01912 typedef struct _slotmsg
01913 {
01914 char cmicore[CmiMsgHeaderSizeBytes];
01915 int pe;
01916 CmiInt8 slot;
01917 CmiInt8 nslots;
01918 } slotmsg;
01919
01920 static slotmsg *prepare_slotmsg(CmiInt8 slot,CmiInt8 nslots)
01921 {
01922 slotmsg *m=(slotmsg *)CmiAlloc(sizeof(slotmsg));
01923 m->pe=CmiMyPe();
01924 m->slot=slot;
01925 m->nslots=nslots;
01926 return m;
01927 }
01928
01929 static void grab_remote(slotmsg *msg)
01930 {
01931 grab_slots(CpvAccess(myss),msg->slot,msg->nslots);
01932 CmiFree(msg);
01933 }
01934
01935 static void free_remote(slotmsg *msg)
01936 {
01937 free_slots(CpvAccess(myss),msg->slot,msg->nslots);
01938 CmiFree(msg);
01939 }
01940 static int grab_remote_idx, free_remote_idx;
01941
01942 struct slotOP {
01943
01944 void (*local)(slotset *ss,CmiInt8 s,CmiInt8 n);
01945
01946 int remote;
01947 };
01948 typedef struct slotOP slotOP;
01949 static slotOP grabOP,freeOP;
01950
01951 static void init_comm(char **argv)
01952 {
01953 CmiAssignOnce(&grab_remote_idx, CmiRegisterHandler((CmiHandler)grab_remote));
01954 CmiAssignOnce(&free_remote_idx, CmiRegisterHandler((CmiHandler)free_remote));
01955 grabOP.local=grab_slots;
01956 grabOP.remote=grab_remote_idx;
01957 freeOP.local=free_slots;
01958 freeOP.remote=free_remote_idx;
01959 }
01960
01961
01962
01963 static void one_slotOP(const slotOP *op,int pe,CmiInt8 s,CmiInt8 n)
01964 {
01965
01966
01967 CmiInt8 p_s=pe2slot(pe), p_e=pe2slot(pe+1);
01968 CmiInt8 e=s+n;
01969 if (s<p_s) s=p_s;
01970 if (e>p_e) e=p_e;
01971 n=e-s;
01972
01973
01974 if (pe==CmiMyPe())
01975 op->local(CpvAccess(myss),s,n);
01976 else
01977 {
01978 slotmsg *m=prepare_slotmsg(s,n);
01979 CmiSetHandler(m, freeOP.remote);
01980 CmiSyncSendAndFree(pe,sizeof(slotmsg),m);
01981 }
01982 }
01983
01984
01985
01986
01987
01988 static void all_slotOP(const slotOP *op,CmiInt8 s,CmiInt8 n)
01989 {
01990 int spe=slot2pe(s), epe=slot2pe(s+n-1);
01991 int pe;
01992 for (pe=spe; pe<=epe; pe++)
01993 one_slotOP(op,pe,s,n);
01994 }
01995
01996
01997 #if CMK_USE_MEMPOOL_ISOMALLOC
01998 static CmiIsomallocBlock *isomalloc_internal_alloc_block(size_t size, mempool_type *pool)
01999 {
02000 CmiIsomallocBlock *blk = (CmiIsomallocBlock*)mempool_malloc(pool, size, 1);
02001 blk->slot = (CmiInt8)(uintptr_t)blk;
02002 return blk;
02003 }
02004 #else
02005 static CmiIsomallocBlock *isomalloc_internal_alloc_block(size_t size)
02006 {
02007 CmiInt8 s,n,i;
02008 CmiIsomallocBlock *blk;
02009 if (isomallocStart==NULL) return (CmiIsomallocBlock *)disabled_map(size);
02010 n=length2slots(size);
02011
02012 s=get_slots(CpvAccess(myss),n);
02013 if (s==-1) {
02014 CmiError("Not enough address space left on processor %d to isomalloc %d bytes!\n",
02015 CmiMyPe(),size);
02016 CmiAbort("Out of virtual address space for isomalloc");
02017 }
02018 grab_slots(CpvAccess(myss),s,n);
02019 for (i=0; i<5; i++) {
02020 blk=map_slots(s,n);
02021 if (blk!=NULL) break;
02022 #if CMK_HAS_USLEEP
02023 if (errno == ENOMEM) { usleep(rand()%1000); continue; }
02024 else break;
02025 #endif
02026 }
02027 if (!blk) map_failed(s,n);
02028 blk->slot=s;
02029 return blk;
02030 }
02031 #endif
02032
02033 #if CMK_USE_MEMPOOL_ISOMALLOC
02034 void* CmiIsomallocFromPool(size_t size, mempool_type *pool)
02035 #else
02036 void *CmiIsomallocPlain(int size)
02037 #endif
02038 {
02039 CmiIsomallocBlock *blk = isomalloc_internal_alloc_block(size + sizeof(CmiIsomallocBlock)
02040 #if CMK_USE_MEMPOOL_ISOMALLOC
02041 , pool
02042 #endif
02043 );
02044 blk->length = size;
02045 blk->align = 0;
02046 blk->alignoffset = 0;
02047 return block2pointer(blk);
02048 }
02049
02050 #define MALLOC_ALIGNMENT ALIGN_BYTES
02051 #define MINSIZE (sizeof(CmiIsomallocBlock))
02052
02053 static size_t isomalloc_internal_validate_align(size_t align)
02054 {
02055 if (align < MINSIZE) align = MINSIZE;
02056
02057 if ((align & (align - 1)) != 0) {
02058 size_t a = MALLOC_ALIGNMENT * 2;
02059 while ((unsigned long)a < (unsigned long)align) a <<= 1;
02060 return a;
02061 }
02062 return align;
02063 }
02064
02065 static void *isomalloc_internal_perform_alignment(CmiIsomallocBlock *blk, size_t align, size_t alignoffset)
02066 {
02067 void *ptr = block2pointer(blk);
02068 CmiIntPtr ptr2align = (CmiIntPtr)ptr + alignoffset;
02069 if (ptr2align % align != 0) {
02070 CmiIsomallocBlock savedblk = *blk;
02071 ptr2align = (ptr2align + align - 1) & -((CmiInt8) align);
02072 ptr2align -= alignoffset;
02073 ptr = (void*)ptr2align;
02074 blk = pointer2block(ptr);
02075 *blk = savedblk;
02076 }
02077 return ptr;
02078 }
02079
02080
02081 static void *isomalloc_internal_alloc_aligned(size_t useralign, size_t usersize, size_t blocklistsize, CmiIsomallocBlockList *list)
02082 {
02083 size_t size = usersize + blocklistsize;
02084 size_t align = isomalloc_internal_validate_align(useralign);
02085 CmiIsomallocBlock *blk = isomalloc_internal_alloc_block(size + sizeof(CmiIsomallocBlock) + align
02086 #if CMK_USE_MEMPOOL_ISOMALLOC
02087 , list->pool
02088 #endif
02089 );
02090 blk->length = size;
02091 blk->align = align;
02092 blk->alignoffset = blocklistsize;
02093 return isomalloc_internal_perform_alignment(blk, align, blocklistsize);
02094 }
02095
02096 int CmiIsomallocEnabled(void)
02097 {
02098 return (isomallocStart!=NULL);
02099 }
02100
02101 void CmiIsomallocPup(pup_er p,void **blockPtrPtr)
02102 {
02103 CmiIsomallocBlock *blk;
02104 CmiInt8 s,length,align,alignoffset;
02105 CmiInt8 n;
02106 #if CMK_USE_MEMPOOL_ISOMALLOC
02107 CmiAbort("Incorrect pup is called\n");
02108 #endif
02109 if (isomallocStart==NULL) CmiAbort("isomalloc is disabled-- cannot use IsomallocPup");
02110
02111 if (!pup_isUnpacking(p))
02112 {
02113 blk=pointer2block(*blockPtrPtr);
02114 s=blk->slot;
02115 length=blk->length;
02116 align=blk->align;
02117 alignoffset=blk->alignoffset;
02118 }
02119
02120 pup_int8(p,&s);
02121 pup_int8(p,&length);
02122 pup_int8(p,&align);
02123 pup_int8(p,&alignoffset);
02124 n=length2slots(length + sizeof(CmiIsomallocBlock) + align);
02125
02126 if (pup_isUnpacking(p))
02127 {
02128 if (pup_isUserlevel(p) || pup_isRestarting(p))
02129 {
02130 all_slotOP(&grabOP,s,n);
02131 }
02132 blk=map_slots(s,n);
02133 if (!blk) map_failed(s,n);
02134 blk->slot=s;
02135
02136 blk->length = length;
02137 blk->align = align;
02138 blk->alignoffset = alignoffset;
02139 *blockPtrPtr = align > 0 ? isomalloc_internal_perform_alignment(blk, align, alignoffset) : block2pointer(blk);
02140 }
02141
02142
02143 pup_bytes(p,*blockPtrPtr,length);
02144
02145 if (pup_isDeleting(p))
02146 {
02147 unmap_slots(s,n);
02148 *blockPtrPtr=NULL;
02149 }
02150 }
02151
02152 void CmiIsomallocFree(void *blockPtr)
02153 {
02154 if (isomallocStart==NULL) {
02155 disabled_unmap(pointer2block(blockPtr));
02156 }
02157 else if (blockPtr!=NULL)
02158 {
02159 #if CMK_USE_MEMPOOL_ISOMALLOC
02160 mempool_free_thread((void*)(uintptr_t)pointer2block(blockPtr)->slot);
02161 #else
02162 CmiIsomallocBlock *blk=pointer2block(blockPtr);
02163 CmiInt8 s=blk->slot;
02164 CmiInt8 n=length2slots(blk->length);
02165 unmap_slots(s,n);
02166
02167 all_slotOP(&freeOP,s,n);
02168 #endif
02169 }
02170 }
02171
02172 CmiInt8 CmiIsomallocLength(void *block)
02173 {
02174 return pointer2block(block)->length;
02175 }
02176
02177
02178 int CmiIsomallocInRange(void *addr)
02179 {
02180 if (isomallocStart==NULL) return 0;
02181 return (addr == NULL) || (pointer_ge((char *)addr,isomallocStart) &&
02182 pointer_lt((char*)addr,isomallocEnd));
02183 }
02184
02185 int _sync_iso_warned = 0;
02186
02187 void CmiIsomallocInit(char **argv)
02188 {
02189 #if CMK_NO_ISO_MALLOC
02190 disable_isomalloc("isomalloc disabled by conv-mach");
02191 #else
02192 if (CmiGetArgFlagDesc(argv,"+noisomalloc","disable isomalloc")) {
02193 disable_isomalloc("isomalloc disabled by user.");
02194 return;
02195 }
02196 #if CMK_MMAP_PROBE
02197 _mmap_probe = 1;
02198 #elif CMK_MMAP_TEST
02199 _mmap_probe = 0;
02200 #endif
02201 if (CmiGetArgFlagDesc(argv,"+isomalloc_probe","call mmap to probe the largest available isomalloc region"))
02202 _mmap_probe = 1;
02203 if (CmiGetArgFlagDesc(argv,"+isomalloc_test","mmap test common areas for the largest available isomalloc region"))
02204 _mmap_probe = 0;
02205 if (CmiGetArgFlagDesc(argv,"+isomalloc_sync","synchronize isomalloc region globaly"))
02206 _sync_iso = 1;
02207 #if __FAULT__
02208 if (CmiGetArgFlagDesc(argv,"+restartisomalloc","restarting isomalloc on this processor after a crash"))
02209 _restart = 1;
02210 #endif
02211 init_comm(argv);
02212 if (!init_map(argv)) {
02213 disable_isomalloc("mmap() does not work");
02214 }
02215 else {
02216
02217 if (CmiMyPe() == 0 && read_randomflag() == 1 && _sync_iso == 0 && _sync_iso_warned == 0) {
02218 _sync_iso_warned = 1;
02219 CmiPrintf("Warning> Randomization of virtual memory (ASLR) is turned "
02220 "on in the kernel, thread migration may not work! Run 'echo 0 > "
02221 "/proc/sys/kernel/randomize_va_space' as root to disable it, "
02222 "or try running with '+isomalloc_sync'.\n");
02223 }
02224
02225 init_ranges(argv);
02226 }
02227 #endif
02228 }
02229
02230
02231
02232
02233
02234
02235
02236
02237 static char *Slot_toUser(CmiIsomallocBlockList *s) {return (char *)(s+1);}
02238 static CmiIsomallocBlockList *Slot_fmUser(void *s) {return ((CmiIsomallocBlockList *)s)-1;}
02239
02240
02241 CmiIsomallocBlockList *CmiIsomallocBlockListNew(void)
02242 {
02243 CmiIsomallocBlockList *ret;
02244
02245 #if CMK_USE_MEMPOOL_ISOMALLOC
02246 mempool_type *pool = mempool_init(2*(sizeof(CmiIsomallocBlock)+sizeof(mempool_header)) + sizeof(mempool_type),
02247 isomallocfn, isofreefn, 0);
02248 ret = (CmiIsomallocBlockList *)CmiIsomallocFromPool(sizeof(*ret), pool);
02249 ret->pool = pool;
02250 #else
02251 ret = (CmiIsomallocBlockList *)CmiIsomallocPlain(sizeof(*ret));
02252 #endif
02253
02254 ret->next=ret;
02255 ret->prev=ret;
02256 return ret;
02257 }
02258
02259
02260 static void print_myslots(void);
02261
02262
02263
02264
02265
02266 #if CMK_USE_MEMPOOL_ISOMALLOC
02267 void CmiIsomallocBlockListPup(pup_er p,CmiIsomallocBlockList **lp)
02268 {
02269 mempool_type *mptr;
02270 block_header *current, *block_head;
02271 large_block_header* lcurr;
02272 slot_header *currSlot;
02273 void *newblock;
02274 CmiInt8 slot;
02275 size_t size;
02276 int flags[2];
02277 int i, j;
02278 int dopup = 1;
02279 int numBlocks = 0, numSlots = 0, flag = 1;
02280
02281 if(!pup_isUnpacking(p)) {
02282 CmiAssert(*lp);
02283 mptr = (*lp)->pool;
02284
02285 if(mptr == NULL) {
02286 dopup = 0;
02287 } else {
02288 dopup = 1;
02289 }
02290 }
02291
02292 pup_int(p,&dopup);
02293 if(!dopup) return;
02294
02295 DEBUG_PRINT("[%d] My rank is %lld Pupping with isUnpack %d isDelete %d \n",
02296 CmiMyPe(),CthSelf(),pup_isUnpacking(p),pup_isDeleting(p));
02297 flags[0] = 0; flags[1] = 1;
02298 if(!pup_isUnpacking(p)) {
02299 current = MEMPOOL_GetBlockHead(mptr);
02300 while(current != NULL) {
02301 numBlocks++;
02302 current = MEMPOOL_GetBlockNext(current)?(block_header *)((char*)mptr+MEMPOOL_GetBlockNext(current)):NULL;
02303 }
02304 DEBUG_PRINT("Number of blocks packed %d\n",numBlocks);
02305 pup_int(p,&numBlocks);
02306 current = MEMPOOL_GetBlockHead(mptr);
02307 while(current != NULL) {
02308 pup_size_t(p,&(MEMPOOL_GetBlockSize(current)));
02309 pup_int8(p,(CmiInt8*)&(MEMPOOL_GetBlockMemHndl(current)));
02310 numSlots = 0;
02311 if(flag) {
02312 pup_bytes(p,current,sizeof(mempool_type));
02313 currSlot = (slot_header*)((char*)current+sizeof(mempool_type));
02314 } else {
02315 pup_bytes(p,current,sizeof(block_header));
02316 currSlot = (slot_header*)((char*)current+sizeof(block_header));
02317 }
02318 while(currSlot != NULL) {
02319 numSlots++;
02320 currSlot = (MEMPOOL_GetSlotGNext(currSlot))?(slot_header*)((char*)mptr+MEMPOOL_GetSlotGNext(currSlot)):NULL;
02321 }
02322 pup_int(p,&numSlots);
02323 if(flag) {
02324 currSlot = (slot_header*)((char*)current+sizeof(mempool_type));
02325 flag = 0;
02326 } else {
02327 currSlot = (slot_header*)((char*)current+sizeof(block_header));
02328 }
02329 while(currSlot != NULL) {
02330 pup_size_t(p,&currSlot->size);
02331 if(MEMPOOL_GetSlotStatus(currSlot)) {
02332 pup_int(p,&flags[0]);
02333 pup_bytes(p,(void*)currSlot,sizeof(slot_header));
02334 } else {
02335 pup_int(p,&flags[1]);
02336 pup_bytes(p,(void*)currSlot,MEMPOOL_GetSlotSize(currSlot));
02337 }
02338 currSlot = (MEMPOOL_GetSlotGNext(currSlot))?(slot_header*)((char*)mptr+MEMPOOL_GetSlotGNext(currSlot)):NULL;
02339 }
02340 current = (MEMPOOL_GetBlockNext(current))?(block_header *)((char*)mptr+MEMPOOL_GetBlockNext(current)):NULL;
02341 }
02342
02343 numBlocks = 0;
02344 lcurr = (mptr->large_blocks)?(large_block_header*)((char*)mptr + mptr->large_blocks):NULL;
02345 while(lcurr != NULL) {
02346 numBlocks++;
02347 lcurr = lcurr->block_next ? (large_block_header *)((char*)mptr + lcurr->block_next) : NULL;
02348 }
02349 pup_int(p,&numBlocks);
02350 lcurr = (mptr->large_blocks)?(large_block_header*)((char*)mptr + mptr->large_blocks):NULL;
02351 while(lcurr != NULL) {
02352 pup_size_t(p,&(MEMPOOL_GetBlockSize(lcurr)));
02353 pup_int8(p,(CmiInt8*)&(MEMPOOL_GetBlockMemHndl(lcurr)));
02354 pup_bytes(p,lcurr,MEMPOOL_GetBlockSize(lcurr));
02355 lcurr = lcurr->block_next ? (large_block_header *)((char*)mptr + lcurr->block_next) : NULL;
02356 }
02357 }
02358
02359 if(pup_isUnpacking(p)) {
02360
02361 pup_int(p,&numBlocks);
02362 DEBUG_PRINT("Number of blocks to be unpacked %d\n",numBlocks);
02363 for(i = 0; i < numBlocks; i++) {
02364 pup_size_t(p,&size);
02365 pup_int8(p,&slot);
02366 newblock = map_slots(slot,size/slotsize);
02367 if(flag) {
02368 mptr = (mempool_type*)newblock;
02369 pup_bytes(p,newblock,sizeof(mempool_type));
02370 newblock = (char*)newblock + sizeof(mempool_type);
02371 flag = 0;
02372 } else {
02373 pup_bytes(p,newblock,sizeof(block_header));
02374 newblock = (char*)newblock + sizeof(block_header);
02375 }
02376 pup_int(p,&numSlots);
02377 for(j=0; j < numSlots; j++) {
02378 pup_size_t(p,&size);
02379 pup_int(p,&flags[1]);
02380 if(flags[1] == 0) {
02381 pup_bytes(p,newblock,sizeof(slot_header));
02382 } else {
02383 pup_bytes(p,newblock,size);
02384 }
02385 newblock = (char*)newblock + size;
02386 }
02387 }
02388
02389 pup_int(p,&numBlocks);
02390 for(i = 0; i < numBlocks; i++) {
02391 pup_size_t(p,&size);
02392 pup_int8(p,&slot);
02393 newblock = map_slots(slot,size/slotsize);
02394 pup_bytes(p,newblock,size);
02395 }
02396 #if CMK_USE_MEMPOOL_ISOMALLOC || (CMK_SMP && CMK_CONVERSE_UGNI)
02397 mptr->mempoolLock = CmiCreateLock();
02398 #endif
02399 }
02400 pup_pointer(p,(void**)lp);
02401 if(pup_isDeleting(p)) {
02402 mempool_destroy(mptr);
02403 *lp=NULL;
02404 }
02405 #if ISOMALLOC_DEBUG
02406 CmiPrintf("Isomalloc:pup done\n");
02407 #endif
02408 }
02409 #else
02410 void CmiIsomallocBlockListPup(pup_er p,CmiIsomallocBlockList **lp)
02411 {
02412
02413
02414
02415 int i,nBlocks=0;
02416 CmiIsomallocBlockList *cur=NULL, *start=*lp;
02417
02418
02419 if (!pup_isUnpacking(p)) {
02420 nBlocks=1;
02421 for (cur=start->next; cur!=start; cur=cur->next)
02422 nBlocks++;
02423
02424 cur=start;
02425 }
02426 pup_int(p,&nBlocks);
02427
02428
02429 for (i=0;i<nBlocks;i++) {
02430 void *newBlock=cur;
02431 if (!pup_isUnpacking(p))
02432 {
02433 cur=cur->next;
02434 }
02435 CmiIsomallocPup(p,&newBlock);
02436 if (i==0 && pup_isUnpacking(p))
02437 *lp=(CmiIsomallocBlockList *)newBlock;
02438 }
02439 if (pup_isDeleting(p))
02440 *lp=NULL;
02441
02442
02443
02444 }
02445 #endif
02446
02447
02448 void CmiIsomallocBlockListDelete(CmiIsomallocBlockList *l)
02449 {
02450 CmiIsomallocBlockList *start=l;
02451 CmiIsomallocBlockList *cur=start;
02452 #if CMK_USE_MEMPOOL_ISOMALLOC
02453 mempool_type *pool;
02454 #endif
02455 if (cur==NULL) return;
02456 #if CMK_USE_MEMPOOL_ISOMALLOC
02457 pool = cur->pool;
02458 #endif
02459 do {
02460 CmiIsomallocBlockList *doomed=cur;
02461 cur=cur->next;
02462 CmiIsomallocFree(doomed);
02463 } while (cur!=start);
02464 #if CMK_USE_MEMPOOL_ISOMALLOC
02465 mempool_destroy(pool);
02466 #endif
02467 }
02468
02469
02470 void *CmiIsomallocBlockListMalloc(CmiIsomallocBlockList *l,size_t nBytes)
02471 {
02472 CmiIsomallocBlockList *n;
02473 #if CMK_USE_MEMPOOL_ISOMALLOC
02474 n = (CmiIsomallocBlockList *)CmiIsomallocFromPool(sizeof(CmiIsomallocBlockList)+nBytes, l->pool);
02475 #else
02476 n = (CmiIsomallocBlockList *)CmiIsomallocPlain(sizeof(CmiIsomallocBlockList)+nBytes);
02477 #endif
02478
02479 n->prev=l;
02480 n->next=l->next;
02481 l->next->prev=n;
02482 l->next=n;
02483 return Slot_toUser(n);
02484 }
02485
02486
02487 void *CmiIsomallocBlockListMallocAlign(CmiIsomallocBlockList *l,size_t align,size_t nBytes)
02488 {
02489 CmiIsomallocBlockList *n;
02490 n=(CmiIsomallocBlockList *)isomalloc_internal_alloc_aligned(align, nBytes, sizeof(CmiIsomallocBlockList), l);
02491
02492 n->prev=l;
02493 n->next=l->next;
02494 l->next->prev=n;
02495 l->next=n;
02496 return Slot_toUser(n);
02497 }
02498
02499
02500 void CmiIsomallocBlockListFree(void *block)
02501 {
02502 CmiIsomallocBlockList *n=Slot_fmUser(block);
02503 #if DOHEAPCHECK
02504 if (n->prev->next!=n || n->next->prev!=n)
02505 CmiAbort("Heap corruption detected in isomalloc block list header!\n"
02506 " Run with ++debug and look for writes to negative array indices");
02507 #endif
02508
02509 n->prev->next=n->next;
02510 n->next->prev=n->prev;
02511 CmiIsomallocFree(n);
02512 }
02513
02514
02515 static void print_myslots(void) {
02516 CmiPrintf("[%d] my slot set=%p\n", CmiMyPe(), CpvAccess(myss));
02517 print_slots(CpvAccess(myss));
02518 }