OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [engine/] [devtimer.c] - Diff between revs 27 and 174

Only display areas with differences | Details | Blame | View Log

Rev 27 Rev 174
/*
/*
 * Copyright (c) 2000 Alex Holden <alex@linuxhacker.org>
 * Copyright (c) 2000 Alex Holden <alex@linuxhacker.org>
 *
 *
 * This file implements the device independant timer functions.
 * This file implements the device independant timer functions.
 *
 *
 * When a part of the server wishes to set a timer, it should call the
 * When a part of the server wishes to set a timer, it should call the
 * GdAddTimer() function with the timeout parameter set to the number of
 * GdAddTimer() function with the timeout parameter set to the number of
 * milliseconds before the timer should activate, the callback argument
 * milliseconds before the timer should activate, the callback argument
 * set to the function which should be called when the timer expires, and
 * set to the function which should be called when the timer expires, and
 * the arg argument set to the (void * type) argument which should be supplied
 * the arg argument set to the (void * type) argument which should be supplied
 * to the timer handler function. The GdAddTimer() returns a pointer to the
 * to the timer handler function. The GdAddTimer() returns a pointer to the
 * timer structure * which was created (or NULL if the creation failed for
 * timer structure * which was created (or NULL if the creation failed for
 * some reason). The prototype for the callback function should look like:
 * some reason). The prototype for the callback function should look like:
 * void callbackfn(void *arg);
 * void callbackfn(void *arg);
 *
 *
 * If a part of the server wishes to destroy a timer before it has expired
 * If a part of the server wishes to destroy a timer before it has expired
 * (it is not necessary to do so after the timer has expired, as the timer
 * (it is not necessary to do so after the timer has expired, as the timer
 * structure is automatically destroyed after the callback function is called),
 * structure is automatically destroyed after the callback function is called),
 * it should call the GdDestroyTimer() function with the address of the timer
 * it should call the GdDestroyTimer() function with the address of the timer
 * structure (which was returned by GdAddTimer()).
 * structure (which was returned by GdAddTimer()).
 *
 *
 * If a part of the server wishes to destroy a timer but does not know the
 * If a part of the server wishes to destroy a timer but does not know the
 * address of it's timer structure, it can call GdFindTimer() with the
 * address of it's timer structure, it can call GdFindTimer() with the
 * callback argument as a parameter. The argument must be unique to that
 * callback argument as a parameter. The argument must be unique to that
 * timer (the address of a structure or function is probably a good choice).
 * timer (the address of a structure or function is probably a good choice).
 * This function returns the address of the first timer found with that
 * This function returns the address of the first timer found with that
 * argument, or NULL if no matching timer was found.
 * argument, or NULL if no matching timer was found.
 *
 *
 * The main select() loop needs to be called with a timeout obtained using the
 * The main select() loop needs to be called with a timeout obtained using the
 * GdGetNextTimeout(). GdGetNextTimeout() is called with the event loop
 * GdGetNextTimeout(). GdGetNextTimeout() is called with the event loop
 * timeout in ms, and fills in the specified timeout structure, which should
 * timeout in ms, and fills in the specified timeout structure, which should
 * be used as the argument to the select() call. The timeout returned by the
 * be used as the argument to the select() call. The timeout returned by the
 * GdGetNextTimeout() call is decided by looking through the timer list for
 * GdGetNextTimeout() call is decided by looking through the timer list for
 * the timer with the shortest amount of time remaining, and also at the
 * the timer with the shortest amount of time remaining, and also at the
 * maximum delay parameter. If there are no timers on the timer list and the
 * maximum delay parameter. If there are no timers on the timer list and the
 * timeout argument is 0, it will return FALSE, otherwise it will return TRUE.
 * timeout argument is 0, it will return FALSE, otherwise it will return TRUE.
 *
 *
 * When the main select() loop times out, the GdTimeout() function should be
 * When the main select() loop times out, the GdTimeout() function should be
 * called. This will go through the timer list and call the callback functions
 * called. This will go through the timer list and call the callback functions
 * of all timers which have expired, then remove them from the timer list. At
 * of all timers which have expired, then remove them from the timer list. At
 * the same time, you should check the value of the maximum timeout parameter
 * the same time, you should check the value of the maximum timeout parameter
 * to see if it has expired (in which case you can then return to the client
 * to see if it has expired (in which case you can then return to the client
 * with a timeout event). This function returns TRUE if the timeout specified in
 * with a timeout event). This function returns TRUE if the timeout specified in
 * the last GdGetNextTimeout() call has expired, or FALSE otherwise.
 * the last GdGetNextTimeout() call has expired, or FALSE otherwise.
 *
 *
 * Note that no guarantees can be made as to when exactly the timer callback
 * Note that no guarantees can be made as to when exactly the timer callback
 * will be called as it depends on how often the GdTimeout() function is
 * will be called as it depends on how often the GdTimeout() function is
 * called and how long any other timeouts in the queue before you take to
 * called and how long any other timeouts in the queue before you take to
 * complete. Especially in the case where the client is linked into the server,
 * complete. Especially in the case where the client is linked into the server,
 * the client must call into the server on a regular basis, otherwise the
 * the client must call into the server on a regular basis, otherwise the
 * timers may run late.
 * timers may run late.
 */
 */
 
 
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdlib.h>
#include "device.h"
#include "device.h"
 
 
static MWTIMER *timerlist = NULL;
static MWTIMER *timerlist = NULL;
static struct timeval mainloop_timeout;
static struct timeval mainloop_timeout;
static struct timeval current_time;
static struct timeval current_time;
 
 
static void calculate_timeval(struct timeval *tv, MWTIMEOUT to);
static void calculate_timeval(struct timeval *tv, MWTIMEOUT to);
static signed long time_to_expiry(struct timeval *t);
static signed long time_to_expiry(struct timeval *t);
 
 
MWTIMER *GdAddTimer(MWTIMEOUT timeout, MWTIMERCB callback, void *arg)
MWTIMER *GdAddTimer(MWTIMEOUT timeout, MWTIMERCB callback, void *arg)
{
{
        MWTIMER *newtimer;
        MWTIMER *newtimer;
 
 
        if(!(newtimer = malloc(sizeof(MWTIMER)))) return NULL;
        if(!(newtimer = malloc(sizeof(MWTIMER)))) return NULL;
 
 
        gettimeofday(&current_time, NULL);
        gettimeofday(&current_time, NULL);
 
 
        if(timerlist) timerlist->prev = newtimer;
        if(timerlist) timerlist->prev = newtimer;
 
 
        calculate_timeval(&newtimer->timeout, timeout);
        calculate_timeval(&newtimer->timeout, timeout);
        newtimer->callback = callback;
        newtimer->callback = callback;
        newtimer->arg = arg;
        newtimer->arg = arg;
        newtimer->next = timerlist;
        newtimer->next = timerlist;
        newtimer->prev = NULL;
        newtimer->prev = NULL;
        newtimer->type   = MWTIMER_ONESHOT;
        newtimer->type   = MWTIMER_ONESHOT;
        newtimer->period = timeout;
        newtimer->period = timeout;
        timerlist = newtimer;
        timerlist = newtimer;
 
 
        return newtimer;
        return newtimer;
}
}
 
 
MWTIMER *GdAddPeriodicTimer(MWTIMEOUT timeout, MWTIMERCB callback, void *arg)
MWTIMER *GdAddPeriodicTimer(MWTIMEOUT timeout, MWTIMERCB callback, void *arg)
{
{
    MWTIMER *newtimer;
    MWTIMER *newtimer;
 
 
    if(!(newtimer = malloc(sizeof(MWTIMER)))) return NULL;
    if(!(newtimer = malloc(sizeof(MWTIMER)))) return NULL;
 
 
    gettimeofday (&current_time, NULL);
    gettimeofday (&current_time, NULL);
 
 
    if (timerlist) timerlist->prev = newtimer;
    if (timerlist) timerlist->prev = newtimer;
 
 
    calculate_timeval (&newtimer->timeout, timeout);
    calculate_timeval (&newtimer->timeout, timeout);
    newtimer->callback = callback;
    newtimer->callback = callback;
    newtimer->arg      = arg;
    newtimer->arg      = arg;
    newtimer->next     = timerlist;
    newtimer->next     = timerlist;
    newtimer->prev     = NULL;
    newtimer->prev     = NULL;
    newtimer->type     = MWTIMER_PERIODIC;
    newtimer->type     = MWTIMER_PERIODIC;
    newtimer->period   = timeout;
    newtimer->period   = timeout;
    timerlist          = newtimer;
    timerlist          = newtimer;
 
 
    return newtimer;
    return newtimer;
}
}
 
 
void GdDestroyTimer(MWTIMER *timer)
void GdDestroyTimer(MWTIMER *timer)
{
{
        if(timer->next) timer->next->prev = timer->prev;
        if(timer->next) timer->next->prev = timer->prev;
        if(timer->prev) timer->prev->next = timer->next;
        if(timer->prev) timer->prev->next = timer->next;
        if(timer == timerlist) {
        if(timer == timerlist) {
                if(timer->next) timerlist = timer->next;
                if(timer->next) timerlist = timer->next;
                else timerlist = timer->prev;
                else timerlist = timer->prev;
        }
        }
        free(timer);
        free(timer);
}
}
 
 
MWTIMER *GdFindTimer(void *arg)
MWTIMER *GdFindTimer(void *arg)
{
{
        MWTIMER *t = timerlist;
        MWTIMER *t = timerlist;
 
 
        while(t) {
        while(t) {
                if(t->arg == arg) break;
                if(t->arg == arg) break;
                t = t->next;
                t = t->next;
        }
        }
 
 
        return t;
        return t;
}
}
 
 
MWBOOL GdGetNextTimeout(struct timeval *tv, MWTIMEOUT timeout)
MWBOOL GdGetNextTimeout(struct timeval *tv, MWTIMEOUT timeout)
{
{
        signed long i, lowest_timeout;
        signed long i, lowest_timeout;
        MWTIMER *t = timerlist;
        MWTIMER *t = timerlist;
 
 
        if(!timeout && !timerlist) return FALSE;
        if(!timeout && !timerlist) return FALSE;
 
 
        gettimeofday(&current_time, NULL);
        gettimeofday(&current_time, NULL);
 
 
        if(timeout) {
        if(timeout) {
                calculate_timeval(&mainloop_timeout, timeout);
                calculate_timeval(&mainloop_timeout, timeout);
                lowest_timeout = time_to_expiry(&mainloop_timeout);
                lowest_timeout = time_to_expiry(&mainloop_timeout);
        } else {
        } else {
                lowest_timeout = time_to_expiry(&t->timeout);
                lowest_timeout = time_to_expiry(&t->timeout);
                mainloop_timeout.tv_sec = -1;
                mainloop_timeout.tv_sec = -1;
                t = t->next;
                t = t->next;
        }
        }
 
 
        while(t) {
        while(t) {
                i = time_to_expiry(&t->timeout);
                i = time_to_expiry(&t->timeout);
                if(i < lowest_timeout) lowest_timeout = i;
                if(i < lowest_timeout) lowest_timeout = i;
                t = t->next;
                t = t->next;
        }
        }
 
 
        if(lowest_timeout <= 0) {
        if(lowest_timeout <= 0) {
                tv->tv_sec = 0;
                tv->tv_sec = 0;
                tv->tv_usec = 0;
                tv->tv_usec = 0;
        } else {
        } else {
                tv->tv_sec = lowest_timeout / 1000;
                tv->tv_sec = lowest_timeout / 1000;
                tv->tv_usec = (lowest_timeout % 1000) * 1000;
                tv->tv_usec = (lowest_timeout % 1000) * 1000;
        }
        }
 
 
        return TRUE;
        return TRUE;
}
}
 
 
MWBOOL GdTimeout(void)
MWBOOL GdTimeout(void)
{
{
        MWTIMER *n, *t = timerlist;
        MWTIMER *n, *t = timerlist;
 
 
        gettimeofday(&current_time, NULL);
        gettimeofday(&current_time, NULL);
 
 
        while(t) {
        while(t) {
                n = t->next;
                n = t->next;
                if(time_to_expiry(&t->timeout) <= 0) {
                if(time_to_expiry(&t->timeout) <= 0) {
                        t->callback(t->arg);
                        t->callback(t->arg);
                        if (t->type == MWTIMER_ONESHOT)
                        if (t->type == MWTIMER_ONESHOT)
                        {
                        {
                            /* One shot timer, is finished delete it now */
                            /* One shot timer, is finished delete it now */
                            GdDestroyTimer(t);
                            GdDestroyTimer(t);
                        }
                        }
                        else
                        else
                        {
                        {
                            /* Periodic timer needs to be reset */
                            /* Periodic timer needs to be reset */
                            calculate_timeval (&t->timeout, t->period);
                            calculate_timeval (&t->timeout, t->period);
                        }
                        }
                }
                }
                t = n;
                t = n;
        }
        }
 
 
        if(mainloop_timeout.tv_sec > 0 || mainloop_timeout.tv_usec > 0)
        if(mainloop_timeout.tv_sec > 0 || mainloop_timeout.tv_usec > 0)
                if(time_to_expiry(&mainloop_timeout) <= 0)
                if(time_to_expiry(&mainloop_timeout) <= 0)
                        return TRUE;
                        return TRUE;
 
 
        return FALSE;
        return FALSE;
}
}
 
 
static void calculate_timeval(struct timeval *tv, MWTIMEOUT to)
static void calculate_timeval(struct timeval *tv, MWTIMEOUT to)
{
{
        tv->tv_sec = current_time.tv_sec + (to / 1000);
        tv->tv_sec = current_time.tv_sec + (to / 1000);
        tv->tv_usec = current_time.tv_usec + ((to % 1000) * 1000);
        tv->tv_usec = current_time.tv_usec + ((to % 1000) * 1000);
        if(tv->tv_usec > 1000000) {
        if(tv->tv_usec > 1000000) {
                tv->tv_sec++;
                tv->tv_sec++;
                tv->tv_usec -= 1000000;
                tv->tv_usec -= 1000000;
        }
        }
}
}
 
 
static signed long time_to_expiry(struct timeval *t)
static signed long time_to_expiry(struct timeval *t)
{
{
        MWTIMEOUT ret = (((t->tv_sec - current_time.tv_sec) * 1000) +
        MWTIMEOUT ret = (((t->tv_sec - current_time.tv_sec) * 1000) +
                        ((t->tv_usec - current_time.tv_usec) / 1000));
                        ((t->tv_usec - current_time.tv_usec) / 1000));
 
 
        return ret;
        return ret;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.