/************************************************************************/
/*	Routing Protocol Simulator	Relese 1.0	1994/3/17	*/
/*									*/
/*		module 	: common routine       				*/
/*		file	: rps_time.c		       			*/
/*									*/
/*   Copyright (c) 1994 by Systems Development Laboratory Hitachi,Ltd.	*/
/*   All rights reserved.						*/
/*----------------------------------------------------------------------*/
/*	UPDATE HISTORY							*/
/*	1994/2/13 fku  added timer task routine for VxWorks		*/
/*		       ( #ifdef VXWORKS )				*/
/*									*/
/************************************************************************/
static char copyright[]=
  "@(#)Copyright (c) 1994 by Systems Development Laboratory Hitachi,Ltd.\n All rights researved.\n";


#ifdef VXWORKS

#include "rps.h"
#include "vxTypes.h"

typedef unsigned short INSTR;

#include "taskLib.h"
#include "68k/regs.h"
#include "systime.h"
#include "sigLib.h"
#include "errno.h"

#else

#include "rps.h"
#include <sys/time.h>
#include <signal.h>
#include <errno.h>

#endif

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

#define TIMER_ACTIVE 	1
#define TIMER_DOWN	0

void timer_check();
void add_timer_list();


time_t start_time=0;
time_t currnt_time=0;

#ifdef VXWORKS

void sys_timer_create();

int timer_task_id;
int timer_task_priority = 80;
int timer_task_option = VX_SUPERVISOR_MODE | VX_FP_TASK | VX_STDIO;
int timer_task_stsize = 20000;

SEMAPHORE time_sem;

int my_task_id;
  
#endif

struct TIMER_LIST *timer_list=NULL;

/*

  time_init

*/
void time_init()
{
#ifdef VXWORKS
    start_time = currnt_time = tickGet();
    semBInit(&time_sem,SEM_Q_PRIORITY,SEM_EMPTY);

/*    semGive(&time_sem);*/
#else
    struct timeval tp;
    struct timezone tzp;

    gettimeofday(&tp,&tzp);

    start_time = currnt_time = tp.tv_sec;
#endif
}

/*

  time_count

*/
void time_count()
{
#ifdef VXWORKS
    currnt_time = tickGet();
#else
    struct timeval tp;
    struct timezone tzp;

    gettimeofday(&tp,&tzp);

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

}


/*

  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

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

    MALLOC(timer,TIMER_LIST);

    timer->id = id;
    timer->time_out = func;
    timer->data = data;
    timer->state = TIMER_DOWN;
    
    add_timer_list(timer);

    return (byte *)timer;
}

/*

  add_timer_list

*/
void add_timer_list(timer)
struct TIMER_LIST *timer;
{
    struct TIMER_LIST *list;

    if(timer_list == NULL) {
	timer_list = timer;
    }
    else {
	for(list=timer_list;list->next;list=list->next) ;

	list->next = timer;
    }
}

/*

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

    if(t)
      timer = (struct TIMER_LIST *)t;
    else
      return ;
    
    timer->state = TIMER_ACTIVE;
#ifdef VXWORKS
    
    timer->interval = interval;

#else

    timer->interval = interval;

#endif
    
    timer->last_time = currnt_time;
}

/*

  timer_stop

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

  
/*

  signal_init

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

    struct itimerval value;
   
#ifdef 	BSD_SIGNALS 
   struct sigvec vec,ovec;
    bzero((char *)&vec,sizeof(vec));
    vec.sv_mask = sigmask(SIGALRM);
    vec.sv_handler = timer_check;
    sigvec(SIGALRM, &vec, &ovec);
#endif /* BSD_SIGNALS */

#ifdef	SUN5_5
    struct sigaction act, oact;
    bzero((u_char *)&act,sizeof(act));
    bzero((u_char *)&oact,sizeof(oact));
 	
    sigemptyset(&act.sa_mask);
    act.sa_handler =  timer_check;
    act.sa_flags = 0;	 	
    sigaction(SIGALRM,&act, &oact);	    	
#endif /* SUN5_5 */


    sem_init();
#ifdef VXWORKS

    my_task_id = taskIdSelf();
    sys_timer_create();
/*    semGive(&time_sem);*/

#else

/*    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("interval = %d,last_time = %d,currnt_time = %d\n",
	timer->interval,timer->last_time,currnt_time);
*/
#ifdef VXWORKS
	
	if(timer->interval <= (currnt_time - timer->last_time)/sysClkRateGet())

#else
	  
	if(timer->interval <= currnt_time - timer->last_time)

#endif	    
       {
	   timer->time_out(timer->id,timer->data);

	    timer->last_time = currnt_time;
	}
    }


#ifdef VXWORKS

#else
/*    
    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
}
    
#ifdef VXWORKS
/*

  vx_alarm

*/
int vx_alarm(sec)
int sec;
{
	while(1) {
/*		semTake(&time_sem,WAIT_FOREVER);*/

/*		timer_check();*/
	        kill(my_task_id,SIGALRM);
 		taskDelay(sec * sysClkRateGet());
  	}
}

#endif

#ifdef VXWORKS
/*

  sys_timer_create

*/
void sys_timer_create()
{
    timer_task_id = taskSpawn("TIMER_TASK",timer_task_priority,
			    timer_task_option,timer_task_stsize,
			    vx_alarm,
			    1,0,0,0,0,0,0,0,0,0);

    if(timer_task_id == ERROR) {
	printf("timer_task can't create\n");
    }
}

#endif

#ifdef VXWORKS
/*

  sys_timer_delete

*/
void sys_timer_delete()
{
    taskDelete(timer_task_id);
}

#endif

/*

  time_term

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

#ifdef VXWORKS

    sys_timer_delete();

#else

    signal(SIGINT, SIG_IGN);
    
#endif
    
    for(time=timer_list;time;time=time->next) {
	timer_stop((char *)time);
    }
}


#ifdef VXWORKS
/*

  time_semaphoe_give

*/
void time_semaphoe_give()
{
	semGive(&time_sem);
}

#endif







