#include "stdinc.h"
#include "dat.h"
#include "fns.h"
void
waitforkick(Round *r)
{
int n;
qlock(&r->lock);
r->last = r->current;
assert(r->current+1 == r->next);
rwakeupall(&r->finish);
while(!r->doanother)
rsleep(&r->start);
n = r->next++;
r->current = n;
r->doanother = 0;
qunlock(&r->lock);
}
static void
_kickround(Round *r, int wait)
{
int n;
if(!r->doanother)
trace(TraceProc, "kick %s", r->name);
r->doanother = 1;
rwakeup(&r->start);
if(wait){
n = r->next;
while((int)(n - r->last) > 0){
r->doanother = 1;
rwakeup(&r->start);
rsleep(&r->finish);
}
}
}
void
kickround(Round *r, int wait)
{
qlock(&r->lock);
_kickround(r, wait);
qunlock(&r->lock);
}
void
initround(Round *r, char *name, int delay)
{
memset(r, 0, sizeof *r);
r->name = name;
r->start.l = &r->lock;
r->finish.l = &r->lock;
r->delaywait.l = &r->lock;
r->last = 0;
r->current = 0;
r->next = 1;
r->doanother = 0;
r->delaytime = delay;
}
void
delaykickround(Round *r)
{
qlock(&r->lock);
r->delaykick = 1;
rwakeup(&r->delaywait);
qunlock(&r->lock);
}
void
delaykickroundproc(void *v)
{
Round *r = v;
int n;
threadsetname("delaykickproc %s", r->name);
qlock(&r->lock);
for(;;){
while(r->delaykick == 0){
trace(TraceProc, "sleep");
rsleep(&r->delaywait);
}
n = r->next;
qunlock(&r->lock);
trace(TraceProc, "waitround 0x%ux", (uint)n);
sleep(r->delaytime);
qlock(&r->lock);
if(n == r->next){
trace(TraceProc, "kickround 0x%ux", (uint)n);
_kickround(r, 1);
}
trace(TraceProc, "finishround 0x%ux", (uint)n);
}
}
|