Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

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