long set_add(long val) { int res = 0; int ran_level = get_rand_level(); __transaction_atomic { int i, l; node_t *node, *next; node_t *preds[MAXLEVEL]; long v; v = VAL_MIN; node = set->head; for (i = node->toplevel-1; i >= 0; i--) { next = node->next[i]; while ((v = next->val) < val) { node = next; next = node->next[i]; } preds[i] = node; } if ((res = (v != val)) == 1) { l = ran_level; node = new_simple_node(val, l); for (i = 0; i < l; i++) { node->next[i] = preds[i]->next[i]; preds[i]->next[i] = node; } } } return res; }
int set_seq_add(long val) { int i, l, result; node_t *node, *next; node_t *preds[MAXLEVEL], *succs[MAXLEVEL]; node = set->head; for (i = node->toplevel-1; i >= 0; i--) { next = node->next[i]; while (next->val < val) { node = next; next = node->next[i]; } preds[i] = node; succs[i] = node->next[i]; } node = node->next[0]; if ((result = (node->val != val)) == 1) { l = get_rand_level(); node = seq_new_simple_node(val, l); for (i = 0; i < l; i++) { node->next[i] = succs[i]; preds[i]->next[i] = node; } } return result; }
/* * [lyj] Disable the interpretation of "deleted" field. */ void fraser_insert(sl_intset_t *set, uint32_t v, bool lin) { sl_node_t *NEW, *new_next, *pred, *succ, *succs[LEVELMAX], *preds[LEVELMAX]; uint32_t i; uint32_t status; // uint32_t attempts = 0; NEW = sl_new_simple_node(v, get_rand_level(), lin); retry: fraser_search(set, v, preds, succs); for (i = 0; i < NEW->toplevel; i++) NEW->nexts[i] = succs[i]; /* Node is visible once inserted at lowest level */ if (!ATOMIC_CAS_MB(&preds[0]->nexts[0], succs[0], NEW)) goto retry; //retry_HTM: status = _xbegin(); if(status == _XBEGIN_STARTED) { for (i = 1; i < NEW->toplevel; i++) { if(preds[i]->nexts[i] == succs[i]) preds[i]->nexts[i] = NEW; else _xabort(66); } _xend(); return; }/*else { if ((status & _XABORT_EXPLICIT) && _XABORT_CODE(status) == 66) { } else if (++attempts < MAX_ATTEMPT_NUM) { goto retry_HTM; } }*/ for (i = 1; i < NEW->toplevel; i++) { while (1) { pred = preds[i]; succ = succs[i]; /* Update the forward pointer if it is stale */ new_next = NEW->nexts[i]; if ((new_next != succ) && (!ATOMIC_CAS_MB(&NEW->nexts[i], unset_mark((uint32_t)new_next), succ))) break; /* Give up if pointer is marked */ /* We retry the search if the CAS fails */ if (ATOMIC_CAS_MB(&pred->nexts[i], succ, NEW)) break; fraser_search(set, v, preds, succs); } } }
/* * Function optimistic_insert stands for the add method of the original paper. * Unlocking and freeing the memory are done at the right places. */ int optimistic_insert(sl_intset_t *set, skey_t key, sval_t val) { sl_node_t *succs[HERLIHY_MAX_MAX_LEVEL], *preds[HERLIHY_MAX_MAX_LEVEL]; sl_node_t *node_found, *prev_pred, *new_node; sl_node_t *pred, *succ; int toplevel, highest_locked, i, valid, found; unsigned int backoff; toplevel = get_rand_level(); backoff = 1; PARSE_START_TS(1); while (1) { UPDATE_TRY(); found = optimistic_search(set, key, preds, succs, 1); PARSE_END_TS(1, lat_parsing_put); if (found != -1) { node_found = succs[found]; if (!node_found->marked) { while (!node_found->fullylinked) { PAUSE; } PARSE_END_INC(lat_parsing_put); return 0; } continue; } GL_LOCK(set->lock); /* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */ 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 && !succ->marked && ((volatile sl_node_t*) pred->next[i] == (volatile sl_node_t*) succ)); } if (!valid) { /* Unlock the predecessors before leaving */ unlock_levels(set, preds, highest_locked); /* unlocks the global-lock in the GL case */ if (backoff > 5000) { nop_rep(backoff & MAX_BACKOFF); } backoff <<= 1; continue; } new_node = sl_new_simple_node(key, val, toplevel, 0); for (i = 0; i < toplevel; i++) { new_node->next[i] = succs[i]; } #if defined(__tile__) MEM_BARRIER; #endif for (i = 0; i < toplevel; i++) { preds[i]->next[i] = new_node; } new_node->fullylinked = 1; unlock_levels(set, preds, highest_locked); PARSE_END_INC(lat_parsing_put); return 1; } }
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; }