File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / trafshow / events.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:55:18 2012 UTC (12 years, 4 months ago) by misho
Branches: trafshow, MAIN
CVS tags: v5_2_3p0, v5_2_3, HEAD
trafshow

    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 = &gap;
  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>