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