/* $Id: timer.c,v 1.1 1999/08/23 16:18:41 naamato Exp $ */
/*
 * Copyright(c) 1998 by Hitachi.Ltd All rights reserved.
 *
 */

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>

struct TIMER_LIST {
    struct TIMER_LIST *next;
    u_long id;
    char *data;
    void (*time_out)();
    int state;
    time_t last_time;
    time_t interval;
};

#define TIMER_ACTIVE 	1
#define TIMER_DOWN	0

void timer_check();

time_t start_time=0;
time_t currnt_time=0;

struct TIMER_LIST *timer_list=NULL;

/*

  time_init

*/
void time_init()
{
    struct timeval tp;
    struct timezone tzp;

    gettimeofday(&tp,&tzp);

    start_time = currnt_time = tp.tv_sec;
}

/*

  time_count

*/
void time_count()
{
    struct timeval tp;
    struct timezone tzp;

    gettimeofday(&tp,&tzp);

    if(currnt_time != tp.tv_sec)
        currnt_time = tp.tv_sec;

}


/*

  get_currnt_time

*/
time_t get_currnt_time()
{
    return currnt_time;
}

/*

  get_time_diff

*/
time_t get_time_diff(base)
time_t base;
{
    time_count();

    return(currnt_time-base);
}

/*

  timer_init

*/
char  *timer_init(id,data,func)
u_long id;
char *data;
void (*func)();
{
    struct TIMER_LIST *timer,*list;


    timer = (struct TIMER_LIST *)malloc(sizeof(struct TIMER_LIST));
    bzero(timer,sizeof(struct TIMER_LIST));
    timer->id = id;
    timer->time_out = func;
    timer->data = data;
    timer->state = TIMER_DOWN;
    
    if(timer_list == NULL) {
	timer_list = timer;
    }
    else {
	for(list=timer_list;list->next;list=list->next) ;

	list->next = timer;
    }

    return (char *)timer;
}

/*

  timer_set
  
*/
void timer_set(t,interval)
char *t;
time_t interval;
{
    struct TIMER_LIST *timer;

    if(t)
      timer = (struct TIMER_LIST *)t;
    else
      return ;

    time_count();
    timer->state = TIMER_ACTIVE;
    timer->interval = interval;
    timer->last_time = currnt_time;
}

/*

  timer_stop

*/
void timer_stop(timer)
char *timer;
{
    if(timer)
      ((struct TIMER_LIST *)timer)->state = TIMER_DOWN;
}

#if 0  
/*

  signal_init

*/
void signal_init()
{
struct  itimerval {
        struct  timeval it_interval;    /* timer interval */
        struct  timeval it_value;       /* current value */
      };
struct itimerval value;

#ifdef SYSTEM_V

    sighold(SIGALRM);
    sigset(SIGALRM, timer_check);

#else /* BSD ( SunOS 4.x, FreeBSD, BSD/OS ) */
    struct sigvec vec,ovec;

    bzero((char *)&vec,sizeof(vec));
    vec.sv_mask = sigmask(SIGALRM);
    vec.sv_handler = timer_check;

    sigvec(SIGALRM, &vec, &ovec);

#endif /* SYSTEM_V */

    sem_init();

/*    signal(SIGALRM, timer_check);*/

/*    value.it_interval.tv_sec = 10;
    value.it_interval.tv_usec = 0;
    value.it_value.tv_sec = 10;
    value.it_value.tv_usec = 0;

    if(setitimer(ITIMER_REAL,&value,(struct itimerval *)0)) {
	printf("setitimer error <%d>\n",errno);
	exit(1);
    } */

    alarm(1);

}
#endif

/*

  timer_check

*/
void timer_check()
{
struct  itimerval {
        struct  timeval it_interval;    /* timer interval */
        struct  timeval it_value;       /* current value */
      };

    struct itimerval value,ovalue;
    struct TIMER_LIST *timer;

/*    ovalue.it_interval.tv_sec = 10;
    ovalue.it_interval.tv_usec = 0;
    ovalue.it_value.tv_sec = 10;
    ovalue.it_value.tv_usec = 0;
*/
    time_count();

    for(timer=timer_list;timer;timer=timer->next) {
	if(timer->state == TIMER_DOWN) continue;
/*
	printf("id:%d interval = %d,last_time = %d,currnt_time = %d\n",
	timer->id,timer->interval,timer->last_time,currnt_time);
*/
	if(timer->interval <= currnt_time - timer->last_time) {
	    timer->time_out(timer->id,timer->data);
	    timer->last_time = currnt_time;
	}
    }

}
    
/*

  time_term

*/
void time_term()
{
    struct TIMER_LIST *time;

    for(time=timer_list;time;time=time->next) {
	timer_stop((char *)time);
    }
}

