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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
|
/*
* The mrouted program is covered by the license in the accompanying file
* named "LICENSE.mrouted". Use of the mrouted program represents acceptance
* of the terms and conditions listed in that file.
*
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
* Leland Stanford Junior University.
*
*
* callout.c,v 3.8.4.5 1997/05/16 20:18:25 fenner Exp
*/
#include "defs.h"
/* the code below implements a callout queue */
static int id = 0;
static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */
struct timeout_q {
struct timeout_q *next; /* next event */
int id;
cfunc_t func; /* function to call */
void *data; /* func's data */
int time; /* time offset to next event*/
};
#if 0
#define CALLOUT_DEBUG 1
#define CALLOUT_DEBUG2 1
#endif /* 0 */
#ifdef CALLOUT_DEBUG2
static void print_Q((void);
#else
#define print_Q()
#endif
void
callout_init()
{
Q = (struct timeout_q *) 0;
}
void
free_all_callouts()
{
struct timeout_q *p;
while (Q) {
p = Q;
Q = Q->next;
free(p);
}
}
/*
* elapsed_time seconds have passed; perform all the events that should
* happen.
*/
void
age_callout_queue(elapsed_time)
int elapsed_time;
{
struct timeout_q *ptr, *expQ;
#ifdef CALLOUT_DEBUG
IF_DEBUG(DEBUG_TIMEOUT)
logit(LOG_DEBUG, 0, "aging queue (elapsed time %d):", elapsed_time);
print_Q();
#endif
expQ = Q;
ptr = NULL;
while (Q) {
if (Q->time > elapsed_time) {
Q->time -= elapsed_time;
if (ptr) {
ptr->next = NULL;
break;
}
return;
} else {
elapsed_time -= Q->time;
ptr = Q;
Q = Q->next;
}
}
/* handle queue of expired timers */
while (expQ) {
ptr = expQ;
if (ptr->func)
ptr->func(ptr->data);
expQ = expQ->next;
free(ptr);
}
}
/*
* Return in how many seconds age_callout_queue() would like to be called.
* Return -1 if there are no events pending.
*/
int
timer_nextTimer()
{
if (Q) {
if (Q->time < 0) {
logit(LOG_WARNING, 0, "timer_nextTimer top of queue says %d",
Q->time);
return 0;
}
return Q->time;
}
return -1;
}
/*
* sets the timer
*/
int
timer_setTimer(delay, action, data)
int delay; /* number of units for timeout */
cfunc_t action; /* function to be called on timeout */
void *data; /* what to call the timeout function with */
{
struct timeout_q *ptr, *node, *prev;
#ifdef CALLOUT_DEBUG
IF_DEBUG(DEBUG_TIMEOUT)
logit(LOG_DEBUG, 0, "setting timer:");
print_Q();
#endif
/* create a node */
node = (struct timeout_q *)calloc(1, sizeof(struct timeout_q));
if (!node) {
logit(LOG_ERR, 0, "Failed calloc() in timer_settimer\n");
return -1;
}
node->func = action;
node->data = data;
node->time = delay;
node->next = 0;
node->id = ++id;
prev = ptr = Q;
/* insert node in the queue */
/* if the queue is empty, insert the node and return */
if (!Q)
Q = node;
else {
/* chase the pointer looking for the right place */
while (ptr) {
if (delay < ptr->time) {
/* right place */
node->next = ptr;
if (ptr == Q)
Q = node;
else
prev->next = node;
ptr->time -= node->time;
print_Q();
return node->id;
} else {
/* keep moving */
delay -= ptr->time; node->time = delay;
prev = ptr;
ptr = ptr->next;
}
}
prev->next = node;
}
print_Q();
return node->id;
}
/* returns the time until the timer is scheduled */
int
timer_leftTimer(timer_id)
int timer_id;
{
struct timeout_q *ptr;
int left = 0;
if (!timer_id)
return -1;
for (ptr = Q; ptr; ptr = ptr->next) {
left += ptr->time;
if (ptr->id == timer_id)
return left;
}
return -1;
}
/* clears the associated timer */
void
timer_clearTimer(timer_id)
int timer_id;
{
struct timeout_q *ptr, *prev;
if (!timer_id)
return;
prev = ptr = Q;
/*
* find the right node, delete it. the subsequent node's time
* gets bumped up
*/
print_Q();
while (ptr) {
if (ptr->id == timer_id) {
/* got the right node */
/* unlink it from the queue */
if (ptr == Q)
Q = Q->next;
else
prev->next = ptr->next;
/* increment next node if any */
if (ptr->next != 0)
(ptr->next)->time += ptr->time;
if (ptr->data)
free(ptr->data);
free(ptr);
print_Q();
return;
}
prev = ptr;
ptr = ptr->next;
}
print_Q();
}
#ifdef CALLOUT_DEBUG2
/*
* debugging utility
*/
static void
print_Q()
{
struct timeout_q *ptr;
IF_DEBUG(DEBUG_TIMEOUT)
for (ptr = Q; ptr; ptr = ptr->next)
logit(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
}
#endif /* CALLOUT_DEBUG2 */
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "ellemtel"
* c-basic-offset: 4
* End:
*/
|