Annotation of embedaddon/pimdd/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: #ifdef CALLOUT_DEBUG
! 28: static void print_Q __P((void));
! 29: #else
! 30: #define print_Q()
! 31: #endif
! 32:
! 33: void
! 34: callout_init()
! 35: {
! 36: Q = (struct timeout_q *) 0;
! 37: }
! 38:
! 39: void
! 40: free_all_callouts()
! 41: {
! 42: struct timeout_q *p;
! 43:
! 44: while (Q) {
! 45: p = Q;
! 46: Q = Q->next;
! 47: free(p);
! 48: }
! 49: }
! 50:
! 51:
! 52: /*
! 53: * elapsed_time seconds have passed; perform all the events that should
! 54: * happen.
! 55: */
! 56: void
! 57: age_callout_queue(elapsed_time)
! 58: int elapsed_time;
! 59: {
! 60: struct timeout_q *ptr, *expQ;
! 61:
! 62: #ifdef CALLOUT_DEBUG
! 63: IF_DEBUG(DEBUG_TIMEOUT)
! 64: log(LOG_DEBUG, 0, "aging queue (elapsed time %d):", elapsed_time);
! 65: print_Q();
! 66: #endif
! 67:
! 68: expQ = Q;
! 69: ptr = NULL;
! 70:
! 71: while (Q) {
! 72: if (Q->time > elapsed_time) {
! 73: Q->time -= elapsed_time;
! 74: if (ptr) {
! 75: ptr->next = NULL;
! 76: break;
! 77: }
! 78: return;
! 79: } else {
! 80: elapsed_time -= Q->time;
! 81: ptr = Q;
! 82: Q = Q->next;
! 83: }
! 84: }
! 85:
! 86: /* handle queue of expired timers */
! 87: while (expQ) {
! 88: ptr = expQ;
! 89: if (ptr->func)
! 90: ptr->func(ptr->data);
! 91: expQ = expQ->next;
! 92: free(ptr);
! 93: }
! 94: }
! 95:
! 96: /*
! 97: * Return in how many seconds age_callout_queue() would like to be called.
! 98: * Return -1 if there are no events pending.
! 99: */
! 100: int
! 101: timer_nextTimer()
! 102: {
! 103: if (Q) {
! 104: if (Q->time < 0) {
! 105: log(LOG_WARNING, 0, "timer_nextTimer top of queue says %d",
! 106: Q->time);
! 107: return 0;
! 108: }
! 109: return Q->time;
! 110: }
! 111: return -1;
! 112: }
! 113:
! 114: /*
! 115: * sets the timer
! 116: */
! 117: int
! 118: timer_setTimer(delay, action, data)
! 119: int delay; /* number of units for timeout */
! 120: cfunc_t action; /* function to be called on timeout */
! 121: void *data; /* what to call the timeout function with */
! 122: {
! 123: struct timeout_q *ptr, *node, *prev;
! 124:
! 125: #ifdef CALLOUT_DEBUG
! 126: IF_DEBUG(DEBUG_TIMEOUT)
! 127: log(LOG_DEBUG, 0, "setting timer:");
! 128: print_Q();
! 129: #endif
! 130:
! 131: /* create a node */
! 132: node = (struct timeout_q *)malloc(sizeof(struct timeout_q));
! 133: if (node == 0) {
! 134: log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
! 135: return -1;
! 136: }
! 137: node->func = action;
! 138: node->data = data;
! 139: node->time = delay;
! 140: node->next = 0;
! 141: node->id = ++id;
! 142:
! 143: prev = ptr = Q;
! 144:
! 145: /* insert node in the queue */
! 146:
! 147: /* if the queue is empty, insert the node and return */
! 148: if (!Q)
! 149: Q = node;
! 150: else {
! 151: /* chase the pointer looking for the right place */
! 152: while (ptr) {
! 153:
! 154: if (delay < ptr->time) {
! 155: /* right place */
! 156:
! 157: node->next = ptr;
! 158: if (ptr == Q)
! 159: Q = node;
! 160: else
! 161: prev->next = node;
! 162: ptr->time -= node->time;
! 163: return node->id;
! 164: } else {
! 165: /* keep moving */
! 166:
! 167: delay -= ptr->time; node->time = delay;
! 168: prev = ptr;
! 169: ptr = ptr->next;
! 170: }
! 171: }
! 172: prev->next = node;
! 173: }
! 174: return node->id;
! 175: }
! 176:
! 177: /* returns the time until the timer is scheduled */
! 178: int
! 179: timer_leftTimer(timer_id)
! 180: int timer_id;
! 181: {
! 182: struct timeout_q *ptr;
! 183: int left = 0;
! 184:
! 185: if (!timer_id)
! 186: return -1;
! 187:
! 188: for (ptr = Q; ptr; ptr = ptr->next) {
! 189: left += ptr->time;
! 190: if (ptr->id == timer_id)
! 191: return left;
! 192: }
! 193: return -1;
! 194: }
! 195:
! 196: /* clears the associated timer */
! 197: void
! 198: timer_clearTimer(timer_id)
! 199: int timer_id;
! 200: {
! 201: struct timeout_q *ptr, *prev;
! 202:
! 203: if (!timer_id)
! 204: return;
! 205:
! 206: prev = ptr = Q;
! 207:
! 208: /*
! 209: * find the right node, delete it. the subsequent node's time
! 210: * gets bumped up
! 211: */
! 212:
! 213: while (ptr) {
! 214: if (ptr->id == timer_id) {
! 215: /* got the right node */
! 216:
! 217: /* unlink it from the queue */
! 218: if (ptr == Q)
! 219: Q = Q->next;
! 220: else
! 221: prev->next = ptr->next;
! 222:
! 223: /* increment next node if any */
! 224: if (ptr->next != 0)
! 225: (ptr->next)->time += ptr->time;
! 226:
! 227: if (ptr->data)
! 228: free(ptr->data);
! 229: free(ptr);
! 230: return;
! 231: }
! 232: prev = ptr;
! 233: ptr = ptr->next;
! 234: }
! 235: }
! 236:
! 237: #ifdef CALLOUT_DEBUG
! 238: /*
! 239: * debugging utility
! 240: */
! 241: static void
! 242: print_Q()
! 243: {
! 244: struct timeout_q *ptr;
! 245:
! 246: IF_DEBUG(DEBUG_TIMEOUT)
! 247: for (ptr = Q; ptr; ptr = ptr->next)
! 248: log(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
! 249: }
! 250: #endif /* CALLOUT_DEBUG */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>