Experimental Physics and Industrial Control System
Subject: |
[Merge] ~anj/epics-base/+git/base-3.15:vxworks-tz-support into epics-base:3.15 |
From: |
Andrew Johnson via Core-talk <[email protected]> |
To: |
[email protected] |
Date: |
Fri, 07 Jun 2019 20:43:22 -0000 |
Andrew Johnson has proposed merging ~anj/epics-base/+git/base-3.15:vxworks-tz-support into epics-base:3.15.
Requested reviews:
Dirk Zimoch (dirk.zimoch)
For more details, see:
https://code.launchpad.net/~anj/epics-base/+git/base-3.15/+merge/368570
Integrate some code Larry Hoff sent me 10 years ago that avoids the need to adjust the value of TIMEZONE every year...
--
Your team EPICS Core Developers is subscribed to branch epics-base:3.15.
diff --git a/configure/CONFIG_SITE_ENV b/configure/CONFIG_SITE_ENV
index 49331f9..0084679 100644
--- a/configure/CONFIG_SITE_ENV
+++ b/configure/CONFIG_SITE_ENV
@@ -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.
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 8ed4e04..f6daa49 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -16,6 +16,38 @@
<!-- Insert new items immediately below here ... -->
+<h3>Replace EPICS_TIMEZONE with EPICS_TZ</h3>
+
+<p>The <tt>EPICS_TIMEZONE</tt> environment parameter provided time-zone
+information for the IOC's locale in the old ANSI format expected by VxWorks for
+its <tt>TIMEZONE</tt> environment variable, and can also used by RTEMS to set
+its <tt>TZ</tt> environment variable. However the <tt>TIMEZONE</tt> 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.</p>
+
+<p>This release contains changes that replace the <tt>EPICS_TIMEZONE</tt>
+environment parameter with one called <tt>EPICS_TZ</tt> and a routine for
+VxWorks that calculates the <tt>TIMEZONE</tt> environment variable from the
+current <tt>TZ</tt> 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.</p>
+
+<p>The default value for the <tt>EPICS_TZ</tt> 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.</p>
+
+<p>If a VxWorks IOC runs continuously without being rebooted from December 31st
+to the start of daylight savings time the following year, its <tt>TIMEZONE</tt>
+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 <tt>tz2timezone()</tt> 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.</p>
+
<h3>Cleaning up with Multiple CA contexts in a Process</h3>
<p>Bruno Martins reported a problem with the CA client library at shutdown in a
diff --git a/src/libCom/RTEMS/rtems_init.c b/src/libCom/RTEMS/rtems_init.c
index 2b909ab..dcb6daa 100644
--- a/src/libCom/RTEMS/rtems_init.c
+++ b/src/libCom/RTEMS/rtems_init.c
@@ -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();
diff --git a/src/libCom/env/envDefs.h b/src/libCom/env/envDefs.h
index 20f0eb2..588cecd 100644
--- a/src/libCom/env/envDefs.h
+++ b/src/libCom/env/envDefs.h
@@ -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;
diff --git a/src/libCom/osi/Makefile b/src/libCom/osi/Makefile
index c06a862..e05aec3 100644
--- a/src/libCom/osi/Makefile
+++ b/src/libCom/osi/Makefile
@@ -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)
diff --git a/src/libCom/osi/epicsTime.cpp b/src/libCom/osi/epicsTime.cpp
index af4fae2..9f54427 100644
--- a/src/libCom/osi/epicsTime.cpp
+++ b/src/libCom/osi/epicsTime.cpp
@@ -955,7 +955,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;
@@ -967,7 +968,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;
diff --git a/src/libCom/osi/os/vxWorks/osdTime.cpp b/src/libCom/osi/os/vxWorks/osdTime.cpp
index 4db375f..eb144c1 100644
--- a/src/libCom/osi/os/vxWorks/osdTime.cpp
+++ b/src/libCom/osi/os/vxWorks/osdTime.cpp
@@ -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 {
diff --git a/src/libCom/osi/os/vxWorks/tz2timezone.c b/src/libCom/osi/os/vxWorks/tz2timezone.c
new file mode 100644
index 0000000..df8db85
--- /dev/null
+++ b/src/libCom/osi/os/vxWorks/tz2timezone.c
@@ -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 <[email protected]>
+ */
+
+/*
+ * 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;
+}
diff --git a/src/libCom/osi/osiClockTime.c b/src/libCom/osi/osiClockTime.c
index fb9d153..01958b2 100644
--- a/src/libCom/osi/osiClockTime.c
+++ b/src/libCom/osi/osiClockTime.c
@@ -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
diff --git a/src/libCom/osi/osiClockTime.h b/src/libCom/osi/osiClockTime.h
index 17eacab..2359888 100644
--- a/src/libCom/osi/osiClockTime.h
+++ b/src/libCom/osi/osiClockTime.h
@@ -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
- Replies:
- Re: [Merge] ~anj/epics-base/+git/base-3.15:vxworks-tz-support into epics-base:3.15 mdavidsaver via Core-talk
- Re: [Merge] ~anj/epics-base/+git/base-3.15:vxworks-tz-support into epics-base:3.15 Andrew Johnson via Core-talk
- Re: [Merge] ~anj/epics-base/+git/base-3.15:vxworks-tz-support into epics-base:3.15 Andrew Johnson via Core-talk
- [Merge] ~anj/epics-base/+git/base-3.15:vxworks-tz-support into epics-base:3.15 Andrew Johnson via Core-talk
- [Merge] ~anj/epics-base/+git/base-3.15:vxworks-tz-support into epics-base:3.15 noreply--- via Core-talk
- Navigate by Date:
- Prev:
Re: [Merge] ~epics-core/epics-base/+git/asLib:as-hostname into epics-base:7.0 mdavidsaver via Core-talk
- Next:
Re: [Merge] ~info-martin-konrad/epics-base:fix-compiler-warnings into epics-base:3.15 Andrew Johnson via Core-talk
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
<2019>
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Build completed: EPICS Base base-3.15-400 AppVeyor via Core-talk
- Next:
Re: [Merge] ~anj/epics-base/+git/base-3.15:vxworks-tz-support into epics-base:3.15 mdavidsaver via Core-talk
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
<2019>
2020
2021
2022
2023
2024