1 1.7 wiz /* $NetBSD: callout.c,v 1.7 2003/03/05 21:05:38 wiz Exp $ */ 2 1.2 thorpej 3 1.1 mycroft /* 4 1.1 mycroft * The mrouted program is covered by the license in the accompanying file 5 1.1 mycroft * named "LICENSE". Use of the mrouted program represents acceptance of 6 1.1 mycroft * the terms and conditions listed in that file. 7 1.1 mycroft * 8 1.1 mycroft * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of 9 1.1 mycroft * Leland Stanford Junior University. 10 1.1 mycroft */ 11 1.1 mycroft 12 1.1 mycroft #include "defs.h" 13 1.1 mycroft 14 1.1 mycroft /* the code below implements a callout queue */ 15 1.1 mycroft static int id = 0; 16 1.1 mycroft static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */ 17 1.1 mycroft 18 1.3 mycroft static int in_callout = 0; 19 1.1 mycroft 20 1.1 mycroft struct timeout_q { 21 1.1 mycroft struct timeout_q *next; /* next event */ 22 1.1 mycroft int id; 23 1.3 mycroft cfunc_t func; /* function to call */ 24 1.1 mycroft char *data; /* func's data */ 25 1.1 mycroft int time; /* time offset to next event*/ 26 1.1 mycroft }; 27 1.1 mycroft 28 1.3 mycroft #ifdef IGMP_DEBUG 29 1.5 wiz static void print_Q(void); 30 1.3 mycroft #else 31 1.3 mycroft #define print_Q() 32 1.3 mycroft #endif 33 1.1 mycroft 34 1.5 wiz int secs_remaining(int); 35 1.4 lukem 36 1.3 mycroft void 37 1.5 wiz callout_init(void) 38 1.1 mycroft { 39 1.1 mycroft Q = (struct timeout_q *) 0; 40 1.1 mycroft } 41 1.1 mycroft 42 1.1 mycroft 43 1.1 mycroft /* 44 1.1 mycroft * signal handler for SIGALARM that is called once every second 45 1.1 mycroft */ 46 1.3 mycroft void 47 1.5 wiz age_callout_queue(void) 48 1.1 mycroft { 49 1.1 mycroft struct timeout_q *ptr; 50 1.1 mycroft 51 1.1 mycroft if (in_callout) 52 1.1 mycroft return; 53 1.1 mycroft 54 1.1 mycroft in_callout = 1; 55 1.1 mycroft ptr = Q; 56 1.1 mycroft 57 1.3 mycroft while (ptr) { 58 1.3 mycroft if (!ptr->time) { 59 1.1 mycroft /* timeout has happened */ 60 1.3 mycroft Q = Q->next; 61 1.3 mycroft 62 1.3 mycroft in_callout = 0; 63 1.3 mycroft if (ptr->func) 64 1.1 mycroft ptr->func(ptr->data); 65 1.3 mycroft in_callout = 1; 66 1.1 mycroft 67 1.1 mycroft free(ptr); 68 1.1 mycroft ptr = Q; 69 1.1 mycroft } 70 1.1 mycroft else { 71 1.1 mycroft ptr->time --; 72 1.1 mycroft #ifdef IGMP_DEBUG 73 1.7 wiz logit(LOG_DEBUG,0,"[callout, age_callout_queue] -- time (%d)", ptr->time); 74 1.3 mycroft #endif /* IGMP_DEBUG */ 75 1.1 mycroft in_callout = 0; return; 76 1.1 mycroft } 77 1.1 mycroft } 78 1.1 mycroft in_callout = 0; 79 1.1 mycroft return; 80 1.1 mycroft } 81 1.1 mycroft 82 1.1 mycroft 83 1.1 mycroft /* 84 1.1 mycroft * sets the timer 85 1.5 wiz * 86 1.5 wiz * delay: number of units for timeout 87 1.5 wiz * action: function to be called on timeout 88 1.5 wiz * data: what to call the timeout function with 89 1.1 mycroft */ 90 1.3 mycroft int 91 1.5 wiz timer_setTimer(int delay, cfunc_t action, char *data) 92 1.1 mycroft { 93 1.1 mycroft struct timeout_q *ptr, *node, *prev; 94 1.1 mycroft 95 1.1 mycroft if (in_callout) 96 1.1 mycroft return -1; 97 1.1 mycroft 98 1.1 mycroft in_callout = 1; 99 1.1 mycroft 100 1.1 mycroft /* create a node */ 101 1.3 mycroft node = (struct timeout_q *)malloc(sizeof(struct timeout_q)); 102 1.1 mycroft if (node == 0) { 103 1.7 wiz logit(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n"); 104 1.1 mycroft in_callout = 0; 105 1.1 mycroft return -1; 106 1.1 mycroft } 107 1.1 mycroft node->func = action; 108 1.1 mycroft node->data = data; 109 1.1 mycroft node->time = delay; 110 1.1 mycroft node->next = 0; 111 1.1 mycroft node->id = ++id; 112 1.1 mycroft 113 1.1 mycroft prev = ptr = Q; 114 1.1 mycroft 115 1.1 mycroft /* insert node in the queue */ 116 1.1 mycroft 117 1.1 mycroft /* if the queue is empty, insert the node and return */ 118 1.1 mycroft if (!Q) 119 1.1 mycroft Q = node; 120 1.1 mycroft else { 121 1.1 mycroft /* chase the pointer looking for the right place */ 122 1.3 mycroft while (ptr) { 123 1.1 mycroft 124 1.3 mycroft if (delay < ptr->time) { 125 1.1 mycroft /* right place */ 126 1.1 mycroft 127 1.1 mycroft node->next = ptr; 128 1.1 mycroft if (ptr == Q) 129 1.1 mycroft Q = node; 130 1.1 mycroft else 131 1.1 mycroft prev->next = node; 132 1.1 mycroft ptr->time -= node->time; 133 1.1 mycroft print_Q(); 134 1.1 mycroft in_callout = 0; 135 1.1 mycroft return node->id; 136 1.3 mycroft } else { 137 1.1 mycroft /* keep moving */ 138 1.1 mycroft 139 1.1 mycroft delay -= ptr->time; node->time = delay; 140 1.1 mycroft prev = ptr; 141 1.1 mycroft ptr = ptr->next; 142 1.1 mycroft } 143 1.1 mycroft } 144 1.1 mycroft prev->next = node; 145 1.1 mycroft } 146 1.1 mycroft print_Q(); 147 1.1 mycroft in_callout = 0; 148 1.1 mycroft return node->id; 149 1.1 mycroft } 150 1.1 mycroft 151 1.1 mycroft 152 1.1 mycroft /* clears the associated timer */ 153 1.3 mycroft void 154 1.5 wiz timer_clearTimer(int timer_id) 155 1.1 mycroft { 156 1.1 mycroft struct timeout_q *ptr, *prev; 157 1.1 mycroft 158 1.3 mycroft if (in_callout) 159 1.3 mycroft return; 160 1.3 mycroft if (!timer_id) 161 1.3 mycroft return; 162 1.3 mycroft 163 1.1 mycroft in_callout = 1; 164 1.1 mycroft 165 1.1 mycroft prev = ptr = Q; 166 1.1 mycroft 167 1.1 mycroft /* 168 1.1 mycroft * find the right node, delete it. the subsequent node's time 169 1.1 mycroft * gets bumped up 170 1.1 mycroft */ 171 1.1 mycroft 172 1.1 mycroft print_Q(); 173 1.3 mycroft while (ptr) { 174 1.3 mycroft if (ptr->id == timer_id) { 175 1.1 mycroft /* got the right node */ 176 1.1 mycroft 177 1.1 mycroft /* unlink it from the queue */ 178 1.3 mycroft if (ptr == Q) 179 1.1 mycroft Q = Q->next; 180 1.1 mycroft else 181 1.1 mycroft prev->next = ptr->next; 182 1.1 mycroft 183 1.1 mycroft /* increment next node if any */ 184 1.1 mycroft if (ptr->next != 0) 185 1.1 mycroft (ptr->next)->time += ptr->time; 186 1.1 mycroft 187 1.1 mycroft free(ptr->data); 188 1.1 mycroft free(ptr); 189 1.1 mycroft print_Q(); 190 1.1 mycroft in_callout = 0; 191 1.1 mycroft return; 192 1.1 mycroft } 193 1.1 mycroft prev = ptr; 194 1.1 mycroft ptr = ptr->next; 195 1.1 mycroft } 196 1.1 mycroft print_Q(); 197 1.1 mycroft in_callout = 0; 198 1.1 mycroft } 199 1.1 mycroft 200 1.3 mycroft #ifdef IGMP_DEBUG 201 1.1 mycroft /* 202 1.1 mycroft * debugging utility 203 1.1 mycroft */ 204 1.3 mycroft static void 205 1.5 wiz print_Q(void) 206 1.1 mycroft { 207 1.1 mycroft struct timeout_q *ptr; 208 1.1 mycroft 209 1.1 mycroft for(ptr = Q; ptr; ptr = ptr->next) 210 1.7 wiz logit(LOG_DEBUG,0,"(%d,%d) ", ptr->id, ptr->time); 211 1.1 mycroft } 212 1.3 mycroft #endif /* IGMP_DEBUG */ 213 1.4 lukem 214 1.3 mycroft int 215 1.5 wiz secs_remaining(int timer_id) 216 1.3 mycroft { 217 1.3 mycroft struct timeout_q *ptr; 218 1.3 mycroft int left=0; 219 1.3 mycroft 220 1.3 mycroft for (ptr = Q; ptr && ptr->id != timer_id; ptr = ptr->next) 221 1.3 mycroft left += ptr->time; 222 1.1 mycroft 223 1.3 mycroft if (!ptr) /* not found */ 224 1.3 mycroft return 0; 225 1.3 mycroft 226 1.3 mycroft return left + ptr->time; 227 1.3 mycroft } 228