Merge branch 'vxworks-tz-support' into 3.15
This commit is contained in:
+35
-34
@@ -24,40 +24,41 @@
|
||||
|
||||
# Site-specific environment settings
|
||||
|
||||
# Time service:
|
||||
# EPICS_TIMEZONE
|
||||
# Local timezone info for vxWorks and RTEMS. The format is
|
||||
# <name>::<minutesWest>:<startDST>:<endDST>
|
||||
# where <name> is only used by strftime() for %Z conversions,
|
||||
# and <startDST> and <endDST> are mmddhh - that is month,day,hour
|
||||
# e.g. for ANL in 2018: EPICS_TIMEZONE=CUS::360:031102:110402
|
||||
# The future dates below assume the rules don't get changed;
|
||||
# see http://www.timeanddate.com/time/dst/2018.html to check.
|
||||
#
|
||||
# DST for 2018 US: Mar 11 - Nov 04
|
||||
# EU: Mar 25 - Oct 28
|
||||
EPICS_TIMEZONE = CUS::360:031102:110402
|
||||
#EPICS_TIMEZONE = MET::-60:032502:102803
|
||||
#
|
||||
# DST for 2019 US: Mar 10 - Nov 03
|
||||
# EU: Mar 31 - Oct 27
|
||||
#EPICS_TIMEZONE = CUS::360:031002:110302
|
||||
#EPICS_TIMEZONE = MET::-60:033102:102703
|
||||
#
|
||||
# DST for 2020 US: Mar 08 - Nov 01
|
||||
# EU: Mar 29 - Oct 25
|
||||
#EPICS_TIMEZONE = CUS::360:030802:110102
|
||||
#EPICS_TIMEZONE = MET::-60:032902:102503
|
||||
#
|
||||
# DST for 2021 US: Mar 14 - Nov 07
|
||||
# EU: Mar 28 - Oct 31
|
||||
#EPICS_TIMEZONE = CUS::360:031402:110702
|
||||
#EPICS_TIMEZONE = MET::-60:032802:103103
|
||||
#
|
||||
# DST for 2022 US: Mar 13 - Nov 06
|
||||
# EU: Mar 27 - Oct 30
|
||||
#EPICS_TIMEZONE = CUS::360:031302:110602
|
||||
#EPICS_TIMEZONE = MET::-60:032702:103003
|
||||
## Time service:
|
||||
# EPICS_TZ
|
||||
# Local timezone rules for vxWorks and RTEMS. The value follows the Posix
|
||||
# TZ environment variable's Mm.n.d/h format (see the IBM link below for
|
||||
# details). If TZ hasn't already been set when the osdTime timeRegister()
|
||||
# C++ static constructor runs, this parameter will be copied into the TZ
|
||||
# environment variable. Once the OS clock has been synchronized to NTP the
|
||||
# routine tz2timezone() will be run to convert TZ into the TIMEZONE
|
||||
# variable format that VxWorks needs.
|
||||
# https://developer.ibm.com/articles/au-aix-posix/
|
||||
|
||||
# Japan Standard Time, no DST:
|
||||
#EPICS_TZ = "JST-9"
|
||||
|
||||
# Central European (Summer) Time:
|
||||
#EPICS_TZ = "CET-1CEST,M3.5.0/2,M10.5.0/3"
|
||||
|
||||
# Greenwich Mean/British Summer Time:
|
||||
#EPICS_TZ = "GMT0BST,M3.5.0/1,M10.5.0/2"
|
||||
|
||||
# US Eastern Standard/Daylight Time:
|
||||
#EPICS_TZ = "EST5EDT,M3.2.0/2,M11.1.0/2"
|
||||
|
||||
# US Central Standard/Daylight Time:
|
||||
EPICS_TZ = "CST6CDT,M3.2.0/2,M11.1.0/2"
|
||||
|
||||
# US Mountain Standard/Daylight Time:
|
||||
#EPICS_TZ = "MST7MDT,M3.2.0/2,M11.1.0/2"
|
||||
|
||||
# US Pacific Standard/Daylight Time:
|
||||
#EPICS_TZ = "PST8PDT,M3.2.0/2,M11.1.0/2"
|
||||
|
||||
# US Hawaiian Standard Time, no DST:
|
||||
#EPICS_TZ = "HST10"
|
||||
|
||||
|
||||
# EPICS_TS_NTP_INET
|
||||
# NTP time server ip address for VxWorks and RTEMS.
|
||||
|
||||
@@ -6,6 +6,37 @@ This version of EPICS Base has not been released yet.
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
### Replace EPICS_TIMEZONE with EPICS_TZ
|
||||
|
||||
The `EPICS_TIMEZONE` environment parameter provided time-zone information for
|
||||
the IOC's locale in the old ANSI format expected by VxWorks for its `TIMEZONE`
|
||||
environment variable, and can also used by RTEMS to set its `TZ` environment
|
||||
variable. However the `TIMEZONE` value has to be updated every year since it
|
||||
contains the exact dates of the daylight-savings time changes. The Posix TZ
|
||||
format that RTEMS uses contains rules that for calculating those dates, thus its
|
||||
value would only need updating if the rules (or the locale) are changed.
|
||||
|
||||
This release contains changes that replace the `EPICS_TIMEZONE` environment
|
||||
parameter with one called `EPICS_TZ` and a routine for VxWorks that calculates
|
||||
the `TIMEZONE` environment variable from the current `TZ` value. This routine
|
||||
will be run once at start-up, when the EPICS clock has synchronized to its NTP
|
||||
server. The calculations it contains were worked out and donated to EPICS by
|
||||
Larry Hoff in 2009; it is unforunate that it has taken 10 years for them to be
|
||||
integrated into Base.
|
||||
|
||||
The default value for the `EPICS_TZ` environment parameter is set in the Base
|
||||
configure/CONFIG_SITE_ENV file, which contains example settings for most EPICS
|
||||
sites that use VxWorks, and a link to a page describing the Posix TZ format for
|
||||
any locations that I missed.
|
||||
|
||||
If a VxWorks IOC runs continuously without being rebooted from December 31st to
|
||||
the start of daylight savings time the following year, its `TIMEZONE` value will
|
||||
be wrong as it was calculated for the previous year. This only affects times
|
||||
that are converted to a string on the IOC however and is easily fixed; just run
|
||||
the command `tz2timezone()` on the VxWorks shell and the calculation will be
|
||||
redone for the current year. IOCs that get rebooted at least once before the
|
||||
start of summer time will not need this to be done.
|
||||
|
||||
### Added new decimation channel filter
|
||||
|
||||
A new server-side filter has been added to the IOC for reducing the number
|
||||
|
||||
@@ -581,25 +581,11 @@ Init (rtems_task_argument ignored)
|
||||
printf ("***** Can't set time: %s\n", rtems_status_text (sc));
|
||||
}
|
||||
if (getenv("TZ") == NULL) {
|
||||
const char *tzp = envGetConfigParamPtr(&EPICS_TIMEZONE);
|
||||
if (tzp == NULL) {
|
||||
printf("Warning -- no timezone information available -- times will be displayed as GMT.\n");
|
||||
}
|
||||
else {
|
||||
char tz[10];
|
||||
int minWest, toDst = 0, fromDst = 0;
|
||||
if(sscanf(tzp, "%9[^:]::%d:%d:%d", tz, &minWest, &toDst, &fromDst) < 2) {
|
||||
printf("Warning: EPICS_TIMEZONE (%s) unrecognizable -- times will be displayed as GMT.\n", tzp);
|
||||
}
|
||||
else {
|
||||
char posixTzBuf[40];
|
||||
char *p = posixTzBuf;
|
||||
p += sprintf(p, "%cST%d:%.2d", tz[0], minWest/60, minWest%60);
|
||||
if (toDst != fromDst)
|
||||
p += sprintf(p, "%cDT", tz[0]);
|
||||
epicsEnvSet("TZ", posixTzBuf);
|
||||
}
|
||||
}
|
||||
const char *tzp = envGetConfigParamPtr(&EPICS_TZ);
|
||||
if (!tzp || *tzp)
|
||||
printf("Warning: No timezone information, times will be displayed in UTC.\n");
|
||||
else
|
||||
epicsEnvSet("TZ", tzp);
|
||||
}
|
||||
tzset();
|
||||
osdTimeRegister();
|
||||
|
||||
Vendored
+1
-1
@@ -61,7 +61,7 @@ epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PORT;
|
||||
epicsShareExtern const ENV_PARAM EPICS_BUILD_COMPILER_CLASS;
|
||||
epicsShareExtern const ENV_PARAM EPICS_BUILD_OS_CLASS;
|
||||
epicsShareExtern const ENV_PARAM EPICS_BUILD_TARGET_ARCH;
|
||||
epicsShareExtern const ENV_PARAM EPICS_TIMEZONE;
|
||||
epicsShareExtern const ENV_PARAM EPICS_TZ;
|
||||
epicsShareExtern const ENV_PARAM EPICS_TS_NTP_INET;
|
||||
epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_PORT;
|
||||
epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_INET;
|
||||
|
||||
@@ -77,7 +77,7 @@ Com_SRCS += epicsGeneralTime.c
|
||||
|
||||
# Time providers
|
||||
Com_SRCS += osiClockTime.c
|
||||
Com_SRCS_vxWorks += osiNTPTime.c
|
||||
Com_SRCS_vxWorks += osiNTPTime.c tz2timezone.c
|
||||
Com_SRCS_RTEMS += osiNTPTime.c
|
||||
|
||||
ifeq ($(OS_CLASS),vxWorks)
|
||||
|
||||
@@ -952,7 +952,8 @@ extern "C" {
|
||||
try {
|
||||
local_tm_nano_sec tmns = epicsTime (*pSrc);
|
||||
*pDest = tmns.ansi_tm;
|
||||
*pNSecDest = tmns.nSec;
|
||||
if (pNSecDest)
|
||||
*pNSecDest = tmns.nSec;
|
||||
}
|
||||
catch (...) {
|
||||
return epicsTimeERROR;
|
||||
@@ -964,7 +965,8 @@ extern "C" {
|
||||
try {
|
||||
gm_tm_nano_sec gmtmns = epicsTime (*pSrc);
|
||||
*pDest = gmtmns.ansi_tm;
|
||||
*pNSecDest = gmtmns.nSec;
|
||||
if (pNSecDest)
|
||||
*pNSecDest = gmtmns.nSec;
|
||||
}
|
||||
catch (...) {
|
||||
return epicsTimeERROR;
|
||||
|
||||
@@ -24,22 +24,38 @@
|
||||
|
||||
#define NTP_REQUEST_TIMEOUT 4 /* seconds */
|
||||
|
||||
extern "C" {
|
||||
int tz2timezone(void);
|
||||
}
|
||||
|
||||
static char sntp_sync_task[] = "ipsntps";
|
||||
static char ntp_daemon[] = "ipntpd";
|
||||
|
||||
static const char *pserverAddr = NULL;
|
||||
static CLOCKTIME_SYNCHOOK prevHook;
|
||||
|
||||
extern char* sysBootLine;
|
||||
|
||||
static void timeSync(int synchronized) {
|
||||
if (!tz2timezone())
|
||||
ClockTime_syncHook = prevHook; /* Don't call me again */
|
||||
}
|
||||
|
||||
static int timeRegister(void)
|
||||
{
|
||||
/* If TIMEZONE not defined, set it from EPICS_TIMEZONE */
|
||||
if (getenv("TIMEZONE") == NULL) {
|
||||
const char *timezone = envGetConfigParamPtr(&EPICS_TIMEZONE);
|
||||
if (timezone == NULL) {
|
||||
printf("timeRegister: No Time Zone Information\n");
|
||||
} else {
|
||||
epicsEnvSet("TIMEZONE", timezone);
|
||||
/* If TZ not defined, set it from EPICS_TZ */
|
||||
if (getenv("TZ") == NULL) {
|
||||
const char *tz = envGetConfigParamPtr(&EPICS_TZ);
|
||||
|
||||
if (tz && *tz) {
|
||||
epicsEnvSet("TZ", tz);
|
||||
|
||||
/* Call tz2timezone() once we know what year it is */
|
||||
prevHook = ClockTime_syncHook;
|
||||
ClockTime_syncHook = timeSync;
|
||||
}
|
||||
else if (getenv("TIMEZONE") == NULL)
|
||||
printf("timeRegister: No Time Zone Information available\n");
|
||||
}
|
||||
|
||||
// Define EPICS_TS_FORCE_NTPTIME to force use of NTPTime provider
|
||||
@@ -57,7 +73,7 @@ static int timeRegister(void)
|
||||
}
|
||||
|
||||
if (useNTP) {
|
||||
// Start NTP first so it can be used to sync SysTime
|
||||
// Start NTP first so it can be used to sync ClockTime
|
||||
NTPTime_Init(100);
|
||||
ClockTime_Init(CLOCKTIME_SYNC);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2009 Brookhaven Science Associates, as Operator of
|
||||
* Brookhaven National Laboratory.
|
||||
* Copyright (c) 2019 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* Authors: Larry Hoff, Andrew Johnson <anj@anl.gov>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file exports a single function "int tz2timezone(void)" which reads
|
||||
* the TZ environment variable (defined by POSIX) and converts it to the
|
||||
* TIMEZONE environment variable defined by ANSI. The latter is used by
|
||||
* VxWorks "time" functions, is largely deprecated in other computing
|
||||
* environments, has limitations, and is difficult to maintain. This holds
|
||||
* out the possibility of "pretending" that VxWorks supports "TZ" - until
|
||||
* such time as it actually does.
|
||||
*
|
||||
* For simplicity, only the "POSIX standard form" of TZ will be supported.
|
||||
* Even that is complicated enough (see following spec). Furthermore,
|
||||
* only the "M" form of DST start and stop dates are supported.
|
||||
*
|
||||
* TZ = zone[-]offset[dst[offset],start[/time],end[/time]]
|
||||
*
|
||||
* zone
|
||||
* A three or more letter name for the timezone in normal (winter) time.
|
||||
*
|
||||
* [-]offset
|
||||
* A signed time giving the offset of the time zone westwards from
|
||||
* Greenwich. The time has the form hh[:mm[:ss]] with a one of two
|
||||
* digit hour, and optional two digit minutes and seconds.
|
||||
*
|
||||
* dst
|
||||
* The name of the time zone when daylight saving is in effect. It may
|
||||
* be followed by an offset giving how big the adjustment is, required
|
||||
* if different than the default of 1 hour.
|
||||
*
|
||||
* start/time,end/time
|
||||
* Specify the start and end of the daylight saving period. The start
|
||||
* and end fields indicate on what day the changeover occurs, and must
|
||||
* be in this format:
|
||||
*
|
||||
* Mm.n.d
|
||||
* This indicates month m, the n-th occurrence of day d, where
|
||||
* 1 <= m <= 12, 1 <= n <= 5, 0 <= d <= 6, 0=Sunday
|
||||
* The 5th occurrence means the last occurrence of that day in a
|
||||
* month. So M4.1.0 is the first Sunday in April, M9.5.0 is the
|
||||
* last Sunday in September.
|
||||
*
|
||||
* The time field indicates what hour the changeover occurs on the given
|
||||
* day (TIMEZONE only supports switching on the hour).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <envLib.h> /* getenv() */
|
||||
#include <stdio.h> /* printf() */
|
||||
#include <string.h> /* strchr() */
|
||||
#include <ctype.h> /* isalpha() */
|
||||
|
||||
#include <epicsTime.h>
|
||||
|
||||
/* for reference: TZ syntax, example, and TIMEZONE example
|
||||
* std offset dst [offset],start[/time],end[/time]
|
||||
* CST6CDT5,M3.2.0,M11.1.0
|
||||
* EST+5EDT,M4.1.0/2,M10.5.0/2
|
||||
*
|
||||
* std <unused> offset start stop
|
||||
* TIMEZONE=EST::300:030802:110102
|
||||
*/
|
||||
|
||||
static int extractDate(const char *tz, struct tm *current, char *s)
|
||||
{
|
||||
static const int startdays[] = {
|
||||
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
||||
};
|
||||
static const int molengths[] = {
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
|
||||
int month, week, weekday, hour=2; /* default=2AM */
|
||||
int jan1wday, wday, mday;
|
||||
|
||||
/* Require 'M' format */
|
||||
if (*++tz != 'M') {
|
||||
printf("tz2timezone: Unsupported date type, need 'M' format\n");
|
||||
return ERROR;
|
||||
}
|
||||
tz++;
|
||||
|
||||
if (sscanf(tz, "%d.%d.%d/%d", &month, &week, &weekday, &hour) < 3)
|
||||
return ERROR; /* something important missing */
|
||||
|
||||
if (month == 0 || month>12 ||
|
||||
week < 1 || week > 5 ||
|
||||
weekday < 0 || weekday > 6 ||
|
||||
hour < 0 || hour > 23)
|
||||
return ERROR;
|
||||
|
||||
/* Now for some brute-force calendar calculations... */
|
||||
/* start month is in "month", and the day is "weekday", but
|
||||
we need to know when that weekday first occurs in that month */
|
||||
/* Let's start with weekday on Jan. 1 */
|
||||
jan1wday = (7 + current->tm_wday - (current->tm_yday % 7)) % 7;
|
||||
|
||||
/* We need to know if it is a leap year (and if it matters) */
|
||||
/* Let's assume that we're working with a date between 1901 and 2099,
|
||||
that way we don't have to think about the "century exception".
|
||||
If this code is still running (unchanged) in 2100, I'll be stunned
|
||||
(and 139 years old) */
|
||||
wday = (jan1wday + startdays[month-1] +
|
||||
((month > 2 && (current->tm_year % 4 == 0)) ? 1 : 0)) % 7;
|
||||
|
||||
/* Let's see on what day-of-the-month the first target weekday occurs
|
||||
(counting from 1). The result is a number between 1 and 7, inclusive. */
|
||||
mday = 1 + ((7 + weekday - wday) % 7);
|
||||
|
||||
/* Next, we add the week offset. If we overflow the month, we subtract
|
||||
one week */
|
||||
mday += 7 * (week - 1);
|
||||
if (mday > molengths[month-1])
|
||||
mday -= 7;
|
||||
|
||||
/* Should I handle Feb 29? I'm willing to gamble that no one in their right
|
||||
mind would schedule a time change to occur on Feb. 29. If so, we'll be a
|
||||
week early */
|
||||
sprintf(s, "%02d%02d%02d", month, mday, hour);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
static const char *getTime(const char *s, int *time)
|
||||
{
|
||||
/* Time format is [+/-]hh[:mm][:ss] followed by the next zone name */
|
||||
|
||||
*time = 0;
|
||||
|
||||
if (!isdigit((int) s[0]))
|
||||
return s; /* no number here... */
|
||||
|
||||
if (!isdigit((int) s[1])) { /* single digit form */
|
||||
*time = s[0] - '0';
|
||||
return s + 1;
|
||||
}
|
||||
|
||||
if (isdigit((int) s[1])) { /* two digit form */
|
||||
*time = 10 * (s[0] - '0') + (s[1] - '0');
|
||||
return s + 2;
|
||||
}
|
||||
|
||||
return s; /* does not follow supported form */
|
||||
}
|
||||
|
||||
int tz2timezone(void)
|
||||
{
|
||||
const char *tz = getenv("TZ");
|
||||
/* Spec. says that zone names must be at least 3 chars.
|
||||
* I've never seen a longer zone name, but I'll allocate
|
||||
* 40 chars. If you live in a zone with a longer name,
|
||||
* you may want to think about the benefits of relocation.
|
||||
*/
|
||||
char zone[40];
|
||||
char start[10], stop[10]; /* only really need 7 bytes now */
|
||||
int hours = 0, minutes = 0, sign = 1;
|
||||
/* This is more than enough, even with a 40-char zone
|
||||
* name, and 4-char offset.
|
||||
*/
|
||||
char timezone[100];
|
||||
int i = 0; /* You *always need an "i" :-) */
|
||||
epicsTimeStamp now;
|
||||
struct tm current;
|
||||
|
||||
/* First let's get the current time. We need the year to
|
||||
* compute the start/stop dates for DST.
|
||||
*/
|
||||
if (epicsTimeGetCurrent(&now) ||
|
||||
epicsTimeToTM(¤t, NULL, &now))
|
||||
return ERROR;
|
||||
|
||||
/* Make sure TZ exists.
|
||||
* Spec. says that ZONE must be at least 3 chars.
|
||||
*/
|
||||
if ((!tz) || (strlen(tz) < 3))
|
||||
return ERROR;
|
||||
|
||||
/* OK, now a bunch of brute-force parsing. My brain hurts if
|
||||
* I try to think of an elegant regular expression for the
|
||||
* string.
|
||||
*/
|
||||
|
||||
/* Start extracting zone name, must be alpha */
|
||||
while ((i < sizeof(zone) - 1) && isalpha((int) *tz)) {
|
||||
zone[i++] = *tz++;
|
||||
}
|
||||
if (i < 3)
|
||||
return ERROR; /* Too short, not a real zone name? */
|
||||
|
||||
zone[i] = 0; /* Nil-terminate (for now) */
|
||||
|
||||
/* Now extract offset time. The format is [+/-]hh[:mm[:ss]]
|
||||
* Recall that TIMEZONE doesn't support seconds....
|
||||
*/
|
||||
if (*tz == '-') {
|
||||
sign = -1;
|
||||
tz++;
|
||||
}
|
||||
else if (*tz == '+') {
|
||||
tz++;
|
||||
}
|
||||
|
||||
/* Need a digit now */
|
||||
if (!isdigit((int) *tz))
|
||||
return ERROR;
|
||||
|
||||
/* First get the hours */
|
||||
tz = getTime(tz, &hours);
|
||||
if (hours > 24)
|
||||
return ERROR;
|
||||
|
||||
if (*tz == ':') { /* There is a minutes part */
|
||||
/* Need another digit now */
|
||||
if (!isdigit((int) *++tz))
|
||||
return ERROR;
|
||||
|
||||
/* Extract the minutes */
|
||||
tz = getTime(tz, &minutes);
|
||||
if (minutes > 60)
|
||||
return ERROR;
|
||||
|
||||
/* Skip any seconds part */
|
||||
if (*tz == ':') {
|
||||
int seconds;
|
||||
tz = getTime(tz + 1, &seconds);
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract any DST zone name, must be alpha */
|
||||
if (isalpha((int) *tz)) {
|
||||
zone[i++] = '/'; /* Separate the names */
|
||||
|
||||
while ((i < sizeof(zone) - 1) && isalpha((int) *tz)) {
|
||||
zone[i++] = *tz++;
|
||||
}
|
||||
zone[i] = 0; /* Nil-terminate */
|
||||
}
|
||||
|
||||
minutes += hours * 60;
|
||||
minutes *= sign;
|
||||
|
||||
/* Look for start/stop dates - require neither or both */
|
||||
tz = strchr(tz, ',');
|
||||
if (!tz) { /* No daylight savings time here */
|
||||
/* Format the env. variable */
|
||||
sprintf(timezone, "TIMEZONE=%s::%d", zone, minutes);
|
||||
}
|
||||
else {
|
||||
if (extractDate(tz, ¤t, start) != OK)
|
||||
return ERROR;
|
||||
|
||||
tz = strchr(tz + 1, ',');
|
||||
if (!tz)
|
||||
return ERROR;
|
||||
if (extractDate(tz, ¤t, stop) != OK)
|
||||
return ERROR;
|
||||
|
||||
/* Format the env. variable */
|
||||
sprintf(timezone, "TIMEZONE=%s::%d:%s:%s", zone, minutes, start, stop);
|
||||
}
|
||||
|
||||
/* Make it live! */
|
||||
putenv(timezone);
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -23,7 +23,8 @@
|
||||
#include "taskwd.h"
|
||||
|
||||
#define NSEC_PER_SEC 1000000000
|
||||
#define ClockTimeSyncInterval_value 60.0
|
||||
#define ClockTimeSyncInterval_initial 1.0
|
||||
#define ClockTimeSyncInterval_normal 60.0
|
||||
|
||||
|
||||
static struct {
|
||||
@@ -79,7 +80,7 @@ static void ClockTime_InitOnce(void *pfirst)
|
||||
|
||||
ClockTimePvt.loopEvent = epicsEventMustCreate(epicsEventEmpty);
|
||||
ClockTimePvt.lock = epicsMutexCreate();
|
||||
ClockTimePvt.ClockTimeSyncInterval = 1.0; /* First sync */
|
||||
ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_initial;
|
||||
|
||||
epicsAtExit(ClockTime_Shutdown, NULL);
|
||||
|
||||
@@ -148,6 +149,8 @@ void ClockTime_GetProgramStart(epicsTimeStamp *pDest)
|
||||
/* Synchronization thread */
|
||||
|
||||
#if defined(vxWorks) || defined(__rtems__)
|
||||
CLOCKTIME_SYNCHOOK ClockTime_syncHook = NULL;
|
||||
|
||||
static void ClockTimeSync(void *dummy)
|
||||
{
|
||||
taskwdInsert(0, NULL, NULL);
|
||||
@@ -179,11 +182,16 @@ static void ClockTimeSync(void *dummy)
|
||||
ClockTimePvt.syncTime = timeNow;
|
||||
epicsMutexUnlock(ClockTimePvt.lock);
|
||||
|
||||
ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_value;
|
||||
if (ClockTime_syncHook)
|
||||
ClockTime_syncHook(1);
|
||||
|
||||
ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_normal;
|
||||
}
|
||||
}
|
||||
|
||||
ClockTimePvt.synchronized = 0;
|
||||
if (ClockTime_syncHook)
|
||||
ClockTime_syncHook(0);
|
||||
taskwdRemove(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,12 @@ void ClockTime_Init(int synchronize);
|
||||
void ClockTime_Shutdown(void *dummy);
|
||||
int ClockTime_Report(int level);
|
||||
|
||||
#if defined(vxWorks) || defined(__rtems__)
|
||||
typedef void (* CLOCKTIME_SYNCHOOK)(int synchronized);
|
||||
|
||||
extern CLOCKTIME_SYNCHOOK ClockTime_syncHook;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user