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); }
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; }
sval_t prioritySL_deleteMin(sl_intset_t *set) { sval_t result = 0; sl_node_t *node; PARSE_START_TS(4); node = GET_UNMARKED(set->head->next[0]); while(node->next[0]!=NULL) { if (!IS_MARKED(node->next[node->toplevel-1])) { int my_delete = mark_node_ptrs(node); if (my_delete) { result = node->val; fraser_search(set, node->key, NULL, NULL); break; } } node = GET_UNMARKED(node->next[0]); } PARSE_END_TS(4, lat_parsing_cleaner++); return result; }
inline int mark_node_ptrs(sl_node_t *n) { int i, cas = 0; sl_node_t* n_next; for (i = n->toplevel - 1; i >= 0; i--) { do { n_next = n->next[i]; if (is_marked((uintptr_t)n_next)) { cas = 0; break; } cas = ATOMIC_CAS_MB(&n->next[i], GET_UNMARKED(n_next), set_mark((uintptr_t)n_next)); } while (!cas); } return (cas); /* if I was the one that marked lvl 0 */ }
/** * Search for a key's position in the ordered list. Upon return, * *left_node points to the left node (and it has a reference) and the * return value points to a node that is referenced too. */ static struct lf_ordlist_node *search(struct lf_ordlist *lst, void *key, struct lf_ordlist_node **left_node) { struct lf_ordlist_node *left_node_next, *right_node; struct lf_ordlist_node *t, *t_next; search_again: for ( ; ; ) { *left_node = left_node_next = NULL; t = mem_safe_read(lst->fl, &lst->head); t_next = mem_safe_read(lst->fl, &NEXT(lst->head)); /* 1: Find left_node and right_node * * Entering this loop: t and t_next are referenced. * * Leaving this loop: t is referenced, and if t_next * is not marked then *left_node * and left_node_next are set and * have their own references. If t * != lst->tail, then t_next is * also referenced. */ do { if (!IS_MARKED(t_next)) { /* these refs may have been copied * before, but we had to loop again */ if (*left_node) { mem_release(lst->fl, *left_node); *left_node = NULL; } if (left_node_next) { mem_release(lst->fl, left_node_next); left_node_next = NULL; } /* copy both t and t_next's refs */ mem_incr_ref(t); (*left_node) = t; mem_incr_ref(t_next); left_node_next = t_next; } mem_release(lst->fl, t); t = GET_UNMARKED(t_next); /* take t_next's ref */ if (t == lst->tail) break; t_next = mem_safe_read(lst->fl, &NEXT(t)); } while (IS_MARKED(t_next) || lst->cmp(t->value, key) < 0); if (t != lst->tail) mem_release(lst->fl, t_next); /* done with t_next */ right_node = t; /* takes t's reference */ /* * At this point, right_node, *left_node and * left_node_next all have references. */ /* 2: Check nodes are adjacent */ if (left_node_next == right_node) { mem_release(lst->fl, left_node_next); if (right_node != lst->tail && IS_MARKED(NEXT(right_node))) { mem_release(lst->fl, right_node); mem_release(lst->fl, *left_node); goto search_again; } else { return right_node; } } /* 3: Remove one or more marked nodes * * Here, left_node_next, right_node and *left_node are * referenced. */ /* in case CAS succeeds. */ mem_incr_ref(right_node); assert(*left_node != lst->tail); if (compare_and_swap(&NEXT(*left_node), (intptr_t) left_node_next, (intptr_t) right_node)) { /* one for NEXT(*left_node), one for * 'left_node_next' */ mem_release(lst->fl, left_node_next); mem_release(lst->fl, left_node_next); if ((right_node != lst->tail) && IS_MARKED(NEXT(right_node))) { mem_release(lst->fl, right_node); mem_release(lst->fl, *left_node); goto search_again; } else { return right_node; } } /* one for the CAS prep. ref and one for * 'right_node' */ mem_release(lst->fl, right_node); mem_release(lst->fl, right_node); mem_release(lst->fl, *left_node); mem_release(lst->fl, left_node_next); } /* for( ; ; ) */ /* should not reach here */ assert(0); }