int ticketepfl_mutex_lock(ticketepfl_mutex_t *impl, ticketepfl_context_t *UNUSED(me)) { // Acquire the local lock uint32_t my_ticket = __sync_add_and_fetch(&impl->u.s.request, 1); uint32_t wait = TICKET_BASE_WAIT; uint32_t distance_prev = 1; while (1) { PREFETCHW(&impl->u.u); uint32_t cur = impl->u.s.grant; if (cur == my_ticket) { break; } uint32_t distance = sub_abs(cur, my_ticket); if (distance > 1) { if (distance != distance_prev) { distance_prev = distance; wait = TICKET_BASE_WAIT; } nop_rep(distance * wait); /* wait = (wait + TICKET_BASE_WAIT) & TICKET_MAX_WAIT; */ } else { nop_rep(TICKET_WAIT_NEXT); } if (distance > 20) { sched_yield(); /* pthread_yield(); */ } } #if COND_VAR int ret = REAL(pthread_mutex_lock)(&impl->posix_lock); assert(ret == 0); #endif return 0; }
/* * 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; } } }
/* * 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; } }