1997-12-30 04:19:22 +00:00
|
|
|
/**************************************************************************
|
|
|
|
* event.c -- Flight Gear periodic event scheduler
|
|
|
|
*
|
|
|
|
* Written by Curtis Olson, started December 1997.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
* (Log is kept at end of this file)
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
1998-04-24 00:52:24 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
1998-04-03 22:12:53 +00:00
|
|
|
|
1997-12-30 04:19:22 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
1998-04-03 22:12:53 +00:00
|
|
|
#ifdef HAVE_STDLIB_H
|
|
|
|
#include <stdlib.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined( HAVE_WINDOWS_H ) && defined(__MWERKS__)
|
1998-01-31 00:42:57 +00:00
|
|
|
# include <windows.h> /* For Metrowerks environment */
|
|
|
|
# include <winbase.h> /* There is no ANSI/MSL time function that */
|
|
|
|
/* contains milliseconds */
|
1998-04-03 22:12:53 +00:00
|
|
|
#endif
|
1997-12-30 04:19:22 +00:00
|
|
|
|
1998-04-18 04:13:51 +00:00
|
|
|
#include <Debug/fg_debug.h>
|
1998-04-24 00:52:24 +00:00
|
|
|
|
|
|
|
#include "event.hxx"
|
|
|
|
#include "fg_time.hxx"
|
|
|
|
|
1997-12-30 04:19:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define MAX_EVENTS 100 /* size of event table */
|
|
|
|
#define MAX_RUN_QUEUE 100 /* size of run queue */
|
|
|
|
|
|
|
|
|
|
|
|
struct fgEVENT {
|
|
|
|
char description[256];
|
|
|
|
|
1998-01-19 18:40:15 +00:00
|
|
|
void (*event)( void ); /* pointer to function */
|
1997-12-30 04:19:22 +00:00
|
|
|
int status; /* status flag */
|
|
|
|
|
|
|
|
long interval; /* interval in ms between each iteration of this event */
|
1998-04-03 22:12:53 +00:00
|
|
|
|
|
|
|
fg_timestamp last_run;
|
|
|
|
fg_timestamp current;
|
|
|
|
fg_timestamp next_run;
|
1997-12-30 04:19:22 +00:00
|
|
|
|
|
|
|
long cum_time; /* cumulative processor time of this event */
|
|
|
|
long min_time; /* time of quickest execution */
|
|
|
|
long max_time; /* time of slowest execution */
|
|
|
|
long count; /* number of times executed */
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Event table */
|
|
|
|
struct fgEVENT events[MAX_EVENTS];
|
|
|
|
int event_ptr;
|
|
|
|
|
|
|
|
|
|
|
|
/* Run Queue */
|
|
|
|
int queue[MAX_RUN_QUEUE];
|
|
|
|
int queue_front;
|
|
|
|
int queue_end;
|
|
|
|
|
|
|
|
|
|
|
|
/* initialize the run queue */
|
1998-01-19 18:40:15 +00:00
|
|
|
void initq( void ) {
|
1997-12-30 04:19:22 +00:00
|
|
|
queue_front = queue_end = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* return queue empty status */
|
1998-01-19 18:40:15 +00:00
|
|
|
int emptyq( void ) {
|
1997-12-30 04:19:22 +00:00
|
|
|
if ( queue_front == queue_end ) {
|
|
|
|
return(1);
|
|
|
|
} else {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* return queue full status */
|
1998-01-19 18:40:15 +00:00
|
|
|
int fullq( void ) {
|
1997-12-30 04:19:22 +00:00
|
|
|
if ( (queue_end + 1) % MAX_RUN_QUEUE == queue_front ) {
|
|
|
|
return(1);
|
|
|
|
} else {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* add a member to the back of the queue */
|
|
|
|
void addq(int ptr) {
|
|
|
|
if ( !fullq() ) {
|
|
|
|
queue[queue_end] = ptr;
|
|
|
|
events[ptr].status = FG_EVENT_QUEUED;
|
|
|
|
|
|
|
|
queue_end = (queue_end + 1) % MAX_RUN_QUEUE;
|
|
|
|
} else {
|
|
|
|
printf("RUN QUEUE FULL!!!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* printf("Queued function %d (%d %d)\n", ptr, queue_front, queue_end); */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* remove a member from the front of the queue */
|
1998-01-19 18:40:15 +00:00
|
|
|
int popq( void ) {
|
1997-12-30 04:19:22 +00:00
|
|
|
int ptr;
|
|
|
|
|
1998-01-27 00:47:41 +00:00
|
|
|
if ( emptyq() ) {
|
|
|
|
printf("PANIC: RUN QUEUE IS EMPTY!!!\n");
|
|
|
|
ptr = 0;
|
|
|
|
} else {
|
1997-12-30 04:19:22 +00:00
|
|
|
ptr = queue[queue_front];
|
|
|
|
/* printf("Popped position %d = %d\n", queue_front, ptr); */
|
|
|
|
queue_front = (queue_front + 1) % MAX_RUN_QUEUE;
|
|
|
|
}
|
1998-01-27 00:47:41 +00:00
|
|
|
|
|
|
|
return(ptr);
|
1997-12-30 04:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* run a specified event */
|
|
|
|
void fgEventRun(int ptr) {
|
|
|
|
struct fgEVENT *e;
|
|
|
|
long duration;
|
|
|
|
|
|
|
|
e = &events[ptr];
|
|
|
|
|
1997-12-30 20:47:34 +00:00
|
|
|
printf("Running %s\n", e->description);
|
|
|
|
|
1997-12-30 04:19:22 +00:00
|
|
|
/* record starting time */
|
1998-04-03 22:12:53 +00:00
|
|
|
timestamp(&(e->last_run));
|
1997-12-30 04:19:22 +00:00
|
|
|
|
|
|
|
/* run the event */
|
|
|
|
(*e->event)();
|
|
|
|
|
|
|
|
/* increment the counter for this event */
|
|
|
|
e->count++;
|
|
|
|
|
|
|
|
/* update the event status */
|
|
|
|
e->status = FG_EVENT_READY;
|
|
|
|
|
|
|
|
/* calculate duration and stats */
|
1998-04-03 22:12:53 +00:00
|
|
|
timestamp(&(e->current));
|
|
|
|
duration = timediff(&(e->last_run), &(e->current));
|
1997-12-30 04:19:22 +00:00
|
|
|
|
|
|
|
e->cum_time += duration;
|
|
|
|
|
|
|
|
if ( duration < e->min_time ) {
|
|
|
|
e->min_time = duration;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( duration > e->max_time ) {
|
|
|
|
e->max_time = duration;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* determine the next absolute run time */
|
1998-04-03 22:12:53 +00:00
|
|
|
timesum(&(e->next_run), &(e->last_run), e->interval);
|
1997-12-30 04:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialize the scheduling subsystem */
|
1998-01-19 18:40:15 +00:00
|
|
|
void fgEventInit( void ) {
|
1997-12-30 20:47:34 +00:00
|
|
|
printf("Initializing event manager\n");
|
1997-12-30 04:19:22 +00:00
|
|
|
event_ptr = 0;
|
|
|
|
initq();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Register an event with the scheduler, returns a pointer into the
|
|
|
|
* event table */
|
1998-01-19 18:40:15 +00:00
|
|
|
int fgEventRegister(char *desc, void (*event)( void ), int status,
|
|
|
|
int interval)
|
|
|
|
{
|
1997-12-30 04:19:22 +00:00
|
|
|
struct fgEVENT *e;
|
|
|
|
|
|
|
|
e = &events[event_ptr];
|
|
|
|
|
1997-12-30 20:47:34 +00:00
|
|
|
printf("Registering event: %s\n", desc);
|
|
|
|
|
1997-12-30 04:19:22 +00:00
|
|
|
if ( strlen(desc) < 256 ) {
|
|
|
|
strcpy(e->description, desc);
|
|
|
|
} else {
|
|
|
|
strncpy(e->description, desc, 255);
|
|
|
|
e->description[255] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
e->event = event;
|
|
|
|
e->status = status;
|
|
|
|
e->interval = interval;
|
|
|
|
|
|
|
|
e->cum_time = 0;
|
|
|
|
e->min_time = 100000;
|
|
|
|
e->max_time = 0;
|
|
|
|
e->count = 0;
|
|
|
|
|
|
|
|
/* Actually run the event */
|
|
|
|
fgEventRun(event_ptr);
|
|
|
|
|
|
|
|
event_ptr++;
|
|
|
|
|
|
|
|
return(event_ptr - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Update the scheduling parameters for an event */
|
1998-01-19 18:40:15 +00:00
|
|
|
void fgEventUpdate( void ) {
|
1997-12-30 04:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Delete a scheduled event */
|
1998-01-19 18:40:15 +00:00
|
|
|
void fgEventDelete( void ) {
|
1997-12-30 04:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Temporarily suspend scheduling of an event */
|
1998-01-19 18:40:15 +00:00
|
|
|
void fgEventSuspend( void ) {
|
1997-12-30 04:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Resume scheduling and event */
|
1998-01-19 18:40:15 +00:00
|
|
|
void fgEventResume( void ) {
|
1997-12-30 04:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Dump scheduling stats */
|
1998-01-19 18:40:15 +00:00
|
|
|
void fgEventPrintStats( void ) {
|
1997-12-30 04:19:22 +00:00
|
|
|
int i;
|
|
|
|
|
1997-12-30 20:47:34 +00:00
|
|
|
if ( event_ptr > 0 ) {
|
|
|
|
printf("\n");
|
|
|
|
printf("Event Stats\n");
|
1997-12-30 22:22:31 +00:00
|
|
|
printf("-----------\n");
|
1997-12-30 04:19:22 +00:00
|
|
|
|
1997-12-30 20:47:34 +00:00
|
|
|
for ( i = 0; i < event_ptr; i++ ) {
|
1998-01-06 01:20:16 +00:00
|
|
|
printf(" %-20s int=%.2fs cum=%ld min=%ld max=%ld count=%ld ave=%.2f\n",
|
1997-12-30 22:22:31 +00:00
|
|
|
events[i].description,
|
|
|
|
events[i].interval / 1000.0,
|
|
|
|
events[i].cum_time,
|
1997-12-30 20:47:34 +00:00
|
|
|
events[i].min_time, events[i].max_time, events[i].count,
|
|
|
|
events[i].cum_time / (double)events[i].count);
|
|
|
|
}
|
1997-12-30 22:22:31 +00:00
|
|
|
printf("\n");
|
1997-12-30 04:19:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Add pending jobs to the run queue and run the job at the front of
|
|
|
|
* the queue */
|
1998-01-19 18:40:15 +00:00
|
|
|
void fgEventProcess( void ) {
|
1998-04-03 22:12:53 +00:00
|
|
|
fg_timestamp current;
|
1997-12-30 04:19:22 +00:00
|
|
|
int i;
|
|
|
|
|
1998-03-14 00:28:34 +00:00
|
|
|
fgPrintf(FG_EVENT, FG_DEBUG, "Processing events\n");
|
1997-12-30 04:19:22 +00:00
|
|
|
|
|
|
|
/* get the current time */
|
1998-04-03 22:12:53 +00:00
|
|
|
timestamp(¤t);
|
1997-12-30 04:19:22 +00:00
|
|
|
|
1998-04-09 18:40:13 +00:00
|
|
|
fgPrintf(FG_EVENT, FG_DEBUG, " Current timestamp = %ld\n", current.seconds);
|
|
|
|
|
1997-12-30 04:19:22 +00:00
|
|
|
/* printf("Checking if anything is ready to move to the run queue\n"); */
|
|
|
|
|
|
|
|
/* see if anything else is ready to be placed on the run queue */
|
|
|
|
for ( i = 0; i < event_ptr; i++ ) {
|
|
|
|
if ( events[i].status == FG_EVENT_READY ) {
|
1998-04-09 18:40:13 +00:00
|
|
|
fgPrintf(FG_EVENT, FG_DEBUG,
|
|
|
|
" Item %d, current %d, next run @ %ld\n",
|
|
|
|
i, current.seconds, events[i].next_run.seconds);
|
|
|
|
if ( timediff(¤t, &(events[i].next_run)) <= 0) {
|
1998-04-03 22:12:53 +00:00
|
|
|
addq(i);
|
1998-01-31 00:42:57 +00:00
|
|
|
}
|
1997-12-30 04:19:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Checking to see if there is anything on the run queue */
|
|
|
|
/* printf("Checking to see if there is anything on the run queue\n"); */
|
|
|
|
if ( !emptyq() ) {
|
|
|
|
/* printf("Yep, running it\n"); */
|
|
|
|
i = popq();
|
|
|
|
fgEventRun(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* $Log$
|
1998-04-24 00:52:24 +00:00
|
|
|
/* Revision 1.1 1998/04/24 00:52:26 curt
|
|
|
|
/* Wrapped "#include <config.h>" in "#ifdef HAVE_CONFIG_H"
|
|
|
|
/* Fog color fixes.
|
|
|
|
/* Separated out lighting calcs into their own file.
|
1997-12-30 04:19:22 +00:00
|
|
|
/*
|
1998-04-24 00:52:24 +00:00
|
|
|
* Revision 1.13 1998/04/18 04:14:08 curt
|
|
|
|
* Moved fg_debug.c to it's own library.
|
|
|
|
*
|
1998-04-18 04:13:51 +00:00
|
|
|
* Revision 1.12 1998/04/09 18:40:13 curt
|
|
|
|
* We had unified some of the platform disparate time handling code, and
|
|
|
|
* there was a bug in timesum() which calculated a new time stamp based on
|
|
|
|
* the current time stamp + offset. This hosed the periodic event processing
|
|
|
|
* logic because you'd never arrive at the time the event was scheduled for.
|
|
|
|
* Sky updates and lighting changes are handled via this event mechanism so
|
|
|
|
* they never changed ... it is fixed now.
|
|
|
|
*
|
1998-04-09 18:40:13 +00:00
|
|
|
* Revision 1.11 1998/04/03 22:12:55 curt
|
|
|
|
* Converting to Gnu autoconf system.
|
|
|
|
* Centralized time handling differences.
|
|
|
|
*
|
1998-04-03 22:12:53 +00:00
|
|
|
* Revision 1.10 1998/03/14 00:28:34 curt
|
|
|
|
* replaced a printf() with an fgPrintf().
|
|
|
|
*
|
1998-03-14 00:28:34 +00:00
|
|
|
* Revision 1.9 1998/01/31 00:43:44 curt
|
|
|
|
* Added MetroWorks patches from Carmen Volpe.
|
|
|
|
*
|
1998-01-31 00:42:57 +00:00
|
|
|
* Revision 1.8 1998/01/27 00:48:05 curt
|
|
|
|
* Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
|
|
|
|
* system and commandline/config file processing code.
|
|
|
|
*
|
1998-01-27 00:47:41 +00:00
|
|
|
* Revision 1.7 1998/01/19 19:27:19 curt
|
|
|
|
* Merged in make system changes from Bob Kuehne <rpk@sgi.com>
|
|
|
|
* This should simplify things tremendously.
|
|
|
|
*
|
1998-01-19 19:26:51 +00:00
|
|
|
* Revision 1.6 1998/01/19 18:40:39 curt
|
|
|
|
* Tons of little changes to clean up the code and to remove fatal errors
|
|
|
|
* when building with the c++ compiler.
|
|
|
|
*
|
1998-01-19 18:40:15 +00:00
|
|
|
* Revision 1.5 1998/01/06 01:20:27 curt
|
|
|
|
* Tweaks to help building with MSVC++
|
|
|
|
*
|
1998-01-06 01:20:16 +00:00
|
|
|
* Revision 1.4 1997/12/31 17:46:50 curt
|
|
|
|
* Tweaked fg_time.c to be able to use ftime() instead of gettimeofday()
|
|
|
|
*
|
1997-12-31 17:46:50 +00:00
|
|
|
* Revision 1.3 1997/12/30 22:22:42 curt
|
|
|
|
* Further integration of event manager.
|
|
|
|
*
|
1997-12-30 22:22:31 +00:00
|
|
|
* Revision 1.2 1997/12/30 20:47:58 curt
|
|
|
|
* Integrated new event manager with subsystem initializations.
|
|
|
|
*
|
1997-12-30 20:47:34 +00:00
|
|
|
* Revision 1.1 1997/12/30 04:19:22 curt
|
|
|
|
* Initial revision.
|
|
|
|
*
|
1997-12-30 04:19:22 +00:00
|
|
|
*/
|