📄 rvtime.c
字号:
#if (0)
*****************************************************************************
Filename :
Description :
******************************************************************************
Copyright (c) 2000 RADVision Inc.
************************************************************************
NOTICE:
This document contains information that is proprietary to RADVision LTD.
No part of this publication may be reproduced in any form whatsoever
without written prior approval by RADVision LTD..
RADVision LTD. reserves the right to revise this publication and make
changes without obligation to notify any person of such revisions or
changes.
******************************************************************************
$Revision:$
$Date:$
$Author: Jay Davis$
******************************************************************************
#endif
#if defined(RV_TEST_CODE)
#include <stdio.h>
#endif
#include "rvtypes.h"
#include "rvtime.h"
#if defined(RV_OS_REDHAT)
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include <unistd.h>
#include <limits.h>
#include <asm/timex.h>
static long long tick_hz; /* speed of cpu (cycles/second) */
#endif
#if defined(RV_OS_TRU64)
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/fcntl.h>
#include <kern/sysdev_info.h>
typedef struct {
int fd;
struct sysdev_info *info;
} RvTimestampClock_;
static RvTimestampClock_ rvTimestampClock;
#endif
#if defined(RV_OS_WIN32)
#include <Olectl.h>
/* Windows epoc is Jan 1, 1601, not Jan 1 1970 (100ns increments)*/
#define EPOCHDELTA 116444736000000000Ui64
static LONGLONG tick_hz; /* Performance Counter Frequency */
#endif
#if defined(RV_OS_VXWORKS)
/* Use the VxWorks timestamp driver for high res timestamp. */
/* Otherwise use system clock, which is low resolution. */
/* #define RV_VXWORKS_USETIMESTAMP */
#include <vxWorks.h>
#include <sysLib.h>
#include <tickLib.h>
#include <limits.h>
#include <wdLib.h>
#if defined(RV_TEST_CODE)
#include <ioLib.h>
#endif
static long long tick_hz; /* clock tick rate */
static int rvTimeCheckWrap(int param); /* Wrap check function declaration */
#if defined(RV_VXWORKS_USETIMESTAMP)
static volatile long long hires_count; /* total timer count as of last wrap */
#else
static volatile long wrap_count; /* how many times the hires counter has wrapped */
static volatile ULONG last_tick; /* Last clock tick value read checking for wrap */
#define WRAP_TICKS ULONG_MAX /* How many clock ticks per wrap */
static WDOG_ID wrap_timer; /* Watchdog timer that will call wrap check */
#endif
#endif
#if defined(RV_OS_PSOS)
#include <psos.h>
#include <limits.h>
extern pSOS_CT PsosCfg; /* pSOS config table declared by pRISM+ */
static long long tick_hz; /* clock tick rate */
#endif
#if defined(RV_OS_OSE)
#include <ose.h>
#include <limits.h>
static long long tick_period; /* clock tick rate in nanoseconds */
static volatile long wrap_count; /* how many times the hires counter has wrapped */
static volatile OSTICK last_tick; /* Last clock tick value read checking for wrap */
#define WRAP_TICKS ULONG_MAX /* How many clock ticks per wrap */
#define WRAP_MS_MAX (ULONG_MAX/2 - 1) /* Safe maximum milliseconds to delay between checks */
static OSTIME wrapcheck_ms; /* Number of milliseconds to delay between wrap checking */
static PROCESS wrap_timer; /* Background process that will call wrap check */
static PROCESS wrap_check; /* Interrupt process that will do the wrap check */
OSENTRYPOINT rvTimeCheckWrap; /* Wrap check function declaration (interrupt) */
OSENTRYPOINT rvTimeCheckWait; /* Check wait function declaration (background) */
#endif
#if defined(RV_OS_NUCLEUS)
#include <nucleus.h>
#include <target.h>
#include <limits.h>
#include "rvtimeutil.h"
static long long tick_hz; /* clock tick rate */
static long timezero; /* # of seconds since 1970 equating to 0 ticks */
static volatile long wrap_count; /* how many times the hires counter has wrapped */
static volatile UNSIGNED last_tick; /* Last clock tick value read checking for wrap */
#define WRAP_TICKS ULONG_MAX /* How many clock ticks per wrap */
static NU_TIMER wrap_timer; /* Timer that will call wrap check */
static VOID rvTimeCheckWrap(UNSIGNED param); /* Wrap check function declaration */
#endif
/* NTP epoc is Jan 1, 1900, not Jan 1 1970 (seconds) */
#define NTPDELTA 2208988800UL
/* Initialize stuff needed for some OS's to save time. Must */
/* be called and completed before any other calls are made. */
RvBool rvTimeInit(void)
{
#if defined(RV_OS_REDHAT)
/* The only way to find out if the high performance timer (tsc) */
/* is present and it's frequency is to read it from the file */
/* /proc/cpuinfo which is generated by the kernel at boot time. */
FILE *cpuinfo;
char linebuf[132], *cptr1, *cptr2;
RvBool has_tsc, found_mhz;
long scale, temp;
has_tsc = rvFalse; /* mark when we have found if tsc is present */
found_mhz = rvFalse; /* mark when we have found and set the cpu speed */
tick_hz = 100000000LL; /* just to prevent accidental divide by zero */
cpuinfo = fopen("/proc/cpuinfo", "r");
if(cpuinfo == NULL) return(rvFalse);
while(fgets(linebuf, sizeof(linebuf), cpuinfo) != NULL) {
/* check for MHz line which will give clock (and tsc) speed */
if(strncmp(linebuf, "cpu MHz", 7) == 0) {
/* line contains cpu speed info, parse it into tick_hz */
cptr1 = strchr(linebuf, ':'); /* find start of data field */
if (cptr1 != NULL) {
cptr1++; /* skip ":" seperator */
cptr2= strchr(cptr1, '.'); /* find decimal point */
if(cptr2 != NULL) { /* it had better be there */
*cptr2 = '\0'; /* split number into parts */
cptr2++; /* move to start of decimal */
temp = strtol(cptr1, NULL, 0); /* read whole number */
if(temp > 0) { /* sanity check */
tick_hz = 1000000LL * (long long)temp;
/* now add variable lengh fraction amount */
scale = 100000L; /* scale of next digit */
while((scale > 0L) && (isdigit(*cptr2) != 0)) {
temp = (long)(*cptr2 - '0');
tick_hz += (long long)(temp * scale);
scale = scale / 10L;
cptr2++;
}
found_mhz = rvTrue;
}
}
}
} /* end of cpu MHz check/parse */
/* check for "flags" line which lists tsc if it is present */
if(strncmp(linebuf, "flags", 5) == 0) {
cptr1 = strchr(linebuf, ':'); /* find start of data field */
if (cptr1 != NULL) {
cptr2 = strstr(cptr1, " tsc"); /* see if tsc is there */
if(cptr2 != NULL) has_tsc = rvTrue;
}
}
} /* end of file read loop */
fclose(cpuinfo);
if((has_tsc == rvFalse) || (found_mhz == rvFalse)) return rvFalse;
#endif
#if defined(RV_OS_TRU64)
/* Open the device once */
if ((rvTimestampClock.fd = open("/dev/sysdev0", O_RDONLY)) < 0)
return rvFalse;
/* Mmap the device into the address space of the user READONLY */
rvTimestampClock.info = (struct sysdev_info *) mmap((caddr_t)0, (size_t)getpagesize(),
PROT_READ,MAP_SHARED|MAP_FILE, rvTimestampClock.fd, (off_t) 0);
if ((long)rvTimestampClock.info < 0L)
return rvFalse;
#endif
#if defined(RV_OS_WIN32)
LARGE_INTEGER Frequency;
if(QueryPerformanceFrequency(&Frequency) == 0) {
tick_hz = 100000000i64; /* just to prevent accidental divide by zero */
return rvFalse;
}
tick_hz = Frequency.QuadPart;
#endif
#if defined(RV_OS_VXWORKS)
#if defined(RV_VXWORKS_USETIMESTAMP)
hires_count = 0LL;
tick_hz = (long long)sysTimestampFreq();
if(tick_hz <= 0LL) {
tick_hz = 100LL; /* just to prevent accidental divide by zero */
return rvFalse;
}
sysTimestampConnect(rvTimeCheckWrap, 0);
sysTimestampEnable(); /* start and reset timestamp timer */
#else
int wrapcheck_time;
wrap_count = 0;
last_tick = tickGet();
tick_hz = (long long)sysClkRateGet();
if(tick_hz <= 0LL) {
tick_hz = 100LL; /* just to prevent accidental divide by zero */
return rvFalse;
}
wrap_timer = wdCreate();
wrapcheck_time = WRAP_TICKS / 4 + WRAP_TICKS / 8;
wdStart(wrap_timer, wrapcheck_time, rvTimeCheckWrap, wrapcheck_time);
#endif
#endif
#if defined(RV_OS_PSOS)
tick_hz = (long long)PsosCfg.kc_ticks2sec;
if(tick_hz <= 0LL) {
tick_hz = 100LL; /* just to prevent accidental divide by zero */
return rvFalse;
}
#endif
#if defined(RV_OS_OSE)
OSTIME systick;
unsigned long wrapcheck_time;
unsigned long long wrapcheck_us;
wrap_count = 0;
last_tick = get_systime(NULL);
systick = system_tick();
tick_period = (long long)systick * 1000LL;
if(tick_period <= 0LL) {
tick_period = 1000000LL;
return rvFalse;
}
wrapcheck_time = WRAP_TICKS / 4 + WRAP_TICKS / 8; /* time in ticks */
wrapcheck_us = (unsigned long long)wrapcheck_time * (unsigned long long)systick; /* time in microsec */
if(wrapcheck_us >=((unsigned long long)WRAP_MS_MAX * 1000ULL)) {
wrapcheck_ms = WRAP_MS_MAX; /* delays are in ms and we don't want to chance wrapping that */
} else wrapcheck_ms = (OSTIME)(wrapcheck_us / 1000LL);
wrap_check = create_process(OS_INT_PROC, "Timecheck", rvTimeCheckWrap, 200, 0, 0, 0, NULL, -1, 0);
wrap_timer = create_process(OS_BG_PROC, "Timewrap", rvTimeCheckWait, 200, 0, 0, 0, NULL, -1, 0);
start(wrap_timer);
#endif
#if defined(RV_OS_NUCLEUS)
int wrapcheck_time;
wrap_count = 0;
last_tick = NU_Retrieve_Clock();
timezero = 0L;
tick_hz = (long long)TICKS_PER_SECOND;
if(tick_hz <= 0LL) {
tick_hz = 100LL; /* just to prevent accidental divide by zero */
return rvFalse;
}
wrapcheck_time = WRAP_TICKS / 4 + WRAP_TICKS / 8;
NU_Create_Timer(&wrap_timer, "Timewrap", rvTimeCheckWrap, wrapcheck_time, wrapcheck_time, wrapcheck_time, NU_ENABLE_TIMER);
#endif
return rvTrue;
}
void rvTimeEnd(void)
{
/* Close the system (clock) device */
#if defined(RV_OS_TRU64)
close(rvTimestampClock.fd);
#endif
/* Have to stop wrap check on systems that require it */
#if defined(RV_OS_VXWORKS)
#if defined(RV_VXWORKS_USETIMESTAMP)
sysTimestampDisable();
#else
wdCancel(wrap_timer);
wdDelete(wrap_timer);
#endif
#endif
#if defined(RV_OS_OSE)
stop(wrap_timer);
kill_proc(wrap_timer);
kill_proc(wrap_check);
#endif
#if defined(RV_OS_NUCLEUS)
NU_Control_Timer(&wrap_timer, NU_DISABLE_TIMER);
NU_Delete_Timer(&wrap_timer);
#endif
}
/* On any OS where the hires counter may wrap, periodically */
/* Check and track the number of wraps. This must be called */
/* from and ISR or task that can't be pre-empted by anything */
/* that might get a high resolution timestamp. */
#if defined(RV_OS_VXWORKS)
static int rvTimeCheckWrap(int param)
{
#if defined(RV_VXWORKS_USETIMESTAMP)
/* Called for us by timestamp driver when wrap occurs */
hires_count = hires_count + (long long)sysTimestampPeriod();
#else
ULONG cur_tick;
cur_tick = tickGet();
if(cur_tick < last_tick)
wrap_count += 1;
last_tick = cur_tick;
wdStart(wrap_timer, param, rvTimeCheckWrap, param);
#endif
return 0;
}
#endif
#if defined(RV_OS_OSE)
/* This is horrible but OSE gives us no other choice */
/* Do the actual check in interrupt process, not tied to any */
/* harware, which gets signaled by the background process. */
/* This insures that the check and update are not interrupted. */
/* It requires including ose_i.h instead of ose.h but that would */
/* require a seperate file. Since we only call get_systime */
/* it doesn't hurt anything. */
OS_PROCESS(rvTimeCheckWrap)
{
OSTICK cur_tick;
cur_tick = get_systime(NULL);
if(cur_tick < last_tick)
wrap_count += 1;
last_tick = cur_tick;
}
/* Set up a background process to wait the proper amount of */
/* time then signal the interrupt process to do the work. It */
/* doesn't hurt performance and doesn't have a problem unless */
/* the system always runs at 100% (over a period of weeks). */
OS_PROCESS(rvTimeCheckWait)
{
for(;;) {
delay(wrapcheck_ms);
signal_fsem(wrap_check);
}
}
#endif
#if defined(RV_OS_NUCLEUS)
static VOID rvTimeCheckWrap(UNSIGNED param)
{
UNSIGNED cur_tick;
INT old_level;
/* Timer runs at lowest HISR level so make sure we don't switch */
old_level = NU_Local_Control_Interrupts(NU_DISABLE_INTERRUPTS);
cur_tick = NU_Retrieve_Clock();
if(cur_tick < last_tick)
wrap_count += 1;
last_tick = cur_tick;
NU_Local_Control_Interrupts(old_level);
}
#endif
/* Get time since epoch -- can vary due to system time adjustments */
/* returns time in seconds and fills result with seconds and nanoseconds */
/* if result is not NULL. Epoch is January 1, 1970 */
RvTime rvTimeGetEpochTime(RvTimespec *result)
{
RvTimespec t, *tp;
#if defined(RV_OS_REDHAT)
struct timeval tv;
#endif
#if defined(RV_OS_WIN32)
SYSTEMTIME systime;
FILETIME filetime;
ULARGE_INTEGER *uint_time;
#endif
#if defined(RV_OS_PSOS)
RvTm epochtm;
unsigned long datefield, timefield, ticks;
#endif
#if defined(RV_OS_OSE)
struct TimePair tvp;
#endif
#if defined(RV_OS_NUCLEUS)
long long curticks;
#endif
if(result == NULL) { /* use t if user doesn't provide result struct */
tp = &t;
} else tp = result;
#if defined(RV_OS_SOLARIS) || defined(RV_OS_TRU64) || defined(RV_OS_HPUX) || defined(RV_OS_VXWORKS)
clock_gettime(CLOCK_REALTIME, tp);
#endif
#if defined(RV_OS_REDHAT)
gettimeofday(&tv, NULL);
TIMEVAL_TO_TIMESPEC(&tv, tp);
#endif
#if defined(RV_OS_WIN32)
GetSystemTime(&systime);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -