/* * [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); } } }
inline int mark_node_ptrs(sl_node_t *n) { sl_node_t *n_next; uint32_t status; //uint32_t attempts = 0; uint32_t i = n->toplevel - 1; //retry: status = _xbegin(); if(status == _XBEGIN_STARTED) { while ( i > 0 ) { if(!is_marked((uint32_t)n->nexts[i])) n->nexts[i] = (sl_node_t*)set_mark((uint32_t)n->nexts[i]); i--; } if (is_marked((uint32_t)n->nexts[0])) { _xend(); return 0; }else { n->nexts[0] = (sl_node_t*)set_mark((uint32_t)n->nexts[0]); _xend(); return 1; } }/*else{ if (++attempts < MAX_ATTEMPT_NUM) { goto retry; } }*/ for (int i=n->toplevel-1; i>0; i--) { do { n_next = n->nexts[i]; if (is_marked((uint32_t)n_next)) break; if (ATOMIC_CAS_MB(&n->nexts[i], n_next, (sl_node_t*)set_mark((uint32_t)n_next))) break; } while (true); } do { n_next = n->nexts[0]; if (is_marked((uint32_t)n_next)) return 0; if (ATOMIC_CAS_MB(&n->nexts[0], n_next, (sl_node_t*)set_mark((uint32_t)n_next))) return 1; } while (true); }
// Fraser's SkipList Algorithm inline void fraser_search(sl_intset_t *set, uint32_t val, sl_node_t **left_list, sl_node_t **right_list) { int i; sl_node_t *left, *left_next, *right, *right_next; retry: left = set->head; for (i = LEVELMAX - 1; i >= 0; i--) { left_next = left->nexts[i]; if (is_marked((uint32_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 */ while(1) { right_next = right->nexts[i]; if (!is_marked((uint32_t)right_next)) break; right = (sl_node_t*)unset_mark((uint32_t)right_next); } if (right->val >= val) break; left = right; left_next = right_next; } /* Ensure left and right nodes are adjacent */ if ((left_next != right) && (!ATOMIC_CAS_MB(&left->nexts[i], left_next, right))) goto retry; if (left_list != NULL) left_list[i] = left; if (right_list != NULL) right_list[i] = right; } }
/* * harris_find deletes a node with the given value val (if the value is present) * or does nothing (if the value is already present). * The deletion is logical and consists of setting the node mark bit to 1. */ int harris_delete(intset_t *set, val_t val) { node_t *right_node, *right_node_next, *left_node; left_node = set->head; do { right_node = harris_search(set, val, &left_node); if (right_node->val != val) return 0; right_node_next = right_node->next; if (!is_marked_ref((long) right_node_next)) if (ATOMIC_CAS_MB(&right_node->next, right_node_next, get_marked_ref((long) right_node_next))) break; } while(1); if (!ATOMIC_CAS_MB(&left_node->next, right_node, right_node_next)) right_node = harris_search(set, right_node->val, &left_node); return 1; }
void mark_node_ptrs(sl_node_t *n) { int i; 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)) break; } while (!ATOMIC_CAS_MB(&n->next[i], n_next, set_mark((uintptr_t)n_next))); } }
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); }
/* * harris_find inserts a new node with the given value val in the list * (if the value was absent) or does nothing (if the value is already present). */ int harris_insert(intset_t *set, val_t val) { node_t *newnode, *right_node, *left_node; left_node = set->head; do { right_node = harris_search(set, val, &left_node); if (right_node->val == val) return 0; newnode = new_node(val, right_node, 0); /* mem-bar between node creation and insertion */ AO_nop_full(); if (ATOMIC_CAS_MB(&left_node->next, right_node, newnode)) return 1; } while(1); }
void fraser_search(sl_intset_t *set, val_t val, sl_node_t **left_list, sl_node_t **right_list) { int i; sl_node_t *left, *left_next, *right, *right_next; #ifdef DEBUG printf("++> fraser_search\n"); IO_FLUSH; #endif retry: 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 */ while(1) { right_next = right->next[i]; if (!is_marked((uintptr_t)right_next)) break; right = (sl_node_t*)unset_mark((uintptr_t)right_next); } if (right->val >= val) 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; } #ifdef DEBUG printf("++> fraser_search ends\n"); IO_FLUSH; #endif }
/* * harris_search looks for value val, it * - returns right_node owning val (if present) or its immediately higher * value present in the list (otherwise) and * - sets the left_node to the node owning the value immediately lower than val. * Encountered nodes that are marked as logically deleted are physically removed * from the list, yet not garbage collected. */ node_t *harris_search(intset_t *set, val_t val, node_t **left_node) { node_t *left_node_next, *right_node; left_node_next = set->head; search_again: do { node_t *t = set->head; node_t *t_next = set->head->next; /* Find left_node and right_node */ do { if (!is_marked_ref((long) t_next)) { (*left_node) = t; left_node_next = t_next; } t = (node_t *) get_unmarked_ref((long) t_next); if (!t->next) break; t_next = t->next; } while (is_marked_ref((long) t_next) || (t->val < val)); right_node = t; /* Check that nodes are adjacent */ if (left_node_next == right_node) { if (right_node->next && is_marked_ref((long) right_node->next)) goto search_again; else return right_node; } /* Remove one or more marked nodes */ if (ATOMIC_CAS_MB(&(*left_node)->next, left_node_next, right_node)) { if (right_node->next && is_marked_ref((long) right_node->next)) goto search_again; else return right_node; } } while (1); }
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 */ }
void* sssp(void *data) { thread_data_t *d = (thread_data_t *)data; /* Create transaction */ set_cpu(the_cores[d->id]); /* Wait on barrier */ ssalloc_init(); PF_CORRECTION; seeds = seed_rand(); #ifdef PIN int id = d->id; // int cpu = 40*(id/40) + 4*(id%10) + (id%40)/10; int cpu = 4*(id%20) + id/20; // printf("Pinning %d to %d\n",id,cpu); pin(pthread_self(), cpu); // pin(pthread_self(), id); #endif #ifdef PAPI if (PAPI_OK != PAPI_start_counters(g_events, G_EVENT_COUNT)) { printf("Problem starting counters 1."); } #endif barrier_cross(d->barrier); // Begin SSSP int fail = 0; // int radius = 0; while (1) { val_t node; slkey_t dist_node; // print_skiplist(d->set); while (1) { if (d->sl) { if (spray_delete_min_key(d->set, &dist_node, &node, d)) break; // keep trying until get a node } else if (d->pq) { if (lotan_shavit_delete_min_key(d->set, &dist_node, &node, d)) break; } else if (d->lin) { node = (val_t) deletemin_key(d->linden_set, &dist_node, d); break; } else { printf("error: no queue selected\n"); exit(1); // TODO: grace } if (dist_node == -1) { // flag that list is empty break; } dist_node = 0; } if (dist_node == -1) { // list is empty; TODO make sure threads don't quit early fail++; if (fail > 20*d->nb_threads) { // TODO: really need a better break condition... break; } continue; } fail = 0; if (dist_node != nodes[node].dist) continue; // dead node nodes[node].times_processed++; int i; for (i = 0;i < nodes[node].deg;i++) { int v = nodes[node].adj[i]; int w = nodes[node].weights[i]; slkey_t dist_v = nodes[v].dist; // printf("v=%d dist_v=%d\n", v, dist_v); if (dist_v == -1 || dist_node + w < dist_v) { // found better path to v // printf("attempting cas...\n"); // printf("nodes[v].dist=%d dist_v=%d dist_node=%d\n", nodes[v].dist, dist_v, dist_node); int res = ATOMIC_CAS_MB(&nodes[v].dist, dist_v, dist_node+w); // printf("%d nodes[%d].dist=%d\n", res, v, nodes[v].dist); if (res) { if (d->pq || d->sl) { sl_add_val(d->set, dist_node+w, v, TRANSACTIONAL); // add to queue only if CAS is successful } else if (d->lin) { insert(d->linden_set, dist_node+w, v); } d->nb_add++; // if (dist_node+1 > radius) { // radius = dist_node+1; // printf("radius %d\n", radius); // } } } } } // End SSSP #ifdef PAPI if (PAPI_OK != PAPI_read_counters(g_values[d->id], G_EVENT_COUNT)) { printf("Problem reading counters 2."); } #endif PF_PRINT; return NULL; }