~kris/9p

9hist

ref: a18dd0f8d3e945c2f7764d6420039e0b9a44c0ff 9hist/port/tcptimer.c -rw-r--r-- 2.2 KiB
a18dd0f8 — David du Colombier Plan 9 from Bell Labs 1991-11-26 34 years ago
                                                                                
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"
#include 	"arp.h"
#include 	"ipdat.h"

/* Head of running timer chain */
Timer 	*timers;
QLock 	timerlock;
Rendez	Tcpack;
Rendez	tcpflowr;

void
tcpackproc(void *junk)
{
	Timer *t,*tp;
	Timer *expired;

	USED(junk);
	for(;;) {
		expired = 0;

		/* Run through the list of running timers, decrementing each one.
		 * If one has expired, take it off the running list and put it
		 * on a singly linked list of expired timers
		 */

		qlock(&timerlock);
		for(t = timers;t != 0; t = tp) {
			tp = t->next;
			if(tp == t)
				panic("Timer loop at %lux\n",(long)tp);
	
 			if(t->state == TIMER_RUN && --(t->count) == 0){

				/* Delete from active timer list */
				if(timers == t)
					timers = t->next;
				if(t->next != 0)
					t->next->prev = t->prev;
				if(t->prev != 0)
					t->prev->next = t->next;

				t->state = TIMER_EXPIRE;
				/* Put on head of expired timer list */
				t->next = expired;
				expired = t;
			}
		}
		qunlock(&timerlock);

		while((t = expired) != 0){
			expired = t->next;
			if(t->state == TIMER_EXPIRE && t->func)
				(*t->func)(t->arg);
		}

		tsleep(&Tcpack, return0, 0, MSPTICK);
	}
}

void
start_timer(Timer *t)
{

	if(t == 0 || t->start == 0)
		return;

	qlock(&timerlock);

	t->count = t->start;
	if(t->state != TIMER_RUN){
		t->state = TIMER_RUN;
		/* Put on head of active timer list */
		t->prev = 0;
		t->next = timers;
		if(t->next != 0)
			t->next->prev = t;
		timers = t;
	}
	qunlock(&timerlock);
}

void
stop_timer(Timer *t)
{
	if(t == 0)
		return;

	qlock(&timerlock);

	if(t->state == TIMER_RUN){
		/* Delete from active timer list */
		if(timers == t)
			timers = t->next;
		if(t->next != 0)
			t->next->prev = t->prev;
		if(t->prev != 0)
			t->prev->next = t->next;
	}
	t->state = TIMER_STOP;

	qunlock(&timerlock);
}

void
tcpflow(void *conv)
{
	Ipconv *base, *ifc, *etab;

	base = (Ipconv*)conv;

	etab = &base[conf.ip];
	for(;;) {
		sleep(&tcpflowr, return0, 0);

		for(ifc = base; ifc < etab; ifc++) {
			if(ifc->stproto == &tcpinfo &&
			   ifc->ref != 0 && ifc->readq &&
			   !QFULL(ifc->readq->next)) {
				tcprcvwin(ifc);
				tcp_acktimer(ifc);
			}
		}
	}
}