From fb2545812196f426800a790c20217cecdfd9b7b7 Mon Sep 17 00:00:00 2001 From: Samy Al Bahra Date: Wed, 9 Mar 2011 19:42:36 -0500 Subject: [PATCH] ck_barrier: Clean up tournament barriers. --- include/ck_barrier.h | 14 +++- regressions/ck_barrier/validate/Makefile | 2 +- .../validate/ck_barrier_tournament.c | 19 +++-- src/ck_barrier_tournament.c | 78 +++++++++++-------- 4 files changed, 68 insertions(+), 45 deletions(-) diff --git a/include/ck_barrier.h b/include/ck_barrier.h index fec90eb..ba1b2b3 100644 --- a/include/ck_barrier.h +++ b/include/ck_barrier.h @@ -115,22 +115,28 @@ void ck_barrier_dissemination(ck_barrier_dissemination_t *, ck_barrier_dissemination_state_t *); struct ck_barrier_tournament_round { - enum {BYE, CHAMPION, DROPOUT, LOSER, WINNER} role; + int role; unsigned int *opponent; unsigned int flag; }; typedef struct ck_barrier_tournament_round ck_barrier_tournament_round_t; +struct ck_barrier_tournament { + unsigned int tid; + struct ck_barrier_tournament_round **rounds; +}; +typedef struct ck_barrier_tournament ck_barrier_tournament_t; + struct ck_barrier_tournament_state { unsigned int sense; unsigned int vpid; }; typedef struct ck_barrier_tournament_state ck_barrier_tournament_state_t; -void ck_barrier_tournament_state_init(ck_barrier_tournament_state_t *); -void ck_barrier_tournament_round_init(ck_barrier_tournament_round_t **, unsigned int); +void ck_barrier_tournament_subscribe(ck_barrier_tournament_t *, ck_barrier_tournament_state_t *); +void ck_barrier_tournament_init(ck_barrier_tournament_t *, ck_barrier_tournament_round_t **, unsigned int); unsigned int ck_barrier_tournament_size(unsigned int); -void ck_barrier_tournament(ck_barrier_tournament_round_t **, ck_barrier_tournament_state_t *); +void ck_barrier_tournament(ck_barrier_tournament_t *, ck_barrier_tournament_state_t *); struct ck_barrier_mcs { unsigned int tid; diff --git a/regressions/ck_barrier/validate/Makefile b/regressions/ck_barrier/validate/Makefile index e0611da..ec7754b 100644 --- a/regressions/ck_barrier/validate/Makefile +++ b/regressions/ck_barrier/validate/Makefile @@ -23,4 +23,4 @@ clean: rm -rf *.dSYM *~ *.o $(OBJECTS) include ../../../build/regressions.build -CFLAGS+=-D_GNU_SOURCE -lpthread +CFLAGS+=-D_GNU_SOURCE -lpthread -ggdb -O0 diff --git a/regressions/ck_barrier/validate/ck_barrier_tournament.c b/regressions/ck_barrier/validate/ck_barrier_tournament.c index 7fdfc15..2d14b61 100644 --- a/regressions/ck_barrier/validate/ck_barrier_tournament.c +++ b/regressions/ck_barrier/validate/ck_barrier_tournament.c @@ -53,17 +53,17 @@ static struct affinity a; static int nthr; static int counters[ENTRIES]; static int barrier_wait; +static ck_barrier_tournament_t barrier; static void * -thread(void *rounds) +thread(CK_CC_UNUSED void *unused) { ck_barrier_tournament_state_t state; int j, counter; int i = 0; aff_iterate(&a); - - ck_barrier_tournament_state_init(&state); + ck_barrier_tournament_subscribe(&barrier, &state); ck_pr_inc_int(&barrier_wait); while (ck_pr_load_int(&barrier_wait) != nthr) @@ -72,7 +72,7 @@ thread(void *rounds) for (j = 0; j < ITERATE; j++) { i = j++ & (ENTRIES - 1); ck_pr_inc_int(&counters[i]); - ck_barrier_tournament(rounds, &state); + ck_barrier_tournament(&barrier, &state); counter = ck_pr_load_int(&counters[i]); if (counter != nthr * (j / ENTRIES + 1)) { fprintf(stderr, "FAILED [%d:%d]: %d != %d\n", i, j - 1, counter, nthr); @@ -80,6 +80,10 @@ thread(void *rounds) } } + ck_pr_inc_int(&barrier_wait); + while (ck_pr_load_int(&barrier_wait) != nthr * 2) + ck_pr_stall(); + return (NULL); } @@ -101,6 +105,7 @@ main(int argc, char *argv[]) fprintf(stderr, "ERROR: Number of threads must be greater than 0\n"); exit(EXIT_FAILURE); } + a.delta = atoi(argv[2]); threads = malloc(sizeof(pthread_t) * nthr); if (threads == NULL) { @@ -122,13 +127,12 @@ main(int argc, char *argv[]) exit(EXIT_FAILURE); } } - ck_barrier_tournament_round_init(rounds, nthr); - a.delta = atoi(argv[2]); + ck_barrier_tournament_init(&barrier, rounds, nthr); fprintf(stderr, "Creating threads (barrier)..."); for (i = 0; i < nthr; i++) { - if (pthread_create(&threads[i], NULL, thread, rounds)) { + if (pthread_create(&threads[i], NULL, thread, NULL)) { fprintf(stderr, "ERROR: Could not create thread %d\n", i); exit(EXIT_FAILURE); } @@ -140,7 +144,6 @@ main(int argc, char *argv[]) pthread_join(threads[i], NULL); fprintf(stderr, "done (passed)\n"); - return (0); } diff --git a/src/ck_barrier_tournament.c b/src/ck_barrier_tournament.c index f699ee4..f00a08f 100644 --- a/src/ck_barrier_tournament.c +++ b/src/ck_barrier_tournament.c @@ -37,52 +37,64 @@ * on their own flags. During the last round, the champion of the tournament * sets the last flag that begins the wakeup process. */ -static unsigned int ck_barrier_tournament_tid; + +enum { + CK_BARRIER_TOURNAMENT_BYE, + CK_BARRIER_TOURNAMENT_CHAMPION, + CK_BARRIER_TOURNAMENT_DROPOUT, + CK_BARRIER_TOURNAMENT_LOSER, + CK_BARRIER_TOURNAMENT_WINNER +}; void -ck_barrier_tournament_state_init(ck_barrier_tournament_state_t *state) +ck_barrier_tournament_subscribe(struct ck_barrier_tournament *barrier, + struct ck_barrier_tournament_state *state) { state->sense = ~0; - state->vpid = ck_pr_faa_uint(&ck_barrier_tournament_tid, 1); + state->vpid = ck_pr_faa_uint(&barrier->tid, 1); return; } void -ck_barrier_tournament_round_init(struct ck_barrier_tournament_round **rounds, - unsigned int nthr) +ck_barrier_tournament_init(struct ck_barrier_tournament *barrier, + struct ck_barrier_tournament_round **rounds, + unsigned int nthr) { unsigned int i, k, size, twok, twokm1, imod2k; + ck_pr_store_uint(&barrier->tid, 0); size = ck_barrier_tournament_size(nthr); + for (i = 0; i < nthr; ++i) { - /* The first role is always DROPOUT. */ + /* The first role is always CK_BARRIER_TOURNAMENT_DROPOUT. */ rounds[i][0].flag = 0; - rounds[i][0].role = DROPOUT; + rounds[i][0].role = CK_BARRIER_TOURNAMENT_DROPOUT; for (k = 1, twok = 2, twokm1 = 1; k < size; ++k, twokm1 = twok, twok <<= 1) { rounds[i][k].flag = 0; imod2k = i & (twok - 1); if (imod2k == 0) { if ((i + twokm1 < nthr) && (twok < nthr)) - rounds[i][k].role = WINNER; + rounds[i][k].role = CK_BARRIER_TOURNAMENT_WINNER; else if (i + twokm1 >= nthr) - rounds[i][k].role = BYE; + rounds[i][k].role = CK_BARRIER_TOURNAMENT_BYE; } - if (imod2k == twokm1) - rounds[i][k].role = LOSER; - /* There is exactly one champion in a tournament barrier. */ + if (imod2k == twokm1) + rounds[i][k].role = CK_BARRIER_TOURNAMENT_LOSER; else if ((i == 0) && (twok >= nthr)) - rounds[i][k].role = CHAMPION; + rounds[i][k].role = CK_BARRIER_TOURNAMENT_CHAMPION; - if (rounds[i][k].role == LOSER) + if (rounds[i][k].role == CK_BARRIER_TOURNAMENT_LOSER) rounds[i][k].opponent = &rounds[i - twokm1][k].flag; - else if (rounds[i][k].role == WINNER || rounds[i][k].role == CHAMPION) + else if (rounds[i][k].role == CK_BARRIER_TOURNAMENT_WINNER || + rounds[i][k].role == CK_BARRIER_TOURNAMENT_CHAMPION) rounds[i][k].opponent = &rounds[i + twokm1][k].flag; } } + ck_pr_store_ptr(&barrier->rounds, rounds); return; } @@ -94,41 +106,42 @@ ck_barrier_tournament_size(unsigned int nthr) } void -ck_barrier_tournament(struct ck_barrier_tournament_round **rounds, +ck_barrier_tournament(struct ck_barrier_tournament *barrier, struct ck_barrier_tournament_state *state) { + struct ck_barrier_tournament_round **rounds = ck_pr_load_ptr(&barrier->rounds); int round = 1; for (;; ++round) { switch (rounds[state->vpid][round].role) { // MIGHT NEED TO USE CK_PR_LOAD*** - case BYE: + case CK_BARRIER_TOURNAMENT_BYE: break; - case CHAMPION: + case CK_BARRIER_TOURNAMENT_CHAMPION: /* - * The CHAMPION waits until it wins the tournament; it then + * The CK_BARRIER_TOURNAMENT_CHAMPION waits until it wins the tournament; it then * sets the final flag before the wakeup phase of the barrier. */ while (ck_pr_load_uint(&rounds[state->vpid][round].flag) != state->sense) ck_pr_stall(); + ck_pr_store_uint(rounds[state->vpid][round].opponent, state->sense); goto wakeup; - break; - case DROPOUT: + case CK_BARRIER_TOURNAMENT_DROPOUT: /* NOTREACHED */ break; - case LOSER: + case CK_BARRIER_TOURNAMENT_LOSER: /* - * LOSERs set the flags of their opponents and wait until + * CK_BARRIER_TOURNAMENT_LOSERs set the flags of their opponents and wait until * their opponents release them after the tournament is over. */ ck_pr_store_uint(rounds[state->vpid][round].opponent, state->sense); while (ck_pr_load_uint(&rounds[state->vpid][round].flag) != state->sense) ck_pr_stall(); + goto wakeup; - break; - case WINNER: + case CK_BARRIER_TOURNAMENT_WINNER: /* - * WINNERs wait until their current opponent sets their flag; they then + * CK_BARRIER_TOURNAMENT_WINNERs wait until their current opponent sets their flag; they then * continue to the next round of the tournament. */ while (ck_pr_load_uint(&rounds[state->vpid][round].flag) != state->sense) @@ -136,21 +149,22 @@ ck_barrier_tournament(struct ck_barrier_tournament_round **rounds, break; } } + wakeup: - for (round -= 1;; --round) { + for (round -= 1 ;; --round) { switch (rounds[state->vpid][round].role) { // MIGHT NEED TO USE CK_PR_LOAD*** - case BYE: + case CK_BARRIER_TOURNAMENT_BYE: break; - case CHAMPION: + case CK_BARRIER_TOURNAMENT_CHAMPION: /* NOTREACHED */ break; - case DROPOUT: + case CK_BARRIER_TOURNAMENT_DROPOUT: goto leave; break; - case LOSER: + case CK_BARRIER_TOURNAMENT_LOSER: /* NOTREACHED */ break; - case WINNER: + case CK_BARRIER_TOURNAMENT_WINNER: /* * Winners inform their old opponents the tournament is over * by setting their flags.