xref: /plan9-contrib/sys/src/cmd/aquarela/alarm.c (revision 4af5a9a1337b2226c3ce480af26cabb9dde39fa9)
1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <ip.h>
4*8ccd4a63SDavid du Colombier #include <thread.h>
5*8ccd4a63SDavid du Colombier #include "netbios.h"
6*8ccd4a63SDavid du Colombier 
7*8ccd4a63SDavid du Colombier static struct {
8*8ccd4a63SDavid du Colombier 	int thread;
9*8ccd4a63SDavid du Colombier 	int die;
10*8ccd4a63SDavid du Colombier 	QLock;
11*8ccd4a63SDavid du Colombier 	NbnsAlarm *head;
12*8ccd4a63SDavid du Colombier } alarmlist = { -1 };
13*8ccd4a63SDavid du Colombier 
14*8ccd4a63SDavid du Colombier #define MaxLong ((1 << (sizeof(long) * 8 - 1)) - 1)
15*8ccd4a63SDavid du Colombier 
16*8ccd4a63SDavid du Colombier void
alarmist(void *)17*8ccd4a63SDavid du Colombier alarmist(void *)
18*8ccd4a63SDavid du Colombier {
19*8ccd4a63SDavid du Colombier 	for (;;) {
20*8ccd4a63SDavid du Colombier 		vlong now;
21*8ccd4a63SDavid du Colombier 		long snooze;
22*8ccd4a63SDavid du Colombier //print("running\n");
23*8ccd4a63SDavid du Colombier 		qlock(&alarmlist);
24*8ccd4a63SDavid du Colombier 		if (alarmlist.die) {
25*8ccd4a63SDavid du Colombier 			qunlock(&alarmlist);
26*8ccd4a63SDavid du Colombier 			break;
27*8ccd4a63SDavid du Colombier 		}
28*8ccd4a63SDavid du Colombier 		now = nsec() / 1000000;
29*8ccd4a63SDavid du Colombier 		while (alarmlist.head && alarmlist.head->expirems <= now) {
30*8ccd4a63SDavid du Colombier //print("expiring because %lld > %lld\n", alarmlist.head->expirems, now);
31*8ccd4a63SDavid du Colombier 			sendul(alarmlist.head->c, 1);
32*8ccd4a63SDavid du Colombier 			alarmlist.head = alarmlist.head->next;
33*8ccd4a63SDavid du Colombier 		}
34*8ccd4a63SDavid du Colombier 		if (alarmlist.head) {
35*8ccd4a63SDavid du Colombier 			vlong vsnooze = alarmlist.head->expirems - now;
36*8ccd4a63SDavid du Colombier 			if (vsnooze > MaxLong)
37*8ccd4a63SDavid du Colombier 				snooze = MaxLong;
38*8ccd4a63SDavid du Colombier 			else
39*8ccd4a63SDavid du Colombier 				snooze = vsnooze;
40*8ccd4a63SDavid du Colombier 		}
41*8ccd4a63SDavid du Colombier 		else
42*8ccd4a63SDavid du Colombier 			snooze = 60 * 1000;
43*8ccd4a63SDavid du Colombier //print("snoozing for %ld\n", snooze);
44*8ccd4a63SDavid du Colombier 		qunlock(&alarmlist);
45*8ccd4a63SDavid du Colombier 		sleep(snooze);
46*8ccd4a63SDavid du Colombier 	}
47*8ccd4a63SDavid du Colombier }
48*8ccd4a63SDavid du Colombier 
49*8ccd4a63SDavid du Colombier NbnsAlarm *
nbnsalarmnew(void)50*8ccd4a63SDavid du Colombier nbnsalarmnew(void)
51*8ccd4a63SDavid du Colombier {
52*8ccd4a63SDavid du Colombier 	NbnsAlarm *a;
53*8ccd4a63SDavid du Colombier 	a = mallocz(sizeof(*a), 1);
54*8ccd4a63SDavid du Colombier 	if (a == nil)
55*8ccd4a63SDavid du Colombier 		return nil;
56*8ccd4a63SDavid du Colombier 	a->c = chancreate(sizeof(ulong), 1);
57*8ccd4a63SDavid du Colombier 	if (a->c == nil) {
58*8ccd4a63SDavid du Colombier 		free(a);
59*8ccd4a63SDavid du Colombier 		return nil;
60*8ccd4a63SDavid du Colombier 	}
61*8ccd4a63SDavid du Colombier 	return a;
62*8ccd4a63SDavid du Colombier }
63*8ccd4a63SDavid du Colombier 
64*8ccd4a63SDavid du Colombier void
nbnsalarmcancel(NbnsAlarm * a)65*8ccd4a63SDavid du Colombier nbnsalarmcancel(NbnsAlarm *a)
66*8ccd4a63SDavid du Colombier {
67*8ccd4a63SDavid du Colombier 	NbnsAlarm **ap;
68*8ccd4a63SDavid du Colombier 	int rv;
69*8ccd4a63SDavid du Colombier 	qlock(&alarmlist);
70*8ccd4a63SDavid du Colombier 	for (ap = &alarmlist.head; *ap && *ap != a; ap = &(*ap)->next)
71*8ccd4a63SDavid du Colombier 		;
72*8ccd4a63SDavid du Colombier 	if (*ap) {
73*8ccd4a63SDavid du Colombier 		*ap = a->next;
74*8ccd4a63SDavid du Colombier 		if (ap == &alarmlist.head)
75*8ccd4a63SDavid du Colombier 			threadint(alarmlist.thread);
76*8ccd4a63SDavid du Colombier 	}
77*8ccd4a63SDavid du Colombier 	qunlock(&alarmlist);
78*8ccd4a63SDavid du Colombier 	do {
79*8ccd4a63SDavid du Colombier 		ulong v;
80*8ccd4a63SDavid du Colombier 		rv = nbrecv(a->c, &v);
81*8ccd4a63SDavid du Colombier 	} while (rv != 0);
82*8ccd4a63SDavid du Colombier }
83*8ccd4a63SDavid du Colombier 
84*8ccd4a63SDavid du Colombier void
nbnsalarmend(void)85*8ccd4a63SDavid du Colombier nbnsalarmend(void)
86*8ccd4a63SDavid du Colombier {
87*8ccd4a63SDavid du Colombier 	qlock(&alarmlist);
88*8ccd4a63SDavid du Colombier 	if (alarmlist.thread >= 0) {
89*8ccd4a63SDavid du Colombier 		alarmlist.die = 1;
90*8ccd4a63SDavid du Colombier 		threadint(alarmlist.thread);
91*8ccd4a63SDavid du Colombier 	}
92*8ccd4a63SDavid du Colombier 	qunlock(&alarmlist);
93*8ccd4a63SDavid du Colombier }
94*8ccd4a63SDavid du Colombier 
95*8ccd4a63SDavid du Colombier void
nbnsalarmset(NbnsAlarm * a,ulong millisec)96*8ccd4a63SDavid du Colombier nbnsalarmset(NbnsAlarm *a, ulong millisec)
97*8ccd4a63SDavid du Colombier {
98*8ccd4a63SDavid du Colombier 	NbnsAlarm **ap;
99*8ccd4a63SDavid du Colombier 	nbnsalarmcancel(a);
100*8ccd4a63SDavid du Colombier 	a->expirems = nsec() / 1000000 + millisec;
101*8ccd4a63SDavid du Colombier 	qlock(&alarmlist);
102*8ccd4a63SDavid du Colombier 	for (ap = &alarmlist.head; *ap; ap = &(*ap)->next)
103*8ccd4a63SDavid du Colombier 		if (a->expirems < (*ap)->expirems)
104*8ccd4a63SDavid du Colombier 			break;
105*8ccd4a63SDavid du Colombier 	a->next = (*ap);
106*8ccd4a63SDavid du Colombier 	*ap = a;
107*8ccd4a63SDavid du Colombier 	if (alarmlist.thread < 0)
108*8ccd4a63SDavid du Colombier 		alarmlist.thread = proccreate(alarmist, nil, 16384);
109*8ccd4a63SDavid du Colombier 	else
110*8ccd4a63SDavid du Colombier 		threadint(alarmlist.thread);
111*8ccd4a63SDavid du Colombier 	qunlock(&alarmlist);
112*8ccd4a63SDavid du Colombier }
113*8ccd4a63SDavid du Colombier 
114*8ccd4a63SDavid du Colombier void
nbnsalarmfree(NbnsAlarm ** ap)115*8ccd4a63SDavid du Colombier nbnsalarmfree(NbnsAlarm **ap)
116*8ccd4a63SDavid du Colombier {
117*8ccd4a63SDavid du Colombier 	NbnsAlarm *a;
118*8ccd4a63SDavid du Colombier 	a = *ap;
119*8ccd4a63SDavid du Colombier 	if (a) {
120*8ccd4a63SDavid du Colombier 		nbnsalarmcancel(a);
121*8ccd4a63SDavid du Colombier 		chanfree(a->c);
122*8ccd4a63SDavid du Colombier 		free(a);
123*8ccd4a63SDavid du Colombier 		*ap = nil;
124*8ccd4a63SDavid du Colombier 	}
125*8ccd4a63SDavid du Colombier }
126