1 /**************************************************************************
2 * event.c -- Flight Gear periodic event scheduler
4 * Written by Curtis Olson, started December 1997.
6 * Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * (Log is kept at end of this file)
24 **************************************************************************/
32 # include <sys/timeb.h> /* for ftime() and struct timeb */
33 #elif defined(__MWERKS__)
34 # include <windows.h> /* For Metrowerks environment */
35 # include <winbase.h> /* There is no ANSI/MSL time function that */
36 /* contains milliseconds */
38 # include <sys/time.h> /* for get/setitimer, gettimeofday, struct timeval */
39 #endif /* USE_FTIME */
42 #include <Time/event.h>
45 #define MAX_EVENTS 100 /* size of event table */
46 #define MAX_RUN_QUEUE 100 /* size of run queue */
50 char description[256];
52 void (*event)( void ); /* pointer to function */
53 int status; /* status flag */
55 long interval; /* interval in ms between each iteration of this event */
58 struct timeb last_run; /* absolute time for last run */
59 struct timeb current; /* current time */
60 struct timeb next_run; /* absolute time for next run */
61 #elif defined(__MWERKS__)
62 SYSTEMTIME last_run; /* A type defed structure that holds */
63 SYSTEMTIME current; /* the only structure that contains */
64 SYSTEMTIME next_run; /* millisecond timing */
66 struct timeval last_run; /* absolute time for last run */
67 struct timeval current; /* current time */
68 struct timeval next_run; /* absolute time for next run */
70 #endif /* USE_FTIME */
72 long cum_time; /* cumulative processor time of this event */
73 long min_time; /* time of quickest execution */
74 long max_time; /* time of slowest execution */
75 long count; /* number of times executed */
80 struct fgEVENT events[MAX_EVENTS];
85 int queue[MAX_RUN_QUEUE];
90 /* initialize the run queue */
92 queue_front = queue_end = 0;
96 /* return queue empty status */
98 if ( queue_front == queue_end ) {
106 /* return queue full status */
108 if ( (queue_end + 1) % MAX_RUN_QUEUE == queue_front ) {
116 /* add a member to the back of the queue */
119 queue[queue_end] = ptr;
120 events[ptr].status = FG_EVENT_QUEUED;
122 queue_end = (queue_end + 1) % MAX_RUN_QUEUE;
124 printf("RUN QUEUE FULL!!!\n");
127 /* printf("Queued function %d (%d %d)\n", ptr, queue_front, queue_end); */
131 /* remove a member from the front of the queue */
136 printf("PANIC: RUN QUEUE IS EMPTY!!!\n");
139 ptr = queue[queue_front];
140 /* printf("Popped position %d = %d\n", queue_front, ptr); */
141 queue_front = (queue_front + 1) % MAX_RUN_QUEUE;
148 /* run a specified event */
149 void fgEventRun(int ptr) {
155 printf("Running %s\n", e->description);
157 /* record starting time */
160 #elif defined(__MWERKS__)
161 GetLocalTime(&e->last_run);
163 gettimeofday(&e->last_run, &e->tz);
164 #endif /* USE_FTIME */
169 /* increment the counter for this event */
172 /* update the event status */
173 e->status = FG_EVENT_READY;
175 /* calculate duration and stats */
178 duration = 1000 * (e->current.time - e->last_run.time) +
179 (e->current.millitm - e->last_run.millitm);
180 #elif defined(__MWERKS__)
181 GetLocalTime(&e->current);
182 duration = 1000 * (e->current.wSecond - e->last_run.wSecond) +
183 (e->current.wMilliseconds - e->last_run.wMilliseconds);
185 gettimeofday(&e->current, &e->tz);
186 duration = 1000000 * (e->current.tv_sec - e->last_run.tv_sec) +
187 (e->current.tv_usec - e->last_run.tv_usec);
188 duration /= 1000; /* convert back to milleseconds */
189 #endif /* USE_FTIME */
191 e->cum_time += duration;
193 if ( duration < e->min_time ) {
194 e->min_time = duration;
197 if ( duration > e->max_time ) {
198 e->max_time = duration;
201 /* determine the next absolute run time */
203 e->next_run.time = e->last_run.time +
204 (e->last_run.millitm + e->interval) / 1000;
205 e->next_run.millitm = (e->last_run.millitm + e->interval) % 1000;
206 #elif defined(__MWERKS__)
207 e->next_run.wSecond = e->last_run.wSecond +
208 (e->last_run.wMilliseconds + e->interval) / 1000;
209 e->next_run.wMilliseconds =
210 (e->last_run.wMilliseconds + e->interval) % 1000;
212 e->next_run.tv_sec = e->last_run.tv_sec +
213 (e->last_run.tv_usec + e->interval * 1000) / 1000000;
214 e->next_run.tv_usec = (e->last_run.tv_usec + e->interval * 1000) % 1000000;
215 #endif /* USE_FTIME */
219 /* Initialize the scheduling subsystem */
220 void fgEventInit( void ) {
221 printf("Initializing event manager\n");
227 /* Register an event with the scheduler, returns a pointer into the
229 int fgEventRegister(char *desc, void (*event)( void ), int status,
234 e = &events[event_ptr];
236 printf("Registering event: %s\n", desc);
238 if ( strlen(desc) < 256 ) {
239 strcpy(e->description, desc);
241 strncpy(e->description, desc, 255);
242 e->description[255] = '\0';
247 e->interval = interval;
250 e->min_time = 100000;
254 /* Actually run the event */
255 fgEventRun(event_ptr);
259 return(event_ptr - 1);
263 /* Update the scheduling parameters for an event */
264 void fgEventUpdate( void ) {
268 /* Delete a scheduled event */
269 void fgEventDelete( void ) {
273 /* Temporarily suspend scheduling of an event */
274 void fgEventSuspend( void ) {
278 /* Resume scheduling and event */
279 void fgEventResume( void ) {
283 /* Dump scheduling stats */
284 void fgEventPrintStats( void ) {
287 if ( event_ptr > 0 ) {
289 printf("Event Stats\n");
290 printf("-----------\n");
292 for ( i = 0; i < event_ptr; i++ ) {
293 printf(" %-20s int=%.2fs cum=%ld min=%ld max=%ld count=%ld ave=%.2f\n",
294 events[i].description,
295 events[i].interval / 1000.0,
297 events[i].min_time, events[i].max_time, events[i].count,
298 events[i].cum_time / (double)events[i].count);
305 /* Add pending jobs to the run queue and run the job at the front of
307 void fgEventProcess( void ) {
309 struct timeb current;
310 #elif defined(__MWERKS__)
311 SYSTEMTIME current; /* current time */
313 struct timeval current;
315 #endif /* USE_FTIME */
318 printf("Processing events\n");
320 /* get the current time */
323 #elif defined(__MWERKS__)
324 GetLocalTime(¤t);
326 gettimeofday(¤t, &tz);
327 #endif /* USE_FTIME */
329 /* printf("Checking if anything is ready to move to the run queue\n"); */
331 /* see if anything else is ready to be placed on the run queue */
332 for ( i = 0; i < event_ptr; i++ ) {
333 if ( events[i].status == FG_EVENT_READY ) {
335 if ( current.time > events[i].next_run.time ) {
337 } else if ( (current.time == events[i].next_run.time) &&
338 (current.millitm >= events[i].next_run.millitm) ) {
341 #elif defined(__MWERKS__)
342 if (current.wSecond > events[i].next_run.wSecond) {
345 else if ( (current.wSecond == events[i].next_run.wSecond) &&
346 (current.wMilliseconds >=
347 events[i].next_run.wMilliseconds)) {
351 if ( current.tv_sec > events[i].next_run.tv_sec ) {
353 } else if ( (current.tv_sec == events[i].next_run.tv_sec) &&
354 (current.tv_usec >= events[i].next_run.tv_usec) ) {
358 #endif /* USE_FTIME */
362 /* Checking to see if there is anything on the run queue */
363 /* printf("Checking to see if there is anything on the run queue\n"); */
365 /* printf("Yep, running it\n"); */
373 /* Revision 1.9 1998/01/31 00:43:44 curt
374 /* Added MetroWorks patches from Carmen Volpe.
376 * Revision 1.8 1998/01/27 00:48:05 curt
377 * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
378 * system and commandline/config file processing code.
380 * Revision 1.7 1998/01/19 19:27:19 curt
381 * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
382 * This should simplify things tremendously.
384 * Revision 1.6 1998/01/19 18:40:39 curt
385 * Tons of little changes to clean up the code and to remove fatal errors
386 * when building with the c++ compiler.
388 * Revision 1.5 1998/01/06 01:20:27 curt
389 * Tweaks to help building with MSVC++
391 * Revision 1.4 1997/12/31 17:46:50 curt
392 * Tweaked fg_time.c to be able to use ftime() instead of gettimeofday()
394 * Revision 1.3 1997/12/30 22:22:42 curt
395 * Further integration of event manager.
397 * Revision 1.2 1997/12/30 20:47:58 curt
398 * Integrated new event manager with subsystem initializations.
400 * Revision 1.1 1997/12/30 04:19:22 curt