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