bool_t bst_add(skey_t k,sval_t v, node_t* root){ node_t* pred; node_t* curr; node_t* new_node = NULL; operation_t* pred_op; operation_t* curr_op; operation_t* cas_op; sval_t result; while(TRUE) { UPDATE_TRY(); result = bst_find(k, &pred, &pred_op, &curr, &curr_op, root, root); if (result & val_mask) { #if GC == 1 if (new_node!=NULL) { ssmem_free(alloc,new_node); } #endif return FALSE; } if (new_node == NULL) { new_node = create_node(k,v,0); } bool_t is_left = (result == NOT_FOUND_L); node_t* old; if (is_left) { old = (node_t*) curr->left; } else { old = (node_t*) curr->right; } cas_op = alloc_op(); 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); #if GC == 1 //if (UNFLAG(curr_op)!=0) ssmem_free(alloc,(void*)UNFLAG(curr_op)); #endif return TRUE; } else { #if GC == 1 ssmem_free(alloc,cas_op); #endif } } }
bool_t bst_insert(skey_t key, sval_t val, node_t* node_r) { node_t* new_internal = NULL; node_t* new_node = NULL; uint created = 0; while (1) { UPDATE_TRY(); bst_seek(key, node_r); if (seek_record->leaf->key == key) { #if GC == 1 if (created) { ssmem_free(alloc, new_internal); ssmem_free(alloc, new_node); } #endif return FALSE; } node_t* parent = seek_record->parent; node_t* leaf = seek_record->leaf; node_t** child_addr; if (key < parent->key) { child_addr= (node_t**) &(parent->left); } else { child_addr= (node_t**) &(parent->right); } if (likely(created==0)) { new_internal=create_node(max(key,leaf->key),0,0); new_node = create_node(key,val,0); created=1; } else { new_internal->key=max(key,leaf->key); } if ( key < leaf->key) { new_internal->left = new_node; new_internal->right = leaf; } else { new_internal->right = new_node; new_internal->left = leaf; } #ifdef __tile__ MEM_BARRIER; #endif node_t* result = CAS_PTR(child_addr, ADDRESS(leaf), ADDRESS(new_internal)); if (result == ADDRESS(leaf)) { return TRUE; } node_t* chld = *child_addr; if ( (ADDRESS(chld)==leaf) && (GETFLAG(chld) || GETTAG(chld)) ) { bst_cleanup(key); } } }
sval_t cpy_delete(copy_on_write_t* set, skey_t key) { size_t bucket = key & set->hash; array_ll_t* all_old; #if CPY_ON_WRITE_READ_ONLY_FAIL == 1 all_old = (array_ll_t*) set->array[bucket]; if (cpy_array_search(all_old, key) == 0) { return 0; } #endif sval_t removed = 0; GL_LOCK(set->lock); LOCK(set->lock + bucket); all_old = (array_ll_t*) set->array[bucket]; array_ll_t* all_new = array_ll_new(all_old->size - 1); int i, n; for (i = 0, n = 0; i < all_old->size; i++, n++) { if (unlikely(all_old->kvs[i].key == key)) { removed = all_old->kvs[i].val; n--; continue; } all_new->kvs[n].key = all_old->kvs[i].key; all_new->kvs[n].val = all_old->kvs[i].val; } if (removed) { set->array[bucket] = all_new; ssmem_free(alloc, (void*) all_old); } else { ssmem_free(alloc, (void*) all_new); } GL_UNLOCK(set->lock); UNLOCK(set->lock + bucket); return removed; }
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 queue_delete_node(queue_node_t *n) { #if GC == 1 ssmem_free(alloc, (void*) n); #endif }
sval_t fraser_remove(sl_intset_t *set, skey_t key) { UPDATE_TRY(); sl_node_t* succs[FRASER_MAX_MAX_LEVEL]; sval_t result = 0; PARSE_START_TS(2); int found = fraser_search_no_cleanup_succs(set, key, succs); PARSE_END_TS(2, lat_parsing_rem++); if (!found) { return false; } sl_node_t* node_del = succs[0]; int my_delete = mark_node_ptrs(node_del); if (my_delete) { result = node_del->val; fraser_search(set, key, NULL, NULL); #if GC == 1 ssmem_free(alloc, (void*) succs[0]); #endif } return result; }
void node_delete(node_t *node) { #if GC == 1 ssmem_free(alloc, node); #else /* ssfree(node); */ #endif }
void node_delete(node_t *node) { #if GC == 1 && SEQ_SSMEM_NO_FREE != 1 ssmem_free(alloc, (void*) node); #else #endif }
void node_delete(node_t *node) { #if GC == 1 && SEQ_SSMEM_NO_FREE != 1 ssmem_free(alloc, node); #else /* ssfree(node); */ #endif }
int cpy_insert(copy_on_write_t* set, skey_t key, sval_t val) { size_t bucket = key & set->hash; array_ll_t* all_old; #if CPY_ON_WRITE_READ_ONLY_FAIL == 1 all_old = (array_ll_t*) set->array[bucket]; if (cpy_array_search(all_old, key) == 1) { return 0; } #endif GL_LOCK(set->lock); LOCK(set->lock + bucket); all_old = (array_ll_t*) set->array[bucket]; array_ll_t* all_new = array_ll_new(all_old->size + 1); int i; for (i = 0; i < all_old->size; i++) { if (unlikely(all_old->kvs[i].key == key)) { ssmem_free(alloc, (void*) all_new); GL_UNLOCK(set->lock); UNLOCK(set->lock + bucket); return 0; } all_new->kvs[i].key = all_old->kvs[i].key; all_new->kvs[i].val = all_old->kvs[i].val; } all_new->kvs[i].key = key; all_new->kvs[i].val = val; set->array[bucket] = all_new; ssmem_free(alloc, (void*) all_old); GL_UNLOCK(set->lock); UNLOCK(set->lock + bucket); return 1; }
/* * File: optik.c * Author: Vasileios Trigonakis <*****@*****.**> * Description: * * Copyright (c) 2014 Vasileios Trigonakis <*****@*****.**>, * Distributed Programming Lab (LPD), EPFL * * ASCYLIB is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, version 2 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include "linkedlist-optik.h" RETRY_STATS_VARS; sval_t optik_find(intset_l_t *set, skey_t key) { PARSE_TRY(); node_l_t* curr = set->head; while (curr != NULL && curr->key < key) { curr = curr->next; } sval_t res = 0; if (curr != NULL && curr->key == key) { res = curr->val; } return res; } #if !defined(LL_GLOBAL_LOCK) int optik_insert(intset_l_t *set, skey_t key, sval_t val) { restart: PARSE_TRY(); volatile node_l_t *curr, *pred = NULL; COMPILER_NO_REORDER(optik_t pred_ver = set->lock); curr = set->head; while (curr != NULL && (curr->key < key)) { pred = curr; curr = curr->next; } UPDATE_TRY(); if (curr != NULL && curr->key == key) { return false; } if (!optik_trylock_version(&set->lock, pred_ver)) { goto restart; } node_l_t* newnode = new_node_l(key, val, curr, 0); #ifdef __tile__ MEM_BARRIER; #endif if (pred != NULL) { pred->next = newnode; } else { set->head = newnode; } optik_unlock(&set->lock); return true; } #else /* LL_GLOBAL_LOCK == 1 :: pessimistic */ int optik_insert(intset_l_t *set, skey_t key, sval_t val) { volatile node_l_t *curr, *pred; COMPILER_NO_REORDER(optik_t pred_ver = set->lock); int r; for (r = 0; r < 2; r++) { PARSE_TRY(); pred = NULL; curr = set->head; while (curr != NULL && curr->key < key) { pred = curr; curr = curr->next; } UPDATE_TRY(); if (curr != NULL && curr->key == key) { if (r) { optik_unlock(&set->lock); } return false; } if (!r && optik_lock_version(&set->lock, pred_ver)) { break; } } node_l_t* newnode = new_node_l(key, val, curr, 0); #ifdef __tile__ MEM_BARRIER; #endif if (pred != NULL) { pred->next = newnode; } else { set->head = newnode; } optik_unlock(&set->lock); return true; } #endif /* LL_GLOBAL_LOCK */ #if !defined(LL_GLOBAL_LOCK) sval_t optik_delete(intset_l_t *set, skey_t key) { restart: PARSE_TRY(); volatile node_l_t *pred = NULL, *curr; sval_t result = 0; COMPILER_NO_REORDER(optik_t pred_ver = set->lock); curr = set->head; while (curr != NULL && curr->key < key) { pred = curr; curr = curr->next; } UPDATE_TRY(); if (curr == NULL || curr->key != key) { return false; } if ((!optik_trylock_version(&set->lock, pred_ver))) { goto restart; } result = curr->val; if (pred != NULL) { pred->next = curr->next; } else { set->head = curr->next; } optik_unlock(&set->lock); #if GC == 1 ssmem_free(alloc, (void*) curr); #endif return result; } #else /* LL_GLOBAL_LOCK = 1 :: pessimistic locking */ sval_t optik_delete(intset_l_t *set, skey_t key) { volatile node_l_t *pred, *curr; COMPILER_NO_REORDER(optik_t pred_ver = set->lock); int r; for (r = 0; r < 2; r++) { PARSE_TRY(); pred = NULL; curr = set->head; while (curr != NULL && curr->key < key) { pred = curr; curr = curr->next; } UPDATE_TRY(); if (curr == NULL || curr->key != key) { if (r) { optik_unlock(&set->lock); } return false; } if (!r && optik_lock_version(&set->lock, pred_ver)) { break; } } sval_t result = curr->val; if (pred != NULL) { pred->next = curr->next; } else { set->head = curr->next; } optik_unlock(&set->lock); #if GC == 1 ssmem_free(alloc, (void*) curr); #endif return result; }
sval_t optik_delete(intset_l_t *set, skey_t key) { restart: PARSE_TRY(); volatile node_l_t *pred = NULL, *curr; sval_t result = 0; COMPILER_NO_REORDER(optik_t pred_ver = set->lock); curr = set->head; while (curr != NULL && curr->key < key) { pred = curr; curr = curr->next; } UPDATE_TRY(); if (curr == NULL || curr->key != key) { return false; } if ((!optik_trylock_version(&set->lock, pred_ver))) { goto restart; } result = curr->val; if (pred != NULL) { pred->next = curr->next; } else { set->head = curr->next; } optik_unlock(&set->lock); #if GC == 1 ssmem_free(alloc, (void*) curr); #endif return result; }
/* * Logically remove an element by setting a mark bit to 1 * before removing it physically. */ sval_t parse_delete(intset_l_t *set, skey_t key) { node_l_t *pred, *curr; sval_t result = 0; int done = 0; do { PARSE_TRY(); pred = set->head; curr = pred->next; while (likely(curr->key < key)) { pred = curr; curr = curr->next; } UPDATE_TRY(); GL_LOCK(set->lock); /* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */ LOCK(ND_GET_LOCK(pred)); LOCK(ND_GET_LOCK(curr)); if (parse_validate(pred, curr)) { if (key == curr->key) { result = curr->val; node_l_t* c_nxt = curr->next; curr->marked = 1; pred->next = c_nxt; #if GC == 1 ssmem_free(alloc, (void*) curr); #endif } done = 1; } GL_UNLOCK(set->lock); UNLOCK(ND_GET_LOCK(curr)); UNLOCK(ND_GET_LOCK(pred)); } while (!done); return result; }
sval_t chm_rem(chm_t* set, skey_t key) { chm_node_t** bucket = &set->table[key & set->hash]; ptlock_t* seg_lock = &set->locks[key & set->hash_seg]; LOCK_A(seg_lock); chm_node_t* curr = *bucket; chm_node_t* pred = NULL; while (curr != NULL) { if (curr->key == key) { /* do the remove */ if (pred != NULL) { pred->next = curr->next; } else { *bucket = curr->next; } #if GC == 1 ssmem_free(alloc, (void*) curr); #endif UNLOCK_A(seg_lock); return curr->val; } pred = curr; curr = curr->next; } UNLOCK_A(seg_lock); return 0; }
sval_t optimistic_delete(sl_intset_t *set, skey_t key) { PARSE_TRY(); UPDATE_TRY(); PARSE_START_TS(2); sl_node_t* update[HERLIHY_MAX_MAX_LEVEL]; sl_node_t* succ = NULL; sl_node_t* pred = set->head; int lvl; for (lvl = levelmax - 1; lvl >= 0; lvl--) { succ = pred->next[lvl]; while (succ->key < key) { pred = succ; succ = succ->next[lvl]; } update[lvl] = pred; } PARSE_END_TS(2, lat_parsing_rem++); GL_LOCK(set->lock); succ = pred; int is_garbage; do { succ = succ->next[0]; if (succ->key > key) { GL_UNLOCK(set->lock); return false; } LOCK(ND_GET_LOCK(succ)); is_garbage = (succ->key > succ->next[0]->key); if (is_garbage || succ->key != key) { UNLOCK(ND_GET_LOCK(succ)); } else { break; } } while(true); for (lvl = succ->toplevel - 1; lvl >= 0; lvl--) { pred = get_lock(update[lvl], key, lvl); pred->next[lvl] = succ->next[lvl]; succ->next[lvl] = pred; /* pointer reversal! :-) */ UNLOCK(ND_GET_LOCK(pred)); } UNLOCK(ND_GET_LOCK(succ)); GL_UNLOCK(set->lock); #if GC == 1 ssmem_free(alloc, (void*) succ); #endif return succ->val; }
sval_t alistarh_deleteMin(sl_intset_t *set) { skey_t key; sval_t result; sl_node_t *next, *node; sl_node_t *update[HERLIHY_MAX_MAX_LEVEL]; sl_node_t *succ, *pred; int i, level, continue_flag; retry: if (unlikely(rand_range(100) <= cleaner_percentage)) { //become cleaner result = 0; PARSE_START_TS(4); node = last_dummy_entry->next[0]; while(node->next[0]!=NULL && result==0) { if (unlikely(node->key > node->next[0]->key)) { node = node->next[0]; continue; } succ = NULL; pred = set->head; key = node->key; continue_flag = 0; for (level = levelmax - 1; level >= 0; level--) { succ = pred->next[level]; while (succ->key < key) { pred = succ; succ = succ->next[level]; } update[level] = pred; } PARSE_END_TS(3, lat_parsing_deleteMin++); GL_LOCK(set->lock); succ = pred; int is_garbage; do { succ = succ->next[0]; if (succ->key > key) { GL_UNLOCK(set->lock); continue_flag = 1; break; } LOCK(ND_GET_LOCK(succ)); is_garbage = (succ->key > succ->next[0]->key); if (is_garbage || succ->key != key) { UNLOCK(ND_GET_LOCK(succ)); } else { break; } } while(true); if (continue_flag) { node = node->next[0]; continue; } for (level = succ->toplevel - 1; level >= 0; level--) { pred = get_lock(update[level], key, level); pred->next[level] = succ->next[level]; succ->next[level] = pred; // pointer reversal! :-) UNLOCK(ND_GET_LOCK(pred)); } result = node->val; UNLOCK(ND_GET_LOCK(succ)); GL_UNLOCK(set->lock); #if GC == 1 ssmem_free(alloc, (void*) succ); #endif } PARSE_END_TS(4, lat_parsing_cleaner++); return result; } else //spray & mark as deleted { UPDATE_TRY(); PARSE_START_TS(3); result = 0; node = set->head; next = NULL; for(level = starting_height; level>=0; level-=ALISTARH_LEVELS_TO_DESCEND) { i = (int)rand_range(max_jump_length); for (; i>0; i--) { next = node->next[level]; if (next==NULL || next->next[0]==NULL) break; node = next; } } if (unlikely(node == set->head)) goto retry; if (unlikely(node->val == KEY_MIN+1)) goto retry; if (unlikely(node->key > node->next[0]->key)) goto retry; succ = NULL; pred = set->head; key = node->key; for (level = levelmax - 1; level >= 0; level--) { succ = pred->next[level]; while (succ->key < key) { pred = succ; succ = succ->next[level]; } update[level] = pred; } PARSE_END_TS(3, lat_parsing_deleteMin++); GL_LOCK(set->lock); succ = pred; int is_garbage; do { succ = succ->next[0]; if (succ->key > key) { GL_UNLOCK(set->lock); goto retry; } LOCK(ND_GET_LOCK(succ)); is_garbage = (succ->key > succ->next[0]->key); if (is_garbage || succ->key != key) { UNLOCK(ND_GET_LOCK(succ)); } else { break; } } while(true); for (level = succ->toplevel - 1; level >= 0; level--) { pred = get_lock(update[level], key, level); pred->next[level] = succ->next[level]; succ->next[level] = pred; // pointer reversal! :-) UNLOCK(ND_GET_LOCK(pred)); } result = node->val; UNLOCK(ND_GET_LOCK(succ)); GL_UNLOCK(set->lock); #if GC == 1 ssmem_free(alloc, (void*) succ); #endif return result; } }
void* test(void* thread) { size_t num_retry_cas1 = 0, num_retry_cas2 = 0, num_retry_cas3 = 0 , num_retry_cas4 = 0, num_retry_cas5 = 0; thread_data_t* td = (thread_data_t*) thread; uint8_t ID = td->id; phys_id = the_cores[ID % (NUMBER_OF_SOCKETS * CORES_PER_SOCKET)]; set_cpu(phys_id); ssmem_allocator_t* alloc = (ssmem_allocator_t*) memalign(CACHE_LINE_SIZE, sizeof(ssmem_allocator_t)); assert(alloc != NULL); ssmem_alloc_init(alloc, SSMEM_DEFAULT_MEM_SIZE, ID); ssmem_gc_thread_init(alloc, ID); PF_INIT(3, SSPFD_NUM_ENTRIES, ID); #if defined(COMPUTE_LATENCY) volatile ticks my_putting_succ = 0; volatile ticks my_putting_fail = 0; volatile ticks my_getting_succ = 0; volatile ticks my_getting_fail = 0; volatile ticks my_removing_succ = 0; volatile ticks my_removing_fail = 0; #endif uint64_t my_putting_count = 0; uint64_t my_getting_count = 0; uint64_t my_removing_count = 0; uint64_t my_putting_count_succ = 0; uint64_t my_getting_count_succ = 0; uint64_t my_removing_count_succ = 0; #if defined(COMPUTE_LATENCY) && PFD_TYPE == 0 volatile ticks start_acq, end_acq; volatile ticks correction = getticks_correction_calc(); #endif seeds = seed_rand(); MEM_BARRIER; barrier_cross(&barrier); barrier_cross(&barrier_global); size_t obj_size_bytes = obj_size * sizeof(size_t); volatile size_t* dat = (size_t*) malloc(obj_size_bytes); assert(dat != NULL); size_t* obj = NULL; while (stop == 0) { size_t rand = (my_random(&(seeds[0]), &(seeds[1]), &(seeds[2]))); size_t k = (rand & 1) + 2; rand &= 1023; /* search baby! */ int i; for (i = 0; i < KEY_BUCKT; i++) { volatile uintptr_t v = val[i]; if (snap->map[i] == MAP_VALID && key[i] == k) { if (val[i] == v) { if (GET_VAL(v) != k) { printf("[%02d] :get: key != val for %zu\n", ID, k); } break; } } } if (rand > 513) { my_putting_count++; if (obj != NULL) { ssmem_free(alloc, (void*) obj); } obj = ssmem_alloc(alloc, 8); *obj = k; int empty_index = -2; clht_snapshot_t s; retry: s.snapshot = snap->snapshot; int i; for (i = 0; i < KEY_BUCKT; i++) { volatile uintptr_t v = val[i]; if (snap->map[i] == MAP_VALID && key[i] == k) { if (val[i] == v) { if (empty_index > 0) { snap->map[empty_index] = MAP_INVLD; } goto end; } } } clht_snapshot_all_t s1; if (empty_index < 0) { empty_index = snap_get_empty_index(s.snapshot); if (empty_index < 0) { num_retry_cas1++; goto end; } s1 = snap_set_map(s.snapshot, empty_index, MAP_INSRT); if (CAS_U64(&snap->snapshot, s.snapshot, s1) != s.snapshot) { empty_index = -2; num_retry_cas2++; goto retry; } val[empty_index] = (uintptr_t) obj; key[empty_index] = k; } else { s1 = snap_set_map(s.snapshot, empty_index, MAP_INSRT); } clht_snapshot_all_t s2 = snap_set_map_and_inc_version(s1, empty_index, MAP_VALID); if (CAS_U64(&snap->snapshot, s1, s2) != s1) { num_retry_cas3++; /* key[empty_index] = 0; */ /* val[empty_index] = 0; */ goto retry; } obj = NULL; my_putting_count_succ++; end: ; } else { my_removing_count++; clht_snapshot_t s; retry_rem: s.snapshot = snap->snapshot; volatile uintptr_t v; int i, removed = 0; for (i = 0; i < KEY_BUCKT && !removed; i++) { if (key[i] == k && s.map[i] == MAP_VALID) { v = val[i]; clht_snapshot_all_t s1 = snap_set_map(s.snapshot, i, MAP_INVLD); if (CAS_U64(&snap->snapshot, s.snapshot, s1) == s.snapshot) { /* snap->map[i] = MAP_INVLD; */ removed = 1; } else { num_retry_cas4++; goto retry_rem; } } } if (removed) { ssmem_free(alloc, (void*) v); my_removing_count_succ++; } } } free((void*) dat); #if defined(DEBUG) if (put_num_restarts | put_num_failed_expand | put_num_failed_on_new) { /* printf("put_num_restarts = %3u / put_num_failed_expand = %3u / put_num_failed_on_new = %3u \n", */ /* put_num_restarts, put_num_failed_expand, put_num_failed_on_new); */ } #endif if (ID < 2) { printf("#retry-stats-thread-%d: #cas1: %-8zu / #cas2: %-8zu /" "#cas3: %-8zu / #cas4: %-8zu / #cas5: %-8zu\n", ID, num_retry_cas1, num_retry_cas2, num_retry_cas3, num_retry_cas4, num_retry_cas5); } /* printf("gets: %-10llu / succ: %llu\n", num_get, num_get_succ); */ /* printf("rems: %-10llu / succ: %llu\n", num_rem, num_rem_succ); */ barrier_cross(&barrier); #if defined(COMPUTE_LATENCY) putting_succ[ID] += my_putting_succ; putting_fail[ID] += my_putting_fail; getting_succ[ID] += my_getting_succ; getting_fail[ID] += my_getting_fail; removing_succ[ID] += my_removing_succ; removing_fail[ID] += my_removing_fail; #endif putting_count[ID] += my_putting_count; getting_count[ID] += my_getting_count; removing_count[ID]+= my_removing_count; putting_count_succ[ID] += my_putting_count_succ; getting_count_succ[ID] += my_getting_count_succ; removing_count_succ[ID]+= my_removing_count_succ; #if (PFD_TYPE == 1) && defined(COMPUTE_LATENCY) if (ID == 0) { printf("get ----------------------------------------------------\n"); SSPFDPN(0, SSPFD_NUM_ENTRIES, print_vals_num); printf("put ----------------------------------------------------\n"); SSPFDPN(1, SSPFD_NUM_ENTRIES, print_vals_num); printf("rem ----------------------------------------------------\n"); SSPFDPN(2, SSPFD_NUM_ENTRIES, print_vals_num); } #endif /* SSPFDTERM(); */ pthread_exit(NULL); }
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 } } } }
/* * Function optimistic_delete is similar to the method remove of the paper. * Here we avoid the fast search parameter as the comparison is faster in C * than calling the Java compareTo method of the Comparable interface * (cf. p132 of SIROCCO'07 proceedings). */ sval_t optimistic_delete(sl_intset_t *set, skey_t key) { sl_node_t *succs[HERLIHY_MAX_MAX_LEVEL], *preds[HERLIHY_MAX_MAX_LEVEL]; sl_node_t *node_todel, *prev_pred; sl_node_t *pred, *succ; int is_marked, toplevel, highest_locked, i, valid, found; unsigned int backoff; node_todel = NULL; is_marked = 0; toplevel = -1; backoff = 1; PARSE_START_TS(2); while(1) { UPDATE_TRY(); found = optimistic_search(set, key, preds, succs, 1); PARSE_END_TS(2, lat_parsing_rem); /* If not marked and ok to delete, then mark it */ if (is_marked || (found != -1 && ok_to_delete(succs[found], found))) { GL_LOCK(set->lock); /* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */ if (!is_marked) { node_todel = succs[found]; LOCK(ND_GET_LOCK(node_todel)); toplevel = node_todel->toplevel; /* Unless it has been marked meanwhile */ if (node_todel->marked) { GL_UNLOCK(set->lock); UNLOCK(ND_GET_LOCK(node_todel)); PARSE_END_INC(lat_parsing_rem); return 0; } node_todel->marked = 1; is_marked = 1; } /* Physical deletion */ highest_locked = -1; prev_pred = NULL; valid = 1; for (i = 0; valid && (i < toplevel); i++) { pred = preds[i]; succ = succs[i]; if (pred != prev_pred) { LOCK(ND_GET_LOCK(pred)); highest_locked = i; prev_pred = pred; } valid = (!pred->marked && ((volatile sl_node_t*) pred->next[i] == (volatile sl_node_t*) succ)); } if (!valid) { unlock_levels(set, preds, highest_locked); if (backoff > 5000) { nop_rep(backoff & MAX_BACKOFF); } backoff <<= 1; continue; } for (i = (toplevel-1); i >= 0; i--) { preds[i]->next[i] = node_todel->next[i]; } sval_t val = node_todel->val; #if GC == 1 ssmem_free(alloc, (void*) node_todel); #endif UNLOCK(ND_GET_LOCK(node_todel)); unlock_levels(set, preds, highest_locked); PARSE_END_INC(lat_parsing_rem); return val; } else { PARSE_END_INC(lat_parsing_rem); return 0; } } }