177 lines
3.6 KiB
C
177 lines
3.6 KiB
C
/* mtimer.c
|
|
*
|
|
* Author Karsten Keil <kkeil@novell.com>
|
|
*
|
|
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
|
* version 2.1 as published by the Free Software Foundation.
|
|
*
|
|
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
|
*
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include "mtimer.h"
|
|
#include "layer3.h"
|
|
#include "helper.h"
|
|
|
|
//#define DEBUG_TIMERS
|
|
|
|
#ifdef DEBUG_TIMERS
|
|
void debug_list(struct timer_base *tb)
|
|
{
|
|
struct mtimer *mt;
|
|
|
|
printf("list all timers of tb=%p:\n", tb);
|
|
list_for_each_entry(mt, &tb->pending_timer, list) {
|
|
printf(" - timer %p\n", mt);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int
|
|
init_timer(struct mtimer *mt, struct timer_base *tb, void *data, mtimer_func_t *f)
|
|
{
|
|
#ifdef DEBUG_TIMERS
|
|
printf("init timer %p\n", mt);
|
|
#endif
|
|
mt->tb = tb;
|
|
mt->id = 0;
|
|
mt->data = data;
|
|
mt->function = f;
|
|
return 0;
|
|
}
|
|
|
|
static int nextid = 1;
|
|
|
|
int
|
|
add_timer(struct mtimer *mt, int tout)
|
|
{
|
|
int ret, para;
|
|
struct mtimer *check;
|
|
|
|
/* hack to be sure that timer will fire even when no or negative time was given */
|
|
if (tout < 1)
|
|
tout = 1;
|
|
|
|
#ifdef DEBUG_TIMERS
|
|
printf("add timer %p (timeout=%d ms)\n", mt, tout);
|
|
debug_list(mt->tb);
|
|
#endif
|
|
|
|
mt->timeout = tout;
|
|
para = tout;
|
|
if (mt->tb->tdev) {
|
|
ret = ioctl(mt->tb->tdev, IMADDTIMER, (long)¶);
|
|
if (ret < 0)
|
|
return ret;
|
|
mt->id = para;
|
|
} else {
|
|
static struct timespec tv;
|
|
clock_gettime(CLOCK_REALTIME, &tv);
|
|
mt->expires = (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0;
|
|
mt->expires += (double)tout / 1000.0;
|
|
ret = 0;
|
|
mt->id = nextid++;
|
|
}
|
|
list_for_each_entry(check, &mt->tb->pending_timer, list) {
|
|
if (check == mt) {
|
|
eprint("%s: timer already in list!\n", __func__);
|
|
return ret;
|
|
}
|
|
}
|
|
list_add_tail(&mt->list, &mt->tb->pending_timer);
|
|
#ifdef DEBUG_TIMERS
|
|
printf("add timer done\n");
|
|
debug_list(mt->tb);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
del_timer(struct mtimer *mt)
|
|
{
|
|
int ret = 0;
|
|
|
|
#ifdef DEBUG_TIMERS
|
|
printf("del timer %p id=%d\n", mt, mt->id);
|
|
debug_list(mt->tb);
|
|
#endif
|
|
if (mt->id) {
|
|
list_del(&mt->list);
|
|
ret = ioctl(mt->tb->tdev, IMDELTIMER, (long)&mt->id);
|
|
mt->id = 0;
|
|
}
|
|
#ifdef DEBUG_TIMERS
|
|
printf("del timer done\n");
|
|
debug_list(mt->tb);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
timer_pending(struct mtimer *mt)
|
|
{
|
|
return mt->id;
|
|
}
|
|
|
|
int expire_timer(struct timer_base *tb, int id)
|
|
{
|
|
struct mtimer *mt;
|
|
double now = 0.0;
|
|
int work = 0;
|
|
|
|
/* if id is < 0, then check for expired timer */
|
|
if (id < 0) {
|
|
static struct timespec tv;
|
|
clock_gettime(CLOCK_REALTIME, &tv);
|
|
now = (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0;
|
|
}
|
|
|
|
again:
|
|
list_for_each_entry(mt, &tb->pending_timer, list) {
|
|
#ifdef DEBUG_TIMERS
|
|
// printf("check timer in list %p\n", mt);
|
|
#endif
|
|
if (id >= 0 && mt->id == id) {
|
|
work |= 1;
|
|
list_del(&mt->list);
|
|
mt->id = 0;
|
|
#ifdef DEBUG_TIMERS
|
|
printf("calling expire function\n");
|
|
debug_list(tb);
|
|
#endif
|
|
mt->function(mt->data);
|
|
#ifdef DEBUG_TIMERS
|
|
printf("expire functiion finished\n");
|
|
debug_list(tb);
|
|
#endif
|
|
return work;
|
|
}
|
|
if (id < 0 && now >= mt->expires) {
|
|
work |= 1;
|
|
list_del(&mt->list);
|
|
mt->expires = 0.0;
|
|
#ifdef DEBUG_TIMERS
|
|
printf("calling expire function\n");
|
|
debug_list(tb);
|
|
#endif
|
|
mt->function(mt->data);
|
|
#ifdef DEBUG_TIMERS
|
|
printf("expire functiion finished\n");
|
|
debug_list(tb);
|
|
#endif
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
return work;
|
|
}
|