void bst_help_marked(node_t* pred, operation_t* pred_op, node_t* curr/*, node_t* root*/){ //fprintf(stderr, "bst help marked\n"); node_t* new_ref; if (ISNULL(curr->left)) { if (ISNULL(curr->right)) { new_ref = (node_t*)SETNULL(curr); } else { new_ref = curr->right; } } else { new_ref = curr->left; } // allocate memory // operation_t* cas_op = new child_cas_op(curr==pred->left, curr, new_ref); operation_t* cas_op = (operation_t*) ssalloc_alloc(1, sizeof(operation_t)); cas_op->child_cas_op.is_left = (curr == pred->left); cas_op->child_cas_op.expected = curr; cas_op->child_cas_op.update = new_ref; // fprintf(stderr, "cas_op address: %p, is_left address: %p, expected addr: %p, update addr: %p\n", (unsigned long)cas_op, &(cas_op->child_cas_op.is_left), &(cas_op->child_cas_op.expected), &(cas_op->child_cas_op.update) // ); if (CAS_PTR(&(pred->op), pred_op, FLAG(cas_op, STATE_OP_CHILDCAS)) == pred_op) { bst_help_child_cas(cas_op, pred/*, root*/); } }
bool_t bst_remove(bst_key_t k, node_t* root, int id){ //fprintf(stderr, "bst remove\n"); // node_t* pred; // node_t* curr; node_t* replace = NULL; // operation_t* pred_op; // operation_t* curr_op; operation_t* replace_op = NULL; operation_t* reloc_op = NULL; bst_search_result_t* my_result; while(TRUE) { //root is now a global pointer to a node, not a node my_result = bst_find(k, /*&pred, &pred_op, &curr, &curr_op,*/ root, root, id); if (my_result->result != FOUND) { return FALSE; } if (ISNULL(my_result->curr->right) || ISNULL(my_result->curr->left)) { // node has less than two children if (CAS_PTR(&(my_result->curr->op), my_result->curr_op, FLAG(my_result->curr_op, STATE_OP_MARK)) == my_result->curr_op) { bst_help_marked(my_result->pred, my_result->pred_op, my_result->curr/*, root*/); return TRUE; } } else { // node has two children node_t* curr = my_result->curr; my_search_result[id]->pred = my_result->pred; my_search_result[id]->pred_op = my_result->pred_op; my_search_result[id]->curr = replace; my_search_result[id]->curr_op = replace_op; // my_result = bst_find(k, &pred, &pred_op, &replace, &replace_op, curr, root, id); my_result = bst_find(k, curr, root, id); if ((my_result->result == ABORT) || (my_result->curr->op != my_result->curr_op)) { continue; } //allocate memory //reloc_op = new RelocateOP(curr, curr_op, k, replace->key); reloc_op = (operation_t*) ssalloc_alloc(1, sizeof(operation_t)); reloc_op->relocate_op.state = STATE_OP_ONGOING; reloc_op->relocate_op.dest = my_result->curr; reloc_op->relocate_op.dest_op = my_result->curr_op; reloc_op->relocate_op.remove_key = k; reloc_op->relocate_op.replace_key = replace->key; // fprintf(stderr, "reloc_op address: %p, state address: %p, dest addr: %p, dest_op addr: %p, remove_key addr: %p, replace_key addr: %p \n", (unsigned long)reloc_op, &(reloc_op->relocate_op.state), &(reloc_op->relocate_op.dest), &(reloc_op->relocate_op.dest_op), &(reloc_op->relocate_op.remove_key), &(reloc_op->relocate_op.replace_key) // ); if (CAS_PTR(&(replace->op), replace_op, FLAG(reloc_op, STATE_OP_RELOCATE)) == replace_op) { if (bst_help_relocate(reloc_op, my_result->pred, my_result->pred_op, replace/*, root*/)) { return TRUE; } } } } }
bool_t bst_add(bst_key_t k, node_t* root, int id){ //fprintf(stderr, "bst add\n"); // node_t* pred; // node_t* curr; node_t* new_node; // operation_t* pred_op; // operation_t* curr_op; operation_t* cas_op; // search_res_t result; bst_search_result_t* my_result; while(TRUE) { //root is now a global pointer to a node, not a node my_result = bst_find(k, /*&pred, &pred_op, &curr, &curr_op, */root, root, id); if (my_result->result == FOUND) { return FALSE; } // allocate memory // new_node = new Node(k); new_node = (node_t*) ssalloc(sizeof(node_t)); new_node->key = k; new_node->op = NULL; new_node->left = NULL; new_node->right = NULL; // fprintf(stderr, "new_node address: %p, 64bit aligned: %d key address %p, left node addr: %p, right node addr: %p, op addr: %p\n", new_node, ((unsigned long)new_node & 7) == 0,&(new_node->key), &(new_node->left), &(new_node->right), &(new_node->op) // ); bool_t is_left = (my_result->result == NOT_FOUND_L); node_t* old; if (is_left) { old = my_result->curr->left; } else { old = my_result->curr->right; } // allocate memory //cas_op = new child_cas_op_t(is_left, old, new_node) cas_op = (operation_t*) ssalloc_alloc(1, sizeof(operation_t)); cas_op->child_cas_op.is_left = is_left; cas_op->child_cas_op.expected = old; cas_op->child_cas_op.update = new_node; // fprintf(stderr, "cas_op address: %p, is_left address: %p, expected addr: %p, update addr: %p\n", (unsigned long)cas_op, &(cas_op->child_cas_op.is_left), &(cas_op->child_cas_op.expected), &(cas_op->child_cas_op.update) // ); if (CAS_PTR(&(my_result->curr->op), my_result->curr_op, FLAG(cas_op, STATE_OP_CHILDCAS)) == my_result->curr_op) { // legit cast? YES!! verif bst_help_child_cas(cas_op, my_result->curr/*, root*/); return TRUE; } } }
bool_t bst_remove(bst_key_t k, node_t* root){ node_t* pred; node_t* curr; node_t* replace; operation_t* pred_op; operation_t* curr_op; operation_t* replace_op; operation_t* reloc_op; while(TRUE) { if (bst_find(k, &pred, &pred_op, &curr, &curr_op, root, root) != FOUND) { return FALSE; } if (ISNULL(curr->right) || ISNULL(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); return TRUE; } } else { // node has two children if ((bst_find(k, &pred, &pred_op, &replace, &replace_op, curr, root) == ABORT) || (curr->op != curr_op)) { continue; } reloc_op = (operation_t*) ssalloc_alloc(1, sizeof(operation_t)); 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.replace_key = replace->key; #if defined(__tile__) MEM_BARRIER; #endif if (CAS_PTR(&(replace->op), replace_op, FLAG(reloc_op, STATE_OP_RELOCATE)) == replace_op) { if (bst_help_relocate(reloc_op, pred, pred_op, replace, root)) { return TRUE; } } } } }
bool_t bst_add(bst_key_t k, node_t* root){ node_t* pred; node_t* curr; node_t* new_node; operation_t* pred_op; operation_t* curr_op; operation_t* cas_op; search_res_t result; while(TRUE) { result = bst_find(k, &pred, &pred_op, &curr, &curr_op, root, root); if (result == FOUND) { return FALSE; } new_node = (node_t*) ssalloc(sizeof(node_t)); new_node->key = k; new_node->op = NULL; new_node->left = NULL; new_node->right = NULL; bool_t is_left = (result == NOT_FOUND_L); node_t* old; if (is_left) { old = curr->left; } else { old = curr->right; } cas_op = (operation_t*) ssalloc_alloc(1, sizeof(operation_t)); cas_op->child_cas_op.is_left = is_left; cas_op->child_cas_op.expected = old; cas_op->child_cas_op.update = new_node; #if defined(__tile__) MEM_BARRIER; #endif if (CAS_PTR(&curr->op, curr_op, FLAG(cas_op, STATE_OP_CHILDCAS)) == curr_op) { bst_help_child_cas(cas_op, curr, root); return TRUE; } } }
/* Links the node into the per-thread list of pending deletions. */ void free_node_later (void *q) { uint8_t my_index = ltd.thread_index; mr_node_t* wrapper_node = ssalloc_alloc(1, sizeof(mr_node_t)); wrapper_node->actual_node = q; // Create timestamp in mr node gettimeofday(&(wrapper_node->created), NULL); add_to_head(ltd.limbo_list[shtd[my_index].epoch], wrapper_node); ltd.rcount++; ltd.free_calls++; if (fallback.flag == 1 && ltd.free_calls >= R) { ltd.free_calls = 0; scan(); } }
void bst_help_marked(node_t* pred, operation_t* pred_op, node_t* curr, node_t* root){ node_t* new_ref; if (ISNULL(curr->left)) { if (ISNULL(curr->right)) { new_ref = (node_t*)SETNULL(curr); } else { new_ref = curr->right; } } else { new_ref = curr->left; } operation_t* cas_op = (operation_t*) ssalloc_alloc(1, sizeof(operation_t)); cas_op->child_cas_op.is_left = (curr == pred->left); cas_op->child_cas_op.expected = curr; cas_op->child_cas_op.update = new_ref; if (CAS_PTR(&(pred->op), pred_op, FLAG(cas_op, STATE_OP_CHILDCAS)) == pred_op) { bst_help_child_cas(cas_op, pred, root); } }
void* ssalloc(size_t size) { return ssalloc_alloc(0, size); }