Nicholas Clark wrote:

On Tue, Jul 15, 2003 at 04:48:56PM +0200, Leopold Toetsch wrote:

Attached is a test program, showing an implementations for multiple


It didn't arrive. Did you attach it, or did its name end .t ?

No extension was .c. Attachment was there:
$ mailq
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
8CDB611802A 6908 Tue Jul 15 16:48:56 [EMAIL PROTECTED]
(deferred transport)
[EMAIL PROTECTED]


-- 6 Kbytes in 1 Request.

so it must have been stripped elsewhere.

Anyway - renamed to timer_c.txt


Nicholas Clark

leo
/*
 * itimer test
 */

#include <sys/time.h>
#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <math.h>

volatile sig_atomic_t got_alarm = 0;

typedef struct timer_t {
    int ticks;
    int value;
    int repeat;
    int run;
    int nr;
    struct timer_t *next;
    struct timer_t *prev;
} timer;

timer *rtimer = 0;

void add_timer(timer *t) {
    timer *next = rtimer;
    rtimer = t;
    t->next = next;
    if (next) {
        t->nr = next->nr + 1;
        next->prev = t;
    }
    else
        t->nr = 1;
}

void del_timer(timer *t) {
    timer *next = t->next;
    timer *prev = t->prev;
    if (prev)
        prev->next = next;
    else
        rtimer = next;
    if (next)
        next->prev = prev;
    free(t);
}

timer * new_timer(void) {
    timer *t = calloc(1, sizeof(timer));
    add_timer(t);
    return t;
}
typedef unsigned int UINTVAL;
typedef double FLOATVAL;

UINTVAL gcd(UINTVAL a, UINTVAL b) {

    UINTVAL q = 0;
    UINTVAL c = 0;
    while (b != 0) {
        q = (UINTVAL)floor( (FLOATVAL)a/b );
        c = a - b*q;
        a = b;
        b = c;
    }
    return a;
}

void
sig_alarm_handler(int i) {
    got_alarm = 1;
}

/* platform interface */
void start_sys_timer_ms(void *handle, int ms) {
    struct itimerval its;
    memset(&its, 0, sizeof(its));
    if (ms) {
        its.it_interval.tv_sec = its.it_value.tv_sec = ms/1000;
        its.it_interval.tv_usec = its.it_value.tv_usec = 1000 *(ms%1000);
    }
    setitimer(ITIMER_REAL, &its, NULL);
    printf("new val = %ld:%ld ms = %d\n",
            its.it_value.tv_sec, its.it_value.tv_usec, ms);
}
void stop_sys_timer_ms(void *handle) {
    start_sys_timer_ms(handle, 0);
}
int get_sys_timer_ms(void *handle) {
    struct itimerval ots;
    getitimer(ITIMER_REAL, &ots);
    return ots.it_interval.tv_sec * 1000 + ots.it_interval.tv_usec/1000;
}
void * new_sys_timer_ms() {return 0; }
/* end platform interface */

void recalc_ticks(void);
void *handle;

void
do_alarm_handler() {
    timer *t;
    UINTVAL ms;
    int recalc = 0;

    ms = get_sys_timer_ms(handle);
    for (t = rtimer; t; t= t->next) {
        if (!--t->ticks) {
            t->run = 1;
            if (t->repeat) {
                t->ticks = t->value/ms;
                if (t->repeat != -1)
                    t->repeat--;
            }
        }
    }
again:
    for (t = rtimer; t; t= t->next) {
        if (t->run == 1) {
            t->run = 0;
            printf("alarm %d\n", t->nr);
            /* code run here may add timers, these have t->run = 2 */
            goto again;
        }
        if (!t->ticks && !t->repeat) {
            printf("del_timer %d\n", t->nr);
            del_timer(t);
            recalc = 1;
            goto again;
        }
    }
    if (recalc)
        recalc_ticks();
}

void p_add_timer(UINTVAL msecs, int repeat)
{
    timer *t;

    if (!msecs)
        return;
    t = new_timer();
    t->repeat = repeat;
    t->value = msecs;
    t->run = 2;
    recalc_ticks();
}

void p_del_timer(timer *t) {
    del_timer(t);
    recalc_ticks();
}

void recalc_ticks() {
    UINTVAL ms, oms;
    timer *t;

    oms = get_sys_timer_ms(handle);
    printf("gettimer oms = %d\n", oms);
    t = rtimer;
    if (t) {
        t->run = 0;
        if (oms && t->ticks)
            ms = oms*t->ticks;  /* time left */
        else
            ms = t->value;
        if (t->next) {
            for (t = t->next; t; t = t->next) {
                t->run = 0;
                if (oms && t->ticks) {
                    ms = gcd(oms*t->ticks, ms);
                }
                else
                    ms = gcd(t->value, ms);
            }
        }
        printf("new ms %d\n", ms);
again:
        for (t = rtimer; t; t= t->next) {
            int ot = t->ticks;
            printf("t%d oticks %d => ", t->nr, t->ticks);
            if (oms && ot)
                t->ticks = t->ticks * ((double)oms / (double)ms);
            else
                t->ticks = t->value / ms;
            if (!t->ticks) {
                ms = oms;
                t->ticks = ot;
                goto again;
            }
            printf("ticks %d value %d\n", t->ticks, t->value);
        }
    }
    else
        ms = 0;

    if (ms)
        start_sys_timer_ms(handle, ms);
    else
        stop_sys_timer_ms(handle);
}


int main(int argc, char **argv) {
    handle = new_sys_timer_ms();
    signal(SIGALRM, sig_alarm_handler);
    p_add_timer(3000, 1);
    p_add_timer(2000, 3);
    p_add_timer(500, 1);
    while (rtimer) {
        if (got_alarm) {        /* CHECK_EVENTS */
            got_alarm = 0;
            do_alarm_handler();
        }
    }
    return 0;
}

Reply via email to