Annotation of embedaddon/trafshow/events.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 1999-2003 Rinet Corp., Novosibirsk, Russia
! 3: *
! 4: * Redistribution and use in source forms, with and without modification,
! 5: * are permitted provided that this entire comment appears intact.
! 6: *
! 7: * THIS SOURCE CODE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
! 8: */
! 9:
! 10: #ifdef HAVE_CONFIG_H
! 11: #include <config.h>
! 12: #endif
! 13:
! 14: #include <sys/types.h>
! 15: #include <sys/time.h>
! 16: #include <time.h>
! 17: #include <stdlib.h>
! 18: #include <string.h>
! 19:
! 20: #include "events.h"
! 21:
! 22: #define dprintf(x) /* nope */
! 23:
! 24: static EVENT *first_event = 0; /* first system event in table */
! 25:
! 26: /*
! 27: * Subtract 2 timeval structs: out = out - in. Out result always greater 0.
! 28: */
! 29: void
! 30: tv_sub(out, in)
! 31: struct timeval *out;
! 32: const struct timeval *in;
! 33: {
! 34: if (out->tv_sec > in->tv_sec) {
! 35: out->tv_sec -= in->tv_sec;
! 36: if (out->tv_usec >= in->tv_usec) {
! 37: out->tv_usec -= in->tv_usec;
! 38: } else {
! 39: out->tv_sec--;
! 40: out->tv_usec += 1000000L - in->tv_usec;
! 41: }
! 42: } else if (out->tv_sec == in->tv_sec) {
! 43: out->tv_sec = 0L;
! 44: out->tv_usec -= in->tv_usec;
! 45: if (out->tv_usec < 1)
! 46: out->tv_usec = 100L; /* not zero anyway */
! 47: } else {
! 48: out->tv_sec = 0L;
! 49: out->tv_usec = 100L; /* not zero anyway */
! 50: }
! 51: }
! 52:
! 53: void
! 54: tv_add(out, in)
! 55: struct timeval *out;
! 56: const struct timeval *in;
! 57: {
! 58: out->tv_sec += in->tv_sec;
! 59: out->tv_usec += in->tv_usec;
! 60: if (out->tv_usec >= 1000000L) {
! 61: out->tv_sec++;
! 62: out->tv_usec -= 1000000L;
! 63: }
! 64: }
! 65:
! 66: /*
! 67: * Round timeval to seconds.
! 68: */
! 69: u_long
! 70: tv_round(in)
! 71: const struct timeval *in;
! 72: {
! 73: u_long sec = in->tv_sec;
! 74: if (in->tv_usec >= 500000L)
! 75: sec++;
! 76: return sec;
! 77: }
! 78:
! 79: /*
! 80: * Return time difference in milliseconds.
! 81: */
! 82: u_long
! 83: tv_diff(tvp1, tvp2)
! 84: const struct timeval *tvp1, *tvp2;
! 85: {
! 86: struct timeval diff;
! 87:
! 88: if (!timerisset(tvp1) || !timerisset(tvp2))
! 89: return 0;
! 90:
! 91: if (timercmp(tvp1, tvp2, >)) {
! 92: diff = *tvp1;
! 93: tv_sub(&diff, tvp2);
! 94: } else {
! 95: diff = *tvp2;
! 96: tv_sub(&diff, tvp1);
! 97: }
! 98: return (diff.tv_sec * 1000 + diff.tv_usec / 1000);
! 99: }
! 100:
! 101: /*
! 102: * Shift the time to be sharp at (12am + N * period), local time.
! 103: */
! 104: void
! 105: tv_sharp(tvp, period)
! 106: struct timeval *tvp;
! 107: int period;
! 108: {
! 109: time_t defect;
! 110: struct tm *tm;
! 111:
! 112: if (!tvp) return;
! 113:
! 114: tm = localtime((time_t *)&tvp->tv_sec);
! 115: defect = tm->tm_sec + 60 * tm->tm_min + 3600 * tm->tm_hour;
! 116: defect %= period;
! 117: period -= defect;
! 118: if (period < 1) period = 1;
! 119: tvp->tv_sec += period;
! 120: tvp->tv_usec = (long)random() % 1000000L;
! 121: }
! 122:
! 123: /*
! 124: * Execute pending event and schedule the next nearest.
! 125: */
! 126: int
! 127: select_event(tvp)
! 128: struct timeval *tvp;
! 129: {
! 130: EVENT *ep, *next_event;
! 131: struct timeval now, gap, earliest;
! 132:
! 133: gettimeofday(&now, 0);
! 134: gap.tv_sec = 0;
! 135: gap.tv_usec = 1000L; /* 0.001sec grip */
! 136: tv_add(&gap, &now);
! 137: again:
! 138: next_event = 0;
! 139: timerclear(&earliest);
! 140:
! 141: for (ep = first_event; ep; ep = ep->next) {
! 142: /* skip over the empty slots */
! 143: if (!ep->func) continue;
! 144:
! 145: if (timercmp(&gap, &ep->tv, >)) {
! 146: void (*func)() = ep->func;
! 147: ep->func = 0; /* free event slot before */
! 148:
! 149: dprintf(("-call_event(%p/%p)", func, ep->arg));
! 150:
! 151: (*func)(ep->arg); /* call event function */
! 152: goto again;
! 153:
! 154: } else if (!timerisset(&earliest) ||
! 155: timercmp(&ep->tv, &earliest, <)) {
! 156: earliest = ep->tv;
! 157: next_event = ep;
! 158: }
! 159: }
! 160: if (!next_event) { /* no more awaiting events */
! 161:
! 162: dprintf(("select_event: no timeout"));
! 163:
! 164: return 1; /* timeout undefined */
! 165: }
! 166: if (tvp) {
! 167: tv_sub(&earliest, &now);
! 168: *tvp = earliest;
! 169:
! 170: dprintf(("=wait_event(%p/%p): timeout=%u.%03d",
! 171: next_event->func, next_event->arg,
! 172: (unsigned)tvp->tv_sec, (int)(tvp->tv_usec / 1000)));
! 173: }
! 174: return 0; /* timeout defined */
! 175: }
! 176:
! 177: /*
! 178: * Add the new system event to be executed at the given time.
! 179: */
! 180: int
! 181: add_event(tvp, func, arg)
! 182: struct timeval *tvp;
! 183: void (*func)(void *);
! 184: void *arg;
! 185: {
! 186: EVENT *ep, *prev = 0, *next = 0;
! 187: struct timeval now, gap;
! 188:
! 189: if (!tvp) {
! 190: gettimeofday(&now, 0);
! 191: gap.tv_sec = 0;
! 192: gap.tv_usec = 250000L; /* 0.25sec mean a bit later */
! 193: tv_add(&gap, &now);
! 194: tvp = ⪆
! 195: }
! 196:
! 197: /*
! 198: * The same event in queue may cause a looping! Prevent it.
! 199: */
! 200: for (ep = first_event; ep; ep = ep->next) {
! 201: if (ep->func == func && ep->arg == arg) {
! 202: ep->tv = *tvp;
! 203: dprintf(("=add_event(%p/%p): modify time", func, arg));
! 204: return 0;
! 205: }
! 206: }
! 207:
! 208: /*
! 209: * Search for first empty or last event slot.
! 210: */
! 211: for (ep = first_event; ep; ep = ep->next) {
! 212: if (!ep->func) {
! 213: next = ep->next;
! 214: break;
! 215: }
! 216: prev = ep;
! 217: }
! 218: if (!ep && (ep = (EVENT *)malloc(sizeof(EVENT))) == 0)
! 219: return -1;
! 220: memset(ep, 0, sizeof(EVENT));
! 221: ep->tv = *tvp;
! 222: ep->func = func;
! 223: ep->arg = arg;
! 224: if (next) ep->next = next;
! 225: else if (prev) prev->next = ep;
! 226: if (!first_event) first_event = ep;
! 227:
! 228: #ifdef notdef
! 229: {
! 230: char at_time[50];
! 231: strftime(at_time, sizeof(at_time), "%T",
! 232: localtime((time_t *)&ep->tv.tv_sec));
! 233: dprintf(("+add_event(%p/%p): schedule=%s.%03d",
! 234: func, arg, at_time, (int)(tvp->tv_usec / 1000)));
! 235: }
! 236: #endif
! 237: return 0;
! 238: }
! 239:
! 240: /*
! 241: * Remove system event from queue if any.
! 242: */
! 243: int
! 244: remove_event(func, arg)
! 245: void (*func)(void *);
! 246: void *arg;
! 247: {
! 248: int found = 0;
! 249: EVENT *ep;
! 250:
! 251: for (ep = first_event; ep; ep = ep->next) {
! 252: if ((!func || ep->func == func) && ep->arg == arg) {
! 253: ep->func = 0;
! 254: found++;
! 255: }
! 256: }
! 257: return found;
! 258: }
! 259:
! 260: /*
! 261: * Modify existing system event in queue for the new function argument.
! 262: */
! 263: int
! 264: change_event(func, arg, new_arg)
! 265: void (*func)(void *);
! 266: void *arg, *new_arg;
! 267: {
! 268: int found = 0;
! 269: EVENT *ep;
! 270:
! 271: for (ep = first_event; ep; ep = ep->next) {
! 272: if ((!func || ep->func == func) && ep->arg == arg) {
! 273: ep->arg = new_arg;
! 274: found++;
! 275: }
! 276: }
! 277: return found;
! 278: }
! 279:
! 280: EVENT *
! 281: find_event(func, arg)
! 282: void (*func)(void *);
! 283: void *arg;
! 284: {
! 285: EVENT *ep;
! 286:
! 287: for (ep = first_event; ep; ep = ep->next) {
! 288: if (ep->func == func && ep->arg == arg)
! 289: return ep;
! 290: }
! 291: return 0;
! 292: }
! 293:
! 294: void
! 295: free_events()
! 296: {
! 297: EVENT *ep, *next;
! 298:
! 299: ep = first_event;
! 300: while (ep) {
! 301: next = ep->next;
! 302: free(ep);
! 303: ep = next;
! 304: }
! 305: first_event = 0;
! 306: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>