Annotation of embedaddon/pimd/callout.c, revision 1.1
1.1 ! misho 1: /*
! 2: * The mrouted program is covered by the license in the accompanying file
! 3: * named "LICENSE.mrouted". Use of the mrouted program represents acceptance
! 4: * of the terms and conditions listed in that file.
! 5: *
! 6: * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
! 7: * Leland Stanford Junior University.
! 8: *
! 9: *
! 10: * callout.c,v 3.8.4.5 1997/05/16 20:18:25 fenner Exp
! 11: */
! 12:
! 13: #include "defs.h"
! 14:
! 15: /* the code below implements a callout queue */
! 16: static int id = 0;
! 17: static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */
! 18:
! 19: struct timeout_q {
! 20: struct timeout_q *next; /* next event */
! 21: int id;
! 22: cfunc_t func; /* function to call */
! 23: void *data; /* func's data */
! 24: int time; /* time offset to next event*/
! 25: };
! 26:
! 27: #if 0
! 28: #define CALLOUT_DEBUG 1
! 29: #define CALLOUT_DEBUG2 1
! 30: #endif /* 0 */
! 31: #ifdef CALLOUT_DEBUG2
! 32: static void print_Q((void);
! 33: #else
! 34: #define print_Q()
! 35: #endif
! 36:
! 37: void
! 38: callout_init()
! 39: {
! 40: Q = (struct timeout_q *) 0;
! 41: }
! 42:
! 43: void
! 44: free_all_callouts()
! 45: {
! 46: struct timeout_q *p;
! 47:
! 48: while (Q) {
! 49: p = Q;
! 50: Q = Q->next;
! 51: free(p);
! 52: }
! 53: }
! 54:
! 55:
! 56: /*
! 57: * elapsed_time seconds have passed; perform all the events that should
! 58: * happen.
! 59: */
! 60: void
! 61: age_callout_queue(elapsed_time)
! 62: int elapsed_time;
! 63: {
! 64: struct timeout_q *ptr, *expQ;
! 65:
! 66: #ifdef CALLOUT_DEBUG
! 67: IF_DEBUG(DEBUG_TIMEOUT)
! 68: logit(LOG_DEBUG, 0, "aging queue (elapsed time %d):", elapsed_time);
! 69: print_Q();
! 70: #endif
! 71:
! 72: expQ = Q;
! 73: ptr = NULL;
! 74:
! 75: while (Q) {
! 76: if (Q->time > elapsed_time) {
! 77: Q->time -= elapsed_time;
! 78: if (ptr) {
! 79: ptr->next = NULL;
! 80: break;
! 81: }
! 82: return;
! 83: } else {
! 84: elapsed_time -= Q->time;
! 85: ptr = Q;
! 86: Q = Q->next;
! 87: }
! 88: }
! 89:
! 90: /* handle queue of expired timers */
! 91: while (expQ) {
! 92: ptr = expQ;
! 93: if (ptr->func)
! 94: ptr->func(ptr->data);
! 95: expQ = expQ->next;
! 96: free(ptr);
! 97: }
! 98: }
! 99:
! 100: /*
! 101: * Return in how many seconds age_callout_queue() would like to be called.
! 102: * Return -1 if there are no events pending.
! 103: */
! 104: int
! 105: timer_nextTimer()
! 106: {
! 107: if (Q) {
! 108: if (Q->time < 0) {
! 109: logit(LOG_WARNING, 0, "timer_nextTimer top of queue says %d",
! 110: Q->time);
! 111: return 0;
! 112: }
! 113: return Q->time;
! 114: }
! 115: return -1;
! 116: }
! 117:
! 118: /*
! 119: * sets the timer
! 120: */
! 121: int
! 122: timer_setTimer(delay, action, data)
! 123: int delay; /* number of units for timeout */
! 124: cfunc_t action; /* function to be called on timeout */
! 125: void *data; /* what to call the timeout function with */
! 126: {
! 127: struct timeout_q *ptr, *node, *prev;
! 128:
! 129: #ifdef CALLOUT_DEBUG
! 130: IF_DEBUG(DEBUG_TIMEOUT)
! 131: logit(LOG_DEBUG, 0, "setting timer:");
! 132: print_Q();
! 133: #endif
! 134:
! 135: /* create a node */
! 136: node = (struct timeout_q *)calloc(1, sizeof(struct timeout_q));
! 137: if (!node) {
! 138: logit(LOG_ERR, 0, "Failed calloc() in timer_settimer\n");
! 139: return -1;
! 140: }
! 141: node->func = action;
! 142: node->data = data;
! 143: node->time = delay;
! 144: node->next = 0;
! 145: node->id = ++id;
! 146:
! 147: prev = ptr = Q;
! 148:
! 149: /* insert node in the queue */
! 150:
! 151: /* if the queue is empty, insert the node and return */
! 152: if (!Q)
! 153: Q = node;
! 154: else {
! 155: /* chase the pointer looking for the right place */
! 156: while (ptr) {
! 157:
! 158: if (delay < ptr->time) {
! 159: /* right place */
! 160:
! 161: node->next = ptr;
! 162: if (ptr == Q)
! 163: Q = node;
! 164: else
! 165: prev->next = node;
! 166: ptr->time -= node->time;
! 167: print_Q();
! 168: return node->id;
! 169: } else {
! 170: /* keep moving */
! 171:
! 172: delay -= ptr->time; node->time = delay;
! 173: prev = ptr;
! 174: ptr = ptr->next;
! 175: }
! 176: }
! 177: prev->next = node;
! 178: }
! 179: print_Q();
! 180: return node->id;
! 181: }
! 182:
! 183: /* returns the time until the timer is scheduled */
! 184: int
! 185: timer_leftTimer(timer_id)
! 186: int timer_id;
! 187: {
! 188: struct timeout_q *ptr;
! 189: int left = 0;
! 190:
! 191: if (!timer_id)
! 192: return -1;
! 193:
! 194: for (ptr = Q; ptr; ptr = ptr->next) {
! 195: left += ptr->time;
! 196: if (ptr->id == timer_id)
! 197: return left;
! 198: }
! 199: return -1;
! 200: }
! 201:
! 202: /* clears the associated timer */
! 203: void
! 204: timer_clearTimer(timer_id)
! 205: int timer_id;
! 206: {
! 207: struct timeout_q *ptr, *prev;
! 208:
! 209: if (!timer_id)
! 210: return;
! 211:
! 212: prev = ptr = Q;
! 213:
! 214: /*
! 215: * find the right node, delete it. the subsequent node's time
! 216: * gets bumped up
! 217: */
! 218:
! 219: print_Q();
! 220: while (ptr) {
! 221: if (ptr->id == timer_id) {
! 222: /* got the right node */
! 223:
! 224: /* unlink it from the queue */
! 225: if (ptr == Q)
! 226: Q = Q->next;
! 227: else
! 228: prev->next = ptr->next;
! 229:
! 230: /* increment next node if any */
! 231: if (ptr->next != 0)
! 232: (ptr->next)->time += ptr->time;
! 233:
! 234: if (ptr->data)
! 235: free(ptr->data);
! 236: free(ptr);
! 237: print_Q();
! 238: return;
! 239: }
! 240: prev = ptr;
! 241: ptr = ptr->next;
! 242: }
! 243: print_Q();
! 244: }
! 245:
! 246: #ifdef CALLOUT_DEBUG2
! 247: /*
! 248: * debugging utility
! 249: */
! 250: static void
! 251: print_Q()
! 252: {
! 253: struct timeout_q *ptr;
! 254:
! 255: IF_DEBUG(DEBUG_TIMEOUT)
! 256: for (ptr = Q; ptr; ptr = ptr->next)
! 257: logit(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
! 258: }
! 259: #endif /* CALLOUT_DEBUG2 */
! 260:
! 261: /**
! 262: * Local Variables:
! 263: * version-control: t
! 264: * indent-tabs-mode: t
! 265: * c-file-style: "ellemtel"
! 266: * c-basic-offset: 4
! 267: * End:
! 268: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>