bool_t bst_help_relocate(operation_t* op, node_t* pred, operation_t* pred_op, node_t* curr, node_t* root){ CLEANUP_TRY(); int seen_state = op->relocate_op.state; if (seen_state == STATE_OP_ONGOING) { // VCAS in original implementation operation_t* seen_op = CAS_PTR(&(op->relocate_op.dest->op), op->relocate_op.dest_op, FLAG(op, STATE_OP_RELOCATE)); if ((seen_op == op->relocate_op.dest_op) || (seen_op == (operation_t *)FLAG(op, STATE_OP_RELOCATE))){ CAS_U32(&(op->relocate_op.state), STATE_OP_ONGOING, STATE_OP_SUCCESSFUL); seen_state = STATE_OP_SUCCESSFUL; if (seen_op == op->relocate_op.dest_op) { #if GC == 1 if (UNFLAG(seen_op)!=0) ssmem_free(alloc,(void*)UNFLAG(seen_op)); #endif } } else { // VCAS in original implementation seen_state = CAS_U32(&(op->relocate_op.state), STATE_OP_ONGOING, STATE_OP_FAILED); } } if (seen_state == STATE_OP_SUCCESSFUL) { skey_t UNUSED dummy0 = CAS_PTR(&(op->relocate_op.dest->key), op->relocate_op.remove_key, op->relocate_op.replace_key); skey_t UNUSED dummy1 = CAS_PTR(&(op->relocate_op.dest->value), op->relocate_op.remove_value, op->relocate_op.replace_value); void* UNUSED dummy2 = CAS_PTR(&(op->relocate_op.dest->op), FLAG(op, STATE_OP_RELOCATE), FLAG(op, STATE_OP_NONE)); }
void bst_help(node_t* pred, operation_t* pred_op, node_t* curr, operation_t* curr_op/*, node_t* root */){ //fprintf(stderr, "bst help\n"); if (GETFLAG(curr_op) == STATE_OP_CHILDCAS) { bst_help_child_cas((operation_t*)UNFLAG(curr_op), curr/*, root*/); } else if (GETFLAG(curr_op) == STATE_OP_RELOCATE) { bst_help_relocate((operation_t*)UNFLAG(curr_op), pred, pred_op, curr/*, root*/); } else if (GETFLAG(curr_op) == STATE_OP_MARK) { bst_help_marked(pred, pred_op, curr/*, root*/); } }
void bst_help(node_t* pred, operation_t* pred_op, node_t* curr, operation_t* curr_op, node_t* root ){ if (GETFLAG(curr_op) == STATE_OP_CHILDCAS) { bst_help_child_cas((operation_t*)UNFLAG(curr_op), curr, root); } else if (GETFLAG(curr_op) == STATE_OP_RELOCATE) { bst_help_relocate((operation_t*)UNFLAG(curr_op), pred, pred_op, curr, root); } else if (GETFLAG(curr_op) == STATE_OP_MARK) { bst_help_marked(pred, pred_op, curr, root); } }
/* * coalesce * Boundary tag coalescing. Return ptr to coalesced block * delete or insert entry of free list. */ static void *coalesce(void *bp) { size_t prev_alloc = IS_PREV_ALLOC(HDRP(bp)); size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp))); size_t size = GET_SIZE(HDRP(bp)); if (prev_alloc && next_alloc) { /* Case 1 */ /* nop */ } else if (prev_alloc && !next_alloc) { /* Case 2 */ if (heap_tailp == NEXT_BLKP(bp)) { heap_tailp = bp; } delete_node(get_level(GET_SIZE(HDRP(NEXT_BLKP(bp)))), NEXT_BLKP(bp)); size += GET_SIZE(HDRP(NEXT_BLKP(bp))); PUT(HDRP(bp), PACK3(size, 2, 0)); PUT(FTRP(bp), PACK3(size, 2, 0)); } else if (!prev_alloc && next_alloc) { /* Case 3 */ int t = (bp == heap_tailp); delete_node(get_level(GET_SIZE(HDRP(PREV_BLKP(bp)))), PREV_BLKP(bp)); size += GET_SIZE(HDRP(PREV_BLKP(bp))); SET_SIZE(FTRP(bp), size); SET_SIZE(HDRP(PREV_BLKP(bp)), size); bp = PREV_BLKP(bp); if (t) { heap_tailp = bp; } } else { /* Case 4 */ int t = (NEXT_BLKP(bp) == heap_tailp); delete_node(get_level(GET_SIZE(HDRP(PREV_BLKP(bp)))), PREV_BLKP(bp)); delete_node(get_level(GET_SIZE(HDRP(NEXT_BLKP(bp)))), NEXT_BLKP(bp)); size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp))); SET_SIZE(HDRP(PREV_BLKP(bp)), size); SET_SIZE(FTRP(NEXT_BLKP(bp)), size); bp = PREV_BLKP(bp); if (t) { heap_tailp = bp; } } UNFLAG(HDRP(NEXT_BLKP(bp))); insert_node(get_level(GET_SIZE(HDRP(bp))), bp); return bp; }
bst_search_result_t* bst_find(bst_key_t k, node_t* aux_root, node_t* root, int id){ //fprintf(stderr, "bst find\n"); bst_search_result_t* my_result = my_search_result[id]; // search_res_t result; bst_key_t curr_key; node_t* next; node_t* last_right; operation_t* last_right_op; retry: my_result->result = NOT_FOUND_R; my_result->curr = aux_root; my_result->curr_op = my_result->curr->op; if(GETFLAG(my_result->curr_op) != STATE_OP_NONE){ fprintf(stderr, "Shouldn't be here\n"); //root is now a pointer to a node, not a node if (aux_root == root){ bst_help_child_cas((operation_t*)UNFLAG(my_result->curr_op), my_result->curr/*, aux_root*/); goto retry; } else { my_result->result = ABORT; return my_result; } } next = my_result->curr->right; last_right = my_result->curr; last_right_op = my_result->curr_op; while (!ISNULL(next)){ my_result->pred = my_result->curr; my_result->pred_op = my_result->curr_op; my_result->curr = next; my_result->curr_op = (my_result->curr)->op; if(GETFLAG(my_result->curr_op) != STATE_OP_NONE){ fprintf(stderr, "Shouldn't be here 2\n"); bst_help(my_result->pred, my_result->pred_op, my_result->curr, my_result->curr_op/*, aux_root*/); goto retry; } curr_key = (my_result->curr)->key; if(k < curr_key){ my_result->result = NOT_FOUND_L; next = (my_result->curr)->left; } else if(k > curr_key) { my_result->result = NOT_FOUND_R; next = (my_result->curr)->right; last_right = my_result->curr; last_right_op = my_result->curr_op; } else{ my_result->result = FOUND; break; } } if ((my_result->result != FOUND) && (last_right_op != last_right->op)) { fprintf(stderr, "Shouldn't be here 3\n"); goto retry; } if ((my_result->curr)->op != my_result->curr_op){ fprintf(stderr, "Shouldn't be here 4\n"); goto retry; } return my_result; }
sval_t bst_find(skey_t k, node_t** pred, operation_t** pred_op, node_t** curr, operation_t** curr_op, node_t* aux_root, node_t* root){ sval_t result; skey_t curr_key; node_t* next; node_t* last_right; operation_t* last_right_op; retry: PARSE_TRY(); result = NOT_FOUND_R; *curr = aux_root; *curr_op = (*curr)->op; if(GETFLAG(*curr_op) != STATE_OP_NONE){ #ifdef __tile__ MEM_BARRIER; #endif if (aux_root == root){ bst_help_child_cas((operation_t*)UNFLAG(*curr_op), *curr, root); goto retry; } else { return ABORT; } } next = (node_t*) (*curr)->right; last_right = *curr; last_right_op = *curr_op; while (!ISNULL(next)){ *pred = *curr; *pred_op = *curr_op; *curr = next; *curr_op = (*curr)->op; if(GETFLAG(*curr_op) != STATE_OP_NONE){ bst_help(*pred, *pred_op, *curr, *curr_op, root); goto retry; } curr_key = (*curr)->key; if(k < curr_key){ result = NOT_FOUND_L; next = (node_t*) (*curr)->left; } else if(k > curr_key) { result = NOT_FOUND_R; next = (node_t*) (*curr)->right; last_right = *curr; last_right_op = *curr_op; } else{ result = (*curr)->value; break; } } if ((!(result & val_mask)) && (last_right_op != last_right->op)) { goto retry; } if ((*curr)->op != *curr_op){ goto retry; } return result; }
sval_t bst_remove(skey_t k, node_t* root){ node_t* pred; node_t* curr; node_t* replace; sval_t val; operation_t* pred_op; operation_t* curr_op; operation_t* replace_op; operation_t* reloc_op=NULL; while(TRUE) { UPDATE_TRY(); sval_t res = bst_find(k, &pred, &pred_op, &curr, &curr_op, root, root); if (!(res & val_mask)) { #if GC == 1 //if (reloc_op!=NULL) ssmem_free(alloc,reloc_op); #endif return 0; } if (ISNULL((node_t*) curr->right) || ISNULL((node_t*) curr->left)) { // node has less than two children if (CAS_PTR(&(curr->op), curr_op, FLAG(curr_op, STATE_OP_MARK)) == curr_op) { bst_help_marked(pred, pred_op, curr, root); #if GC == 1 //if (reloc_op!=NULL) ssmem_free(alloc,reloc_op); if (UNFLAG(curr->op)!=0) ssmem_free(alloc,(void*)UNFLAG(curr->op)); ssmem_free(alloc,curr); #endif return res; } } else { // node has two children val = bst_find(k, &pred, &pred_op, &replace, &replace_op, curr, root); if ((val == ABORT) || (curr->op != curr_op)) { continue; } //if (reloc_op==NULL) { reloc_op = alloc_op(); //} reloc_op->relocate_op.state = STATE_OP_ONGOING; reloc_op->relocate_op.dest = curr; reloc_op->relocate_op.dest_op = curr_op; reloc_op->relocate_op.remove_key = k; reloc_op->relocate_op.remove_value = res; reloc_op->relocate_op.replace_key = replace->key; reloc_op->relocate_op.replace_value = replace->value; #if defined(__tile__) MEM_BARRIER; #endif if (CAS_PTR(&(replace->op), replace_op, FLAG(reloc_op, STATE_OP_RELOCATE)) == replace_op) { #if GC == 1 if (UNFLAG(replace_op)!=0) ssmem_free(alloc,(void*)UNFLAG(replace_op)); #endif if (bst_help_relocate(reloc_op, pred, pred_op, replace, root)) { //if (UNFLAG(replace->op)!=0) ssmem_free(alloc,(void*)UNFLAG(replace->op)); #if GC == 1 //ssmem_free(alloc,replace); #endif return res; } } else { #if GC == 1 ssmem_free(alloc,reloc_op); // reloc_op=NULL; #endif } } } }
search_res_t bst_find(bst_key_t k, node_t** pred, operation_t** pred_op, node_t** curr, operation_t** curr_op, node_t* aux_root, node_t* root){ search_res_t result; bst_key_t curr_key; node_t* next; node_t* last_right; operation_t* last_right_op; retry: result = NOT_FOUND_R; *curr = aux_root; *curr_op = (*curr)->op; if(GETFLAG(*curr_op) != STATE_OP_NONE){ if (aux_root == root){ bst_help_child_cas((operation_t*)UNFLAG(*curr_op), *curr, root); goto retry; } else { return ABORT; } } next = (*curr)->right; last_right = *curr; last_right_op = *curr_op; while (!ISNULL(next)){ *pred = *curr; *pred_op = *curr_op; *curr = next; *curr_op = (*curr)->op; if(GETFLAG(*curr_op) != STATE_OP_NONE){ bst_help(*pred, *pred_op, *curr, *curr_op, root); goto retry; } curr_key = (*curr)->key; if(k < curr_key){ result = NOT_FOUND_L; next = (*curr)->left; } else if(k > curr_key) { result = NOT_FOUND_R; next = (*curr)->right; last_right = *curr; last_right_op = *curr_op; } else{ result = FOUND; break; } } if ((result != FOUND) && (last_right_op != last_right->op)) { goto retry; } if ((*curr)->op != *curr_op){ goto retry; } return result; }