aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/venti/srv/round.c
blob: bbf4a478a1276fc07c80b6c98f611cc74ded5a36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#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);
	}
}