From b89d27f08347006c09c11025393cca2a1ad8a4af Mon Sep 17 00:00:00 2001 From: curt Date: Tue, 30 Dec 1997 04:19:22 +0000 Subject: [PATCH] Initial revision. --- Time/Makefile | 8 +- Time/event.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++++++ Time/event.h | 63 ++++++++++ 3 files changed, 399 insertions(+), 1 deletion(-) create mode 100644 Time/event.c create mode 100644 Time/event.h diff --git a/Time/Makefile b/Time/Makefile index 88de7e487..7ed2b350e 100644 --- a/Time/Makefile +++ b/Time/Makefile @@ -26,7 +26,7 @@ TARGET = libTime.a -CFILES = fg_time.c fg_timer.c sunpos.c +CFILES = event.c fg_time.c fg_timer.c sunpos.c OFILES = $(CFILES:.c=.o) @@ -56,6 +56,9 @@ clean: include depend +event.o: + $(CC) $(CFLAGS) -c event.c -o $@ + fg_time.o: $(CC) $(CFLAGS) -c fg_time.c -o $@ @@ -68,6 +71,9 @@ sunpos.o: #--------------------------------------------------------------------------- # $Log$ +# Revision 1.14 1997/12/30 04:19:22 curt +# Initial revision. +# # Revision 1.13 1997/09/22 14:44:22 curt # Continuing to try to align stars correctly. # diff --git a/Time/event.c b/Time/event.c new file mode 100644 index 000000000..48fa97320 --- /dev/null +++ b/Time/event.c @@ -0,0 +1,329 @@ +/************************************************************************** + * 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) + **************************************************************************/ + + +#include +#include + +#ifdef USE_FTIME +# include /* for ftime() and struct timeb */ +#else +# include /* for get/setitimer, gettimeofday, struct timeval */ +#endif USE_FTIME + + +#include "event.h" + + +#define MAX_EVENTS 100 /* size of event table */ +#define MAX_RUN_QUEUE 100 /* size of run queue */ + + +struct fgEVENT { + char description[256]; + + void (*event)(); /* pointer to function */ + int status; /* status flag */ + + long interval; /* interval in ms between each iteration of this event */ + +#ifdef USE_FTIME + struct timeb last_run; /* absolute time for last run */ + struct timeb current; /* current time */ + struct timeb next_run; /* absolute time for next run */ +#else + struct timeval last_run; /* absolute time for last run */ + struct timeval current; /* current time */ + struct timeval next_run; /* absolute time for next run */ + struct timezone tz; +#endif /* USE_FTIME */ + + 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 */ +void initq() { + queue_front = queue_end = 0; +} + + +/* return queue empty status */ +int emptyq() { + if ( queue_front == queue_end ) { + return(1); + } else { + return(0); + } +} + + +/* return queue full status */ +int fullq() { + 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 */ +int popq() { + int ptr; + + if ( !emptyq() ) { + ptr = queue[queue_front]; + /* printf("Popped position %d = %d\n", queue_front, ptr); */ + queue_front = (queue_front + 1) % MAX_RUN_QUEUE; + return(ptr); + } else { + printf("PANIC: RUN QUEUE IS EMPTY!!!\n"); + exit(0); + } +} + + +/* run a specified event */ +void fgEventRun(int ptr) { + struct fgEVENT *e; + long duration; + + e = &events[ptr]; + + /* record starting time */ +#ifdef USE_FTIME + ftime(&e->last_run); +#else + gettimeofday(&e->last_run, &e->tz); +#endif /* USE_FTIME */ + + /* 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 */ +#ifdef USE_FTIME + ftime(&e->current); + duration = 1000 * (e->current.time - e->last_run.time) + + (e->current.millitm - e->last_run.millitm); +#else + gettimeofday(&e->current, &e->tz); + duration = 1000000 * (e->current.tv_sec - e->last_run.tv_sec) + + (e->current.tv_usec - e->last_run.tv_usec); + duration /= 1000; /* convert back to milleseconds */ +#endif /* USE_FTIME */ + + 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 */ +#ifdef USE_FTIME + e->next_run.time = e->last_run.time + + (e->last_run.millitm + e->interval) / 1000; + e->next_run.millitm = (e->last_run.millitm + e->interval) % 1000; +#else + e->next_run.tv_sec = e->last_run.tv_sec + + (e->last_run.tv_usec + e->interval * 1000) / 1000000; + e->next_run.tv_usec = (e->last_run.tv_usec + e->interval * 1000) % 1000000; +#endif /* USE_FTIME */ + +} + + +/* Initialize the scheduling subsystem */ +void fgEventInit() { + event_ptr = 0; + initq(); +} + + +/* Register an event with the scheduler, returns a pointer into the + * event table */ +int fgEventRegister(char *desc, void (*event)(), int status, int interval) { + struct fgEVENT *e; + + e = &events[event_ptr]; + + 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 */ +void fgEventUpdate() { +} + + +/* Delete a scheduled event */ +void fgEventDelete() { +} + + +/* Temporarily suspend scheduling of an event */ +void fgEventSuspend() { +} + + +/* Resume scheduling and event */ +void fgEventResume() { +} + + +/* Dump scheduling stats */ +void fgEventPrintStats() { + int i; + + printf("Event Stats\n"); + + for ( i = 0; i < event_ptr; i++ ) { + printf(" %s cum=%d min=%d max=%d count=%d ave=%.2f\n", + events[i].description, events[i].cum_time, events[i].min_time, + events[i].max_time, events[i].count, + events[i].cum_time / (double)events[i].count); + } +} + + +/* Add pending jobs to the run queue and run the job at the front of + * the queue */ +void fgEventProcess() { +#ifdef USE_FTIME + struct timeb current; +#else + struct timeval current; + struct timezone tz; +#endif /* USE_FTIME */ + int i; + + /* printf("Processing events\n"); */ + + /* get the current time */ +#ifdef USE_FTIME + ftime(¤t); +#else + gettimeofday(¤t, &tz); +#endif /* USE_FTIME */ + + /* 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 ) { +#ifdef USE_FTIME + if ( current.time > events[i].next_run.time ) { + addq(i); + } else if ( (current.time == events[i].next_run.time) && + (current.millitm >= events[i].next_run.millitm) ) { + addq(i); + } +#else + if ( current.tv_sec > events[i].next_run.tv_sec ) { + addq(i); + } else if ( (current.tv_sec == events[i].next_run.tv_sec) && + (current.tv_usec >= events[i].next_run.tv_usec) ) { + addq(i); + } + +#endif /* USE_FTIME */ + } + } + + /* 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$ +/* Revision 1.1 1997/12/30 04:19:22 curt +/* Initial revision. +/* + */ diff --git a/Time/event.h b/Time/event.h new file mode 100644 index 000000000..b8853c61a --- /dev/null +++ b/Time/event.h @@ -0,0 +1,63 @@ +/************************************************************************** + * event.h -- 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) + **************************************************************************/ + + +#define FG_EVENT_SUSP 0 +#define FG_EVENT_READY 1 +#define FG_EVENT_QUEUED 2 + + +/* Initialize the scheduling subsystem */ +void fgEventInit(); + +/* Register an event with the scheduler, returns a pointer into the + * event table */ +int fgEventRegister(char *desc, void (*event)(), int status, int interval); + +/* Update the scheduling parameters for an event */ +void fgEventUpdate(); + +/* Delete a scheduled event */ +void fgEventDelete(); + +/* Temporarily suspend scheduling of an event */ +void fgEventSuspend(); + +/* Resume scheduling and event */ +void fgEventResume(); + +/* Dump scheduling stats */ +void fgEventPrintStats(); + +/* Add pending jobs to the run queue and run the job at the front of + * the queue */ +void fgEventProcess(); + + +/* $Log$ +/* Revision 1.1 1997/12/30 04:19:22 curt +/* Initial revision. +/* + */