blob: 0ed4ea56051a35fd235a7d76e857ec984533edd6 (
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include <u.h>
#include <libc.h>
#include <ip.h>
#include <thread.h>
#include "netbios.h"
static struct {
int thread;
int die;
QLock;
NbnsAlarm *head;
} alarmlist = { -1 };
#define MaxLong ((1 << (sizeof(long) * 8 - 1)) - 1)
void
alarmist(void *)
{
for (;;) {
vlong now;
long snooze;
//print("running\n");
qlock(&alarmlist);
if (alarmlist.die) {
qunlock(&alarmlist);
break;
}
now = nsec() / 1000000;
while (alarmlist.head && alarmlist.head->expirems <= now) {
//print("expiring because %lld > %lld\n", alarmlist.head->expirems, now);
sendul(alarmlist.head->c, 1);
alarmlist.head = alarmlist.head->next;
}
if (alarmlist.head) {
vlong vsnooze = alarmlist.head->expirems - now;
if (vsnooze > MaxLong)
snooze = MaxLong;
else
snooze = vsnooze;
}
else
snooze = 60 * 1000;
//print("snoozing for %ld\n", snooze);
qunlock(&alarmlist);
sleep(snooze);
}
}
NbnsAlarm *
nbnsalarmnew(void)
{
NbnsAlarm *a;
a = mallocz(sizeof(*a), 1);
if (a == nil)
return nil;
a->c = chancreate(sizeof(ulong), 1);
if (a->c == nil) {
free(a);
return nil;
}
return a;
}
void
nbnsalarmcancel(NbnsAlarm *a)
{
NbnsAlarm **ap;
int rv;
qlock(&alarmlist);
for (ap = &alarmlist.head; *ap && *ap != a; ap = &(*ap)->next)
;
if (*ap) {
*ap = a->next;
if (ap == &alarmlist.head)
threadint(alarmlist.thread);
}
qunlock(&alarmlist);
do {
ulong v;
rv = nbrecv(a->c, &v);
} while (rv != 0);
}
void
nbnsalarmend(void)
{
qlock(&alarmlist);
if (alarmlist.thread >= 0) {
alarmlist.die = 1;
threadint(alarmlist.thread);
}
qunlock(&alarmlist);
}
void
nbnsalarmset(NbnsAlarm *a, ulong millisec)
{
NbnsAlarm **ap;
nbnsalarmcancel(a);
a->expirems = nsec() / 1000000 + millisec;
qlock(&alarmlist);
for (ap = &alarmlist.head; *ap; ap = &(*ap)->next)
if (a->expirems < (*ap)->expirems)
break;
a->next = (*ap);
*ap = a;
if (alarmlist.thread < 0)
alarmlist.thread = proccreate(alarmist, nil, 16384);
else
threadint(alarmlist.thread);
qunlock(&alarmlist);
}
void
nbnsalarmfree(NbnsAlarm **ap)
{
NbnsAlarm *a;
a = *ap;
if (a) {
nbnsalarmcancel(a);
chanfree(a->c);
free(a);
*ap = nil;
}
}
|