ck_barrier: Clean up tournament barriers.

ck_pring
Samy Al Bahra 14 years ago
parent 8b4f72057c
commit fb25458121

@ -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;

@ -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

@ -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);
}

@ -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.

Loading…
Cancel
Save