Commit 4b48aaf9 authored by Dridi Boukelmoune's avatar Dridi Boukelmoune Committed by Lasse Karstensen

Barriers can be cyclic but not like semaphores

This is useful in HTTP loops where it's impossible to predict and use an
array of barriers. All cycles expect the same number of waiters, unlike
semaphores.
parent 315bdbcc
varnishtest "Barrier operations"
barrier b1 cond 4
barrier b2 cond 4
# bs -> server, bc -> client, bb -> both
barrier bs cond 4
barrier bc cond 4
barrier bb cond 4 -cyclic
server s1 {
rxreq
barrier b1 sync
barrier bs sync
barrier bb sync
delay .9
txresp
} -start
server s2 {
rxreq
barrier b1 sync
barrier bs sync
barrier bb sync
delay .6
txresp
} -start
server s3 {
rxreq
barrier b1 sync
barrier bs sync
barrier bb sync
delay .2
txresp
} -start
......@@ -28,25 +33,30 @@ client c1 -connect ${s1_sock} {
delay .2
txreq
rxresp
barrier b2 sync
barrier bc sync
barrier bb sync
} -start
client c2 -connect ${s2_sock} {
delay .6
txreq
rxresp
barrier b2 sync
barrier bc sync
barrier bb sync
} -start
client c3 -connect ${s3_sock} {
delay .9
txreq
rxresp
barrier b2 sync
barrier bc sync
barrier bb sync
} -start
# Wait for all servers to have received requests
barrier b1 sync
barrier bs sync
barrier bb sync
# Wait for all clients to have received responses
barrier b2 sync
barrier bc sync
barrier bb sync
......@@ -52,6 +52,7 @@ struct barrier {
unsigned waiters;
unsigned expected;
unsigned cyclic;
enum barrier_e type;
};
......@@ -122,6 +123,23 @@ barrier_sock(struct barrier *b, const char *av, struct vtclog *vl)
INCOMPL();
}
static void
barrier_cyclic(struct barrier *b, struct vtclog *vl)
{
CHECK_OBJ_NOTNULL(b, BARRIER_MAGIC);
if (b->type == BARRIER_NONE)
vtc_log(vl, 0,
"Barrier(%s) use error: not initialized", b->name);
if (b->waiters != 0)
vtc_log(vl, 0,
"Barrier(%s) use error: already in use", b->name);
b->cyclic = 1;
}
/**********************************************************************
* Sync a barrier
*/
......@@ -148,6 +166,9 @@ barrier_cond_sync(struct barrier *b, struct vtclog *vl)
b->name, b->waiters, b->expected);
AZ(pthread_cond_wait(&b->cond, &b->mtx));
}
if (b->cyclic)
b->waiters = 0;
}
static void
......@@ -189,7 +210,10 @@ cmd_barrier(CMD_ARGS)
VTAILQ_FOREACH_SAFE(b, &barriers, list, b2) {
AZ(pthread_mutex_lock(&b->mtx));
assert(b->type != BARRIER_NONE);
assert(b->waiters == b->expected);
if (b->cyclic)
AZ(b->waiters);
else
assert(b->waiters == b->expected);
AZ(pthread_mutex_unlock(&b->mtx));
}
AZ(pthread_mutex_unlock(&barrier_mtx));
......@@ -226,6 +250,10 @@ cmd_barrier(CMD_ARGS)
barrier_sync(b, vl);
continue;
}
if (!strcmp(*av, "-cyclic")) {
barrier_cyclic(b, vl);
continue;
}
vtc_log(vl, 0, "Unknown barrier argument: %s", *av);
}
AZ(pthread_mutex_unlock(&b->mtx));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment