void ck_barrier_centralized(struct ck_barrier_centralized *barrier, struct ck_barrier_centralized_state *state, unsigned int n_threads) { unsigned int sense, value; /* * Every execution context has a sense associated with it. * This sense is reversed when the barrier is entered. Every * thread will spin on the global sense until the last thread * reverses it. */ sense = state->sense = ~state->sense; value = ck_pr_faa_uint(&barrier->value, 1); if (value == n_threads - 1) { ck_pr_store_uint(&barrier->value, 0); ck_pr_fence_memory(); ck_pr_store_uint(&barrier->sense, sense); return; } ck_pr_fence_load(); while (sense != ck_pr_load_uint(&barrier->sense)) ck_pr_stall(); ck_pr_fence_memory(); return; }
void ck_barrier_mcs_subscribe(struct ck_barrier_mcs *barrier, struct ck_barrier_mcs_state *state) { state->sense = ~0; state->vpid = ck_pr_faa_uint(&barrier->tid, 1); return; }
void ck_barrier_dissemination_subscribe(struct ck_barrier_dissemination *barrier, struct ck_barrier_dissemination_state *state) { state->parity = 0; state->sense = ~0; state->tid = ck_pr_faa_uint(&barrier->tid, 1); return; }
static void ck_barrier_combining_aux(struct ck_barrier_combining *barrier, struct ck_barrier_combining_group *tnode, unsigned int sense) { /* * If this is the last thread in the group, it moves on to the parent group. * Otherwise, it spins on this group's sense. */ if (ck_pr_faa_uint(&tnode->count, 1) == tnode->k - 1) { /* * If we are and will be the last thread entering the barrier for the * current group then signal the parent group if one exists. */ if (tnode->parent != NULL) ck_barrier_combining_aux(barrier, tnode->parent, sense); /* * Once the thread returns from its parent(s), it reinitializes the group's * arrival count and signals other threads to continue by flipping the group * sense. Order of these operations is not important since we assume a static * number of threads are members of a barrier for the lifetime of the barrier. * Since count is explicitly reinitialized, it is guaranteed that at any point * tnode->count is equivalent to tnode->k if and only if that many threads * are at the barrier. */ ck_pr_store_uint(&tnode->count, 0); ck_pr_fence_store(); ck_pr_store_uint(&tnode->sense, ~tnode->sense); } else { ck_pr_fence_memory(); while (sense != ck_pr_load_uint(&tnode->sense)) ck_pr_stall(); } return; }
#define ITERATE 1000000 #endif static struct affinity a; static unsigned int locked; static unsigned int tid = 2; static int nthr; static ck_rwlock_t lock = CK_RWLOCK_INITIALIZER; static ck_rwlock_recursive_t r_lock = CK_RWLOCK_RECURSIVE_INITIALIZER; static void * thread_recursive(void *null CK_CC_UNUSED) { int i = ITERATE; unsigned int l; unsigned int t = ck_pr_faa_uint(&tid, 1); if (aff_iterate(&a)) { perror("ERROR: Could not affine thread"); exit(EXIT_FAILURE); } while (i--) { while (ck_rwlock_recursive_write_trylock(&r_lock, t) == false) ck_pr_stall(); ck_rwlock_recursive_write_lock(&r_lock, t); ck_rwlock_recursive_write_lock(&r_lock, t); ck_rwlock_recursive_write_lock(&r_lock, t); {
static void * test_spmc(void *c) { unsigned int observed = 0; unsigned long previous = 0; unsigned int seed; int i, k, j, tid; struct context *context = c; ck_ring_buffer_t *buffer; buffer = context->buffer; if (aff_iterate(&a)) { perror("ERROR: Could not affine thread"); exit(EXIT_FAILURE); } tid = ck_pr_faa_int(&eb, 1); ck_pr_fence_memory(); while (ck_pr_load_int(&eb) != nthr - 1); for (i = 0; i < ITERATIONS; i++) { for (j = 0; j < size; j++) { struct entry *o; int spin; /* Keep trying until we encounter at least one node. */ if (j & 1) { while (ck_ring_dequeue_spmc(&ring_spmc, buffer, &o) == false); } else { while (ck_ring_trydequeue_spmc(&ring_spmc, buffer, &o) == false); } observed++; if (o->value < 0 || o->value != o->tid || o->magic != 0xdead || (previous != 0 && previous >= o->value_long)) { ck_error("[0x%p] (%x) (%d, %d) >< (0, %d)\n", (void *)o, o->magic, o->tid, o->value, size); } o->magic = 0xbeef; o->value = -31337; o->tid = -31338; previous = o->value_long; if (ck_pr_faa_uint(&o->ref, 1) != 0) { ck_error("[%p] We dequeued twice.\n", (void *)o); } if ((i % 4) == 0) { spin = common_rand_r(&seed) % 16384; for (k = 0; k < spin; k++) { ck_pr_stall(); } } free(o); } } fprintf(stderr, "[%d] Observed %u\n", tid, observed); return NULL; }