sval_t optimistic_find(sl_intset_t *set, skey_t key) { PARSE_TRY(); PARSE_START_TS(0); sval_t val = 0; 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]; } if (succ->key == key) /* at any search level */ { val = succ->val; break; } } PARSE_END_TS(0, lat_parsing_get++); return val; }
inline sl_node_t* optimistic_left_search(sl_intset_t *set, skey_t key) { PARSE_TRY(); int i; sl_node_t *pred, *curr, *nd = NULL; pred = set->head; for (i = (pred->toplevel - 1); i >= 0; i--) { curr = pred->next[i]; while (key > curr->key) { pred = curr; curr = pred->next[i]; } if (key == curr->key) { nd = curr; break; } } return nd; }
int fraser_search_no_cleanup_succs(sl_intset_t *set, skey_t key, sl_node_t **right_list) { PARSE_TRY(); int i; sl_node_t *left, *left_next, *right = NULL; left = set->head; for (i = levelmax - 1; i >= 0; i--) { left_next = GET_UNMARKED(left->next[i]); right = left_next; while (1) { if (likely(!IS_MARKED(right->next[i]))) { if (right->key >= key) { break; } left = right; } right = GET_UNMARKED(right->next[i]); } right_list[i] = right; } return (right->key == key); }
sval_t lockc_find(intset_l_t *set, skey_t key) { PARSE_TRY(); node_l_t *curr, *next; sval_t res = 0; GL_LOCK(set->lock); /* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */ LOCK(ND_GET_LOCK(set->head)); curr = set->head; LOCK(ND_GET_LOCK(curr->next)); next = curr->next; while (next->key < key) { UNLOCK(ND_GET_LOCK(curr)); curr = next; LOCK(ND_GET_LOCK(next->next)); next = curr->next; } if (key == next->key) { res = next->val; } GL_UNLOCK(set->lock); UNLOCK(ND_GET_LOCK(curr)); UNLOCK(ND_GET_LOCK(next)); return res; }
/* * Function optimistic_search corresponds to the findNode method of the * original paper. A fast parameter has been added to speed-up the search * so that the function quits as soon as the searched element is found. */ inline int optimistic_search(sl_intset_t *set, skey_t key, sl_node_t **preds, sl_node_t **succs, int fast) { PARSE_TRY(); int found, i; sl_node_t *pred, *curr; found = -1; pred = set->head; for (i = (pred->toplevel - 1); i >= 0; i--) { curr = pred->next[i]; while (key > curr->key) { pred = curr; curr = pred->next[i]; } if (preds != NULL) preds[i] = pred; succs[i] = curr; if (found == -1 && key == curr->key) { found = i; } } return found; }
static sl_node_t* fraser_left_search(sl_intset_t *set, skey_t key) { PARSE_TRY(); sl_node_t* left = NULL; sl_node_t* left_prev; left_prev = set->head; int lvl; for (lvl = levelmax - 1; lvl >= 0; lvl--) { left = GET_UNMARKED(left_prev->next[lvl]); while(left->key < key || IS_MARKED(left->next[lvl])) { if (!IS_MARKED(left->next[lvl])) { left_prev = left; } left = GET_UNMARKED(left->next[lvl]); } if ((left->key == key)) { break; } } return left; }
/* * 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; }
/* * 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; }
int fraser_search(sl_intset_t *set, skey_t key, sl_node_t **left_list, sl_node_t **right_list) { int i; sl_node_t *left, *left_next, *right = NULL, *right_next; retry: PARSE_TRY(); left = set->head; for (i = levelmax - 1; i >= 0; i--) { left_next = left->next[i]; if ((is_marked((uintptr_t)left_next))) { goto retry; } /* Find unmarked node pair at this level */ for (right = left_next; ; right = right_next) { /* Skip a sequence of marked nodes */ right_next = right->next[i]; while ((is_marked((uintptr_t)right_next))) { right = (sl_node_t*)unset_mark((uintptr_t)right_next); right_next = right->next[i]; } if (right->key >= key) { break; } left = right; left_next = right_next; } /* Ensure left and right nodes are adjacent */ if ((left_next != right) && (!ATOMIC_CAS_MB(&left->next[i], left_next, right))) { goto retry; } if (left_list != NULL) { left_list[i] = left; } if (right_list != NULL) { right_list[i] = right; } } return (right->key == key); }
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; }
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; }
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; }
sval_t parse_find(intset_l_t *set, skey_t key) { PARSE_TRY(); node_l_t* curr = set->head; while (curr->key < key) { curr = curr->next; } sval_t res = 0; if ((curr->key == key) && !curr->marked) { res = curr->val; } return res; }
int parse_insert(intset_l_t *set, skey_t key, sval_t val) { node_l_t *curr, *pred, *newnode; int result = -1; 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)) { result = (curr->key != key); if (result) { newnode = new_node_l(key, val, curr, 0); #ifdef __tile__ MEM_BARRIER; #endif pred->next = newnode; } } GL_UNLOCK(set->lock); UNLOCK(ND_GET_LOCK(curr)); UNLOCK(ND_GET_LOCK(pred)); } while (result < 0); return result; }
seek_record_t * bst_seek(skey_t key, node_t* node_r){ PARSE_TRY(); volatile seek_record_t seek_record_l; node_t* node_s = ADDRESS(node_r->left); seek_record_l.ancestor = node_r; seek_record_l.successor = node_s; seek_record_l.parent = node_s; seek_record_l.leaf = ADDRESS(node_s->left); node_t* parent_field = (node_t*) seek_record_l.parent->left; node_t* current_field = (node_t*) seek_record_l.leaf->left; node_t* current = ADDRESS(current_field); while (current != NULL) { if (!GETTAG(parent_field)) { seek_record_l.ancestor = seek_record_l.parent; seek_record_l.successor = seek_record_l.leaf; } seek_record_l.parent = seek_record_l.leaf; seek_record_l.leaf = current; parent_field = current_field; if (key < current->key) { current_field= (node_t*) current->left; } else { current_field= (node_t*) current->right; } current=ADDRESS(current_field); } seek_record->ancestor=seek_record_l.ancestor; seek_record->successor=seek_record_l.successor; seek_record->parent=seek_record_l.parent; seek_record->leaf=seek_record_l.leaf; return seek_record; }
int lockc_insert(intset_l_t *set, skey_t key, sval_t val) { PARSE_TRY(); UPDATE_TRY(); node_l_t *curr, *next, *newnode; int found; GL_LOCK(set->lock); /* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */ LOCK(ND_GET_LOCK(set->head)); curr = set->head; LOCK(ND_GET_LOCK(curr->next)); next = curr->next; while (next->key < key) { UNLOCK(ND_GET_LOCK(curr)); curr = next; LOCK(ND_GET_LOCK(next->next)); next = curr->next; } found = (key == next->key); if (!found) { newnode = new_node_l(key, val, next, 1); #ifdef __tile__ MEM_BARRIER; #endif curr->next = newnode; } GL_UNLOCK(set->lock); UNLOCK(ND_GET_LOCK(curr)); UNLOCK(ND_GET_LOCK(next)); return !found; }
int optimistic_insert(sl_intset_t *set, skey_t key, sval_t val) { PARSE_TRY(); UPDATE_TRY(); PARSE_START_TS(1); sl_node_t* update[HERLIHY_MAX_MAX_LEVEL]; sl_node_t* succ; 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]; } if (unlikely(succ->key == key)) /* at any search level */ { return false; } update[lvl] = pred; } PARSE_END_TS(1, lat_parsing_put++); int rand_lvl = get_rand_level(); /* do the rand_lvl outside the CS */ GL_LOCK(set->lock); pred = get_lock(pred, key, 0); if (unlikely(pred->next[0]->key == key)) { UNLOCK(ND_GET_LOCK(pred)); GL_UNLOCK(set->lock); return false; } sl_node_t* n = sl_new_simple_node(key, val, rand_lvl, 0); LOCK(ND_GET_LOCK(n)); n->next[0] = pred->next[0]; /* we already hold the lock for lvl 0 */ #ifdef __tile__ MEM_BARRIER; #endif pred->next[0] = n; UNLOCK(ND_GET_LOCK(pred)); for (lvl = 1; lvl < n->toplevel; lvl++) { pred = get_lock(update[lvl], key, lvl); n->next[lvl] = pred->next[lvl]; #ifdef __tile__ MEM_BARRIER; #endif pred->next[lvl] = n; UNLOCK(ND_GET_LOCK(pred)); } UNLOCK(ND_GET_LOCK(n)); GL_UNLOCK(set->lock); return 1; }
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 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; }