/*----------------------------------------------------------------------------
Name: virttimer.c (implimentation of virtual timer)
Author: Christopher Huyler
Date: March 13, 2002
Description: virttimer API
Provides reset_virt, start_virt and get_virt functions to keep track of time
API overrides the SIGVTALRM signal using the _incr_virt signal handler.
----------------------------------------------------------------------------*/
#include <sys/time.h>
#include <signal.h>

struct itimerval _v;                    // itimer initializer (private)
static long _virt_time;              	// virt time (private)

void _incr_virt(int);					// signal handler (private)
int  start_virt(void);					// start the virt timer
void reset_virt(void);     				// initialize timer to current time
struct timeval get_virt(void);			// get current time

/*  incriment virt signal handler --------------------------------------------
	input		- signal type integer
	output		- incriments virt_time by one second every time called
	syscalls	- calls signal to re-register itself */
void _incr_virt(int sig)
{
	_virt_time++;							// incriment virt time
	signal(SIGVTALRM,_incr_virt);			// reset signal
}

/*	start virt timer ---------------------------------------------------------
	input		- nothing
	output		- initializes an itimer and registers a SIGVTALRM signal handler
	syscalls	- calls signal and setitimer */
int start_virt()
{
	signal(SIGVTALRM,_incr_virt);			// register signal handler
		
	_v.it_interval.tv_sec = (long) 1;		// set interval seconds
	_v.it_interval.tv_usec = (long) 0;		// set interval microseconds
	_v.it_value.tv_sec = (long) 1;			// set start seconds value
	_v.it_value.tv_usec = (long) 0;			// set start useconds value
	
	setitimer(ITIMER_VIRTUAL, &_v, NULL);	// start the timer
}

/*	reset virt timer ---------------------------------------------------------
	input		- nothing
	output		- resets virt time timeval
	syscalls	- none */
void reset_virt()
{
	_virt_time = 0;
}

/*	get current virt time ----------------------------------------------------
	input		- reads vvirt_time variable
	output		- returns virt_time value + current itimer value
	syscalls	- calls getitimer */
struct timeval get_virt()
{
	struct timeval current_time;
	getitimer(ITIMER_VIRTUAL,&_v);			// get current timer state
	current_time.tv_sec = _virt_time;		// and add it to virt time
	current_time.tv_usec = elapsed_usecs(_v.it_value.tv_sec,_v.it_value.tv_usec); // time = start - remaining
	return current_time;
}

/*	test function for virt  --------------------------------------------------
	input		- nothing
	output		- prints out virt time recursively using realtimer functions
	syscalls	- none	
int main() {
	struct timeval myTime;
	start_virt();
	while(1) {
		myTime = get_virt();
		printf("\n%ld seconds, %ld microseconds",
				myTime.tv_sec,
				myTime.tv_usec);
	}
} */
