/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1991 by John E. Lloyd.				    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

#if !defined(SGI_CFG) && !defined(VXWORKS_CFG)

#include <sys/time.h>

#include "../h/cdefs.h"
#include "../h/rciConfig.h"
#include "../h/rciTask.h"

extern int rciCpu;
extern int rciSimOnly;

int *_rciClockAddrs[MAX_CPUS];
int *_rciClockHosts[MAX_CPUS];

static rciTimeInitDone = -1;
static double clockRes;
static int *clockAddr = NULL;
static struct timeval starttime;

rciTimeInit (addr, res)
int *addr;
double res;
{
	/* Called by monitor clock control code */

	clockRes = res;
	clockAddr = addr;	
	rciTimeInitDone = rciCpu;
	requestFlagInit(&rciTimeInitDone);
	if (rciSimOnly)
	 { getSystemTime (&starttime);
	 }
}

rciTime ()
{
/* IRIX: use system clock */

	if (!rciSimOnly)
	 { if (rciTimeInitDone != rciCpu || clockAddr == NULL)
	    { return (0);
	    }
	   else
	    { return ((*clockAddr) * clockRes);
	    }
	 }
	else
	 { struct timeval tv;

	   getSystemTime (&tv);
	   tv.tv_sec -= starttime.tv_sec;
	   tv.tv_usec -= starttime.tv_usec;
	   return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
	 }
}

float rciTimeInterval()
{
/* IRIX: use system clock */

	return (clockRes);
}

rciGetClock(num)
{
/* IRIX: ignore */

	return (*_rciClockAddrs[num]);
}

rciSetClock(num, count)
int num, count;
{
/* IRIX: maybe allow for a setable clock offset */
	*_rciClockAddrs[num] = count;
}

rciStartClock (incumbent, newRes, oldRes)
int incumbent;
float newRes, oldRes;
{
/* IRIX: maybe allow for a setable clock offset */
	int setcount;

	if (incumbent == UNDEF)
	 { if (rciCpu != ARBITER_CPU)
	    { *_rciClockAddrs[rciCpu] = 0;
	      setcount = 0;	
	    }
	   else
	    { setcount = *_rciClockAddrs[rciCpu];
	    }
	 }
	else
	 { setcount = (*_rciClockHosts[incumbent])*(oldRes/newRes);
	   *_rciClockAddrs[rciCpu] = setcount;
	 }
	rciTimeInit (_rciClockAddrs[rciCpu], newRes);
	return (setcount);
}

rciExportClock (targetCpu, code)
int targetCpu, code;
{
/* IRIX: ignore */
	exportclock (targetCpu, code);
}

rciImportClock (cpu, res, reInitialize)
int cpu;
double res;
int reInitialize;
{
/* IRIX: ignore */
	if (reInitialize)
	 { 
	   /* used to signal that we are transfering the clock from the 
	      arbiter to an auxiliary CPU */

	   /* check clock phase; boost if necessary */

	   if (*_rciClockHosts[cpu] < *_rciClockAddrs[rciCpu])
	    { *_rciClockHosts[cpu] = *_rciClockAddrs[rciCpu];
	    }
	 }
	rciTimeInit (_rciClockAddrs[cpu], res);
}

#endif /* !defined(SGI_CFG) && !defined(VXWORKS_CFG) */
