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