Merge ~anj/epics-base/+git/base-3.15:vxworks-tz-support into ~epics-core/epics-base/+git/epics-base:3.15

Proposed by Andrew Johnson
Status: Merged
Approved by: Andrew Johnson
Approved revision: d3a8a49552ca7930aa9a5ab34ceb1de9cd25ccf4
Merged at revision: 3881328f2f7a0ad9853ed14c3d0fd5e97d02fafe
Proposed branch: ~anj/epics-base/+git/base-3.15:vxworks-tz-support
Merge into: ~epics-core/epics-base/+git/epics-base:3.15
Diff against target: 618 lines (+397/-68)
10 files modified
configure/CONFIG_SITE_ENV (+35/-34)
documentation/RELEASE_NOTES.html (+32/-0)
src/libCom/RTEMS/rtems_init.c (+5/-19)
src/libCom/env/envDefs.h (+1/-1)
src/libCom/osi/Makefile (+1/-1)
src/libCom/osi/epicsTime.cpp (+4/-2)
src/libCom/osi/os/vxWorks/osdTime.cpp (+24/-8)
src/libCom/osi/os/vxWorks/tz2timezone.c (+278/-0)
src/libCom/osi/osiClockTime.c (+11/-3)
src/libCom/osi/osiClockTime.h (+6/-0)
Reviewer Review Type Date Requested Status
Andrew Johnson Approve
Dirk Zimoch Pending
Review via email: mp+368570@code.launchpad.net

Description of the change

Integrate some code Larry Hoff sent me 10 years ago that avoids the need to adjust the value of TIMEZONE every year...

To post a comment you must log in.
Revision history for this message
mdavidsaver (mdavidsaver) wrote :

This looks like almost a no-op for RTEMS, so I see no problem. Are the changes to epicsTime.cpp a bug fix?

Revision history for this message
Andrew Johnson (anj) wrote :

MAD: The RTEMS code will need adjusting when merging up to 7.0, try to add the tzset() as suggested.

Revision history for this message
Andrew Johnson (anj) wrote :

Group 10/4: No major issues.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 @@
2424
25# Site-specific environment settings25# Site-specific environment settings
2626
27# Time service:27## Time service:
28# EPICS_TIMEZONE28# EPICS_TZ
29# Local timezone info for vxWorks and RTEMS. The format is29# Local timezone rules for vxWorks and RTEMS. The value follows the Posix
30# <name>::<minutesWest>:<startDST>:<endDST>30# TZ environment variable's Mm.n.d/h format (see the IBM link below for
31# where <name> is only used by strftime() for %Z conversions,31# details). If TZ hasn't already been set when the osdTime timeRegister()
32# and <startDST> and <endDST> are mmddhh - that is month,day,hour32# C++ static constructor runs, this parameter will be copied into the TZ
33# e.g. for ANL in 2018: EPICS_TIMEZONE=CUS::360:031102:11040233# environment variable. Once the OS clock has been synchronized to NTP the
34# The future dates below assume the rules don't get changed;34# routine tz2timezone() will be run to convert TZ into the TIMEZONE
35# see http://www.timeanddate.com/time/dst/2018.html to check.35# variable format that VxWorks needs.
36#36# https://developer.ibm.com/articles/au-aix-posix/
37# DST for 2018 US: Mar 11 - Nov 0437
38# EU: Mar 25 - Oct 2838# Japan Standard Time, no DST:
39EPICS_TIMEZONE = CUS::360:031102:11040239#EPICS_TZ = "JST-9"
40#EPICS_TIMEZONE = MET::-60:032502:10280340
41#41# Central European (Summer) Time:
42# DST for 2019 US: Mar 10 - Nov 0342#EPICS_TZ = "CET-1CEST,M3.5.0/2,M10.5.0/3"
43# EU: Mar 31 - Oct 2743
44#EPICS_TIMEZONE = CUS::360:031002:11030244# Greenwich Mean/British Summer Time:
45#EPICS_TIMEZONE = MET::-60:033102:10270345#EPICS_TZ = "GMT0BST,M3.5.0/1,M10.5.0/2"
46#46
47# DST for 2020 US: Mar 08 - Nov 0147# US Eastern Standard/Daylight Time:
48# EU: Mar 29 - Oct 2548#EPICS_TZ = "EST5EDT,M3.2.0/2,M11.1.0/2"
49#EPICS_TIMEZONE = CUS::360:030802:11010249
50#EPICS_TIMEZONE = MET::-60:032902:10250350# US Central Standard/Daylight Time:
51#51EPICS_TZ = "CST6CDT,M3.2.0/2,M11.1.0/2"
52# DST for 2021 US: Mar 14 - Nov 0752
53# EU: Mar 28 - Oct 3153# US Mountain Standard/Daylight Time:
54#EPICS_TIMEZONE = CUS::360:031402:11070254#EPICS_TZ = "MST7MDT,M3.2.0/2,M11.1.0/2"
55#EPICS_TIMEZONE = MET::-60:032802:10310355
56#56# US Pacific Standard/Daylight Time:
57# DST for 2022 US: Mar 13 - Nov 0657#EPICS_TZ = "PST8PDT,M3.2.0/2,M11.1.0/2"
58# EU: Mar 27 - Oct 3058
59#EPICS_TIMEZONE = CUS::360:031302:11060259# US Hawaiian Standard Time, no DST:
60#EPICS_TIMEZONE = MET::-60:032702:10300360#EPICS_TZ = "HST10"
61
6162
62# EPICS_TS_NTP_INET63# EPICS_TS_NTP_INET
63# NTP time server ip address for VxWorks and RTEMS.64# 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 @@
1616
17<!-- Insert new items immediately below here ... -->17<!-- Insert new items immediately below here ... -->
1818
19<h3>Replace EPICS_TIMEZONE with EPICS_TZ</h3>
20
21<p>The <tt>EPICS_TIMEZONE</tt> environment parameter provided time-zone
22information for the IOC's locale in the old ANSI format expected by VxWorks for
23its <tt>TIMEZONE</tt> environment variable, and can also used by RTEMS to set
24its <tt>TZ</tt> environment variable. However the <tt>TIMEZONE</tt> value has to
25be updated every year since it contains the exact dates of the daylight-savings
26time changes. The Posix TZ format that RTEMS uses contains rules that for
27calculating those dates, thus its value would only need updating if the rules
28(or the locale) are changed.</p>
29
30<p>This release contains changes that replace the <tt>EPICS_TIMEZONE</tt>
31environment parameter with one called <tt>EPICS_TZ</tt> and a routine for
32VxWorks that calculates the <tt>TIMEZONE</tt> environment variable from the
33current <tt>TZ</tt> value. This routine will be run once at start-up, when the
34EPICS clock has synchronized to its NTP server. The calculations it contains
35were worked out and donated to EPICS by Larry Hoff in 2009; it is unforunate
36that it has taken 10 years for them to be integrated into Base.</p>
37
38<p>The default value for the <tt>EPICS_TZ</tt> environment parameter is set in
39the Base configure/CONFIG_SITE_ENV file, which contains example settings for
40most EPICS sites that use VxWorks, and a link to a page describing the Posix TZ
41format for any locations that I missed.</p>
42
43<p>If a VxWorks IOC runs continuously without being rebooted from December 31st
44to the start of daylight savings time the following year, its <tt>TIMEZONE</tt>
45value will be wrong as it was calculated for the previous year. This only
46affects times that are converted to a string on the IOC however and is easily
47fixed; just run the command <tt>tz2timezone()</tt> on the VxWorks shell and the
48calculation will be redone for the current year. IOCs that get rebooted at least
49once before the start of summer time will not need this to be done.</p>
50
19<h3>Cleaning up with Multiple CA contexts in a Process</h3>51<h3>Cleaning up with Multiple CA contexts in a Process</h3>
2052
21<p>Bruno Martins reported a problem with the CA client library at shutdown in a53<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)
581 printf ("***** Can't set time: %s\n", rtems_status_text (sc));581 printf ("***** Can't set time: %s\n", rtems_status_text (sc));
582 }582 }
583 if (getenv("TZ") == NULL) {583 if (getenv("TZ") == NULL) {
584 const char *tzp = envGetConfigParamPtr(&EPICS_TIMEZONE);584 const char *tzp = envGetConfigParamPtr(&EPICS_TZ);
585 if (tzp == NULL) {585 if (!tzp || *tzp)
586 printf("Warning -- no timezone information available -- times will be displayed as GMT.\n");586 printf("Warning: No timezone information, times will be displayed in UTC.\n");
587 }587 else
588 else {588 epicsEnvSet("TZ", tzp);
589 char tz[10];
590 int minWest, toDst = 0, fromDst = 0;
591 if(sscanf(tzp, "%9[^:]::%d:%d:%d", tz, &minWest, &toDst, &fromDst) < 2) {
592 printf("Warning: EPICS_TIMEZONE (%s) unrecognizable -- times will be displayed as GMT.\n", tzp);
593 }
594 else {
595 char posixTzBuf[40];
596 char *p = posixTzBuf;
597 p += sprintf(p, "%cST%d:%.2d", tz[0], minWest/60, minWest%60);
598 if (toDst != fromDst)
599 p += sprintf(p, "%cDT", tz[0]);
600 epicsEnvSet("TZ", posixTzBuf);
601 }
602 }
603 }589 }
604 tzset();590 tzset();
605 osdTimeRegister();591 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;
61epicsShareExtern const ENV_PARAM EPICS_BUILD_COMPILER_CLASS;61epicsShareExtern const ENV_PARAM EPICS_BUILD_COMPILER_CLASS;
62epicsShareExtern const ENV_PARAM EPICS_BUILD_OS_CLASS;62epicsShareExtern const ENV_PARAM EPICS_BUILD_OS_CLASS;
63epicsShareExtern const ENV_PARAM EPICS_BUILD_TARGET_ARCH;63epicsShareExtern const ENV_PARAM EPICS_BUILD_TARGET_ARCH;
64epicsShareExtern const ENV_PARAM EPICS_TIMEZONE;64epicsShareExtern const ENV_PARAM EPICS_TZ;
65epicsShareExtern const ENV_PARAM EPICS_TS_NTP_INET;65epicsShareExtern const ENV_PARAM EPICS_TS_NTP_INET;
66epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_PORT;66epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_PORT;
67epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_INET;67epicsShareExtern 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
7777
78# Time providers78# Time providers
79Com_SRCS += osiClockTime.c79Com_SRCS += osiClockTime.c
80Com_SRCS_vxWorks += osiNTPTime.c80Com_SRCS_vxWorks += osiNTPTime.c tz2timezone.c
81Com_SRCS_RTEMS += osiNTPTime.c81Com_SRCS_RTEMS += osiNTPTime.c
8282
83ifeq ($(OS_CLASS),vxWorks)83ifeq ($(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" {
955 try {955 try {
956 local_tm_nano_sec tmns = epicsTime (*pSrc);956 local_tm_nano_sec tmns = epicsTime (*pSrc);
957 *pDest = tmns.ansi_tm;957 *pDest = tmns.ansi_tm;
958 *pNSecDest = tmns.nSec;958 if (pNSecDest)
959 *pNSecDest = tmns.nSec;
959 }960 }
960 catch (...) {961 catch (...) {
961 return epicsTimeERROR;962 return epicsTimeERROR;
@@ -967,7 +968,8 @@ extern "C" {
967 try {968 try {
968 gm_tm_nano_sec gmtmns = epicsTime (*pSrc);969 gm_tm_nano_sec gmtmns = epicsTime (*pSrc);
969 *pDest = gmtmns.ansi_tm;970 *pDest = gmtmns.ansi_tm;
970 *pNSecDest = gmtmns.nSec;971 if (pNSecDest)
972 *pNSecDest = gmtmns.nSec;
971 }973 }
972 catch (...) {974 catch (...) {
973 return epicsTimeERROR;975 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 @@
2424
25#define NTP_REQUEST_TIMEOUT 4 /* seconds */25#define NTP_REQUEST_TIMEOUT 4 /* seconds */
2626
27extern "C" {
28 int tz2timezone(void);
29}
30
27static char sntp_sync_task[] = "ipsntps";31static char sntp_sync_task[] = "ipsntps";
28static char ntp_daemon[] = "ipntpd";32static char ntp_daemon[] = "ipntpd";
2933
30static const char *pserverAddr = NULL;34static const char *pserverAddr = NULL;
35static CLOCKTIME_SYNCHOOK prevHook;
36
31extern char* sysBootLine;37extern char* sysBootLine;
3238
39static void timeSync(int synchronized) {
40 if (!tz2timezone())
41 ClockTime_syncHook = prevHook; /* Don't call me again */
42}
43
33static int timeRegister(void)44static int timeRegister(void)
34{45{
35 /* If TIMEZONE not defined, set it from EPICS_TIMEZONE */46 /* If TZ not defined, set it from EPICS_TZ */
36 if (getenv("TIMEZONE") == NULL) {47 if (getenv("TZ") == NULL) {
37 const char *timezone = envGetConfigParamPtr(&EPICS_TIMEZONE);48 const char *tz = envGetConfigParamPtr(&EPICS_TZ);
38 if (timezone == NULL) {49
39 printf("timeRegister: No Time Zone Information\n");50 if (tz && *tz) {
40 } else {51 epicsEnvSet("TZ", tz);
41 epicsEnvSet("TIMEZONE", timezone);52
53 /* Call tz2timezone() once we know what year it is */
54 prevHook = ClockTime_syncHook;
55 ClockTime_syncHook = timeSync;
42 }56 }
57 else if (getenv("TIMEZONE") == NULL)
58 printf("timeRegister: No Time Zone Information available\n");
43 }59 }
4460
45 // Define EPICS_TS_FORCE_NTPTIME to force use of NTPTime provider61 // Define EPICS_TS_FORCE_NTPTIME to force use of NTPTime provider
@@ -57,7 +73,7 @@ static int timeRegister(void)
57 }73 }
5874
59 if (useNTP) {75 if (useNTP) {
60 // Start NTP first so it can be used to sync SysTime76 // Start NTP first so it can be used to sync ClockTime
61 NTPTime_Init(100);77 NTPTime_Init(100);
62 ClockTime_Init(CLOCKTIME_SYNC);78 ClockTime_Init(CLOCKTIME_SYNC);
63 } else {79 } else {
diff --git a/src/libCom/osi/os/vxWorks/tz2timezone.c b/src/libCom/osi/os/vxWorks/tz2timezone.c
64new file mode 10064480new file mode 100644
index 0000000..df8db85
--- /dev/null
+++ b/src/libCom/osi/os/vxWorks/tz2timezone.c
@@ -0,0 +1,278 @@
1/*************************************************************************\
2* Copyright (c) 2009 Brookhaven Science Associates, as Operator of
3* Brookhaven National Laboratory.
4* Copyright (c) 2019 UChicago Argonne LLC, as Operator of Argonne
5* National Laboratory.
6* EPICS BASE is distributed subject to a Software License Agreement found
7* in file LICENSE that is included with this distribution.
8\*************************************************************************/
9/*
10 * Authors: Larry Hoff, Andrew Johnson <anj@anl.gov>
11 */
12
13/*
14 * This file exports a single function "int tz2timezone(void)" which reads
15 * the TZ environment variable (defined by POSIX) and converts it to the
16 * TIMEZONE environment variable defined by ANSI. The latter is used by
17 * VxWorks "time" functions, is largely deprecated in other computing
18 * environments, has limitations, and is difficult to maintain. This holds
19 * out the possibility of "pretending" that VxWorks supports "TZ" - until
20 * such time as it actually does.
21 *
22 * For simplicity, only the "POSIX standard form" of TZ will be supported.
23 * Even that is complicated enough (see following spec). Furthermore,
24 * only the "M" form of DST start and stop dates are supported.
25 *
26 * TZ = zone[-]offset[dst[offset],start[/time],end[/time]]
27 *
28 * zone
29 * A three or more letter name for the timezone in normal (winter) time.
30 *
31 * [-]offset
32 * A signed time giving the offset of the time zone westwards from
33 * Greenwich. The time has the form hh[:mm[:ss]] with a one of two
34 * digit hour, and optional two digit minutes and seconds.
35 *
36 * dst
37 * The name of the time zone when daylight saving is in effect. It may
38 * be followed by an offset giving how big the adjustment is, required
39 * if different than the default of 1 hour.
40 *
41 * start/time,end/time
42 * Specify the start and end of the daylight saving period. The start
43 * and end fields indicate on what day the changeover occurs, and must
44 * be in this format:
45 *
46 * Mm.n.d
47 * This indicates month m, the n-th occurrence of day d, where
48 * 1 <= m <= 12, 1 <= n <= 5, 0 <= d <= 6, 0=Sunday
49 * The 5th occurrence means the last occurrence of that day in a
50 * month. So M4.1.0 is the first Sunday in April, M9.5.0 is the
51 * last Sunday in September.
52 *
53 * The time field indicates what hour the changeover occurs on the given
54 * day (TIMEZONE only supports switching on the hour).
55 *
56 */
57
58#include <vxWorks.h>
59#include <envLib.h> /* getenv() */
60#include <stdio.h> /* printf() */
61#include <string.h> /* strchr() */
62#include <ctype.h> /* isalpha() */
63
64#include <epicsTime.h>
65
66/* for reference: TZ syntax, example, and TIMEZONE example
67 * std offset dst [offset],start[/time],end[/time]
68 * CST6CDT5,M3.2.0,M11.1.0
69 * EST+5EDT,M4.1.0/2,M10.5.0/2
70 *
71 * std <unused> offset start stop
72 * TIMEZONE=EST::300:030802:110102
73 */
74
75static int extractDate(const char *tz, struct tm *current, char *s)
76{
77 static const int startdays[] = {
78 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
79 };
80 static const int molengths[] = {
81 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
82 };
83
84 int month, week, weekday, hour=2; /* default=2AM */
85 int jan1wday, wday, mday;
86
87 /* Require 'M' format */
88 if (*++tz != 'M') {
89 printf("tz2timezone: Unsupported date type, need 'M' format\n");
90 return ERROR;
91 }
92 tz++;
93
94 if (sscanf(tz, "%d.%d.%d/%d", &month, &week, &weekday, &hour) < 3)
95 return ERROR; /* something important missing */
96
97 if (month == 0 || month>12 ||
98 week < 1 || week > 5 ||
99 weekday < 0 || weekday > 6 ||
100 hour < 0 || hour > 23)
101 return ERROR;
102
103 /* Now for some brute-force calendar calculations... */
104 /* start month is in "month", and the day is "weekday", but
105 we need to know when that weekday first occurs in that month */
106 /* Let's start with weekday on Jan. 1 */
107 jan1wday = (7 + current->tm_wday - (current->tm_yday % 7)) % 7;
108
109 /* We need to know if it is a leap year (and if it matters) */
110 /* Let's assume that we're working with a date between 1901 and 2099,
111 that way we don't have to think about the "century exception".
112 If this code is still running (unchanged) in 2100, I'll be stunned
113 (and 139 years old) */
114 wday = (jan1wday + startdays[month-1] +
115 ((month > 2 && (current->tm_year % 4 == 0)) ? 1 : 0)) % 7;
116
117 /* Let's see on what day-of-the-month the first target weekday occurs
118 (counting from 1). The result is a number between 1 and 7, inclusive. */
119 mday = 1 + ((7 + weekday - wday) % 7);
120
121 /* Next, we add the week offset. If we overflow the month, we subtract
122 one week */
123 mday += 7 * (week - 1);
124 if (mday > molengths[month-1])
125 mday -= 7;
126
127 /* Should I handle Feb 29? I'm willing to gamble that no one in their right
128 mind would schedule a time change to occur on Feb. 29. If so, we'll be a
129 week early */
130 sprintf(s, "%02d%02d%02d", month, mday, hour);
131
132 return OK;
133}
134
135
136static const char *getTime(const char *s, int *time)
137{
138 /* Time format is [+/-]hh[:mm][:ss] followed by the next zone name */
139
140 *time = 0;
141
142 if (!isdigit((int) s[0]))
143 return s; /* no number here... */
144
145 if (!isdigit((int) s[1])) { /* single digit form */
146 *time = s[0] - '0';
147 return s + 1;
148 }
149
150 if (isdigit((int) s[1])) { /* two digit form */
151 *time = 10 * (s[0] - '0') + (s[1] - '0');
152 return s + 2;
153 }
154
155 return s; /* does not follow supported form */
156}
157
158int tz2timezone(void)
159{
160 const char *tz = getenv("TZ");
161 /* Spec. says that zone names must be at least 3 chars.
162 * I've never seen a longer zone name, but I'll allocate
163 * 40 chars. If you live in a zone with a longer name,
164 * you may want to think about the benefits of relocation.
165 */
166 char zone[40];
167 char start[10], stop[10]; /* only really need 7 bytes now */
168 int hours = 0, minutes = 0, sign = 1;
169 /* This is more than enough, even with a 40-char zone
170 * name, and 4-char offset.
171 */
172 char timezone[100];
173 int i = 0; /* You *always need an "i" :-) */
174 epicsTimeStamp now;
175 struct tm current;
176
177 /* First let's get the current time. We need the year to
178 * compute the start/stop dates for DST.
179 */
180 if (epicsTimeGetCurrent(&now) ||
181 epicsTimeToTM(&current, NULL, &now))
182 return ERROR;
183
184 /* Make sure TZ exists.
185 * Spec. says that ZONE must be at least 3 chars.
186 */
187 if ((!tz) || (strlen(tz) < 3))
188 return ERROR;
189
190 /* OK, now a bunch of brute-force parsing. My brain hurts if
191 * I try to think of an elegant regular expression for the
192 * string.
193 */
194
195 /* Start extracting zone name, must be alpha */
196 while ((i < sizeof(zone) - 1) && isalpha((int) *tz)) {
197 zone[i++] = *tz++;
198 }
199 if (i < 3)
200 return ERROR; /* Too short, not a real zone name? */
201
202 zone[i] = 0; /* Nil-terminate (for now) */
203
204 /* Now extract offset time. The format is [+/-]hh[:mm[:ss]]
205 * Recall that TIMEZONE doesn't support seconds....
206 */
207 if (*tz == '-') {
208 sign = -1;
209 tz++;
210 }
211 else if (*tz == '+') {
212 tz++;
213 }
214
215 /* Need a digit now */
216 if (!isdigit((int) *tz))
217 return ERROR;
218
219 /* First get the hours */
220 tz = getTime(tz, &hours);
221 if (hours > 24)
222 return ERROR;
223
224 if (*tz == ':') { /* There is a minutes part */
225 /* Need another digit now */
226 if (!isdigit((int) *++tz))
227 return ERROR;
228
229 /* Extract the minutes */
230 tz = getTime(tz, &minutes);
231 if (minutes > 60)
232 return ERROR;
233
234 /* Skip any seconds part */
235 if (*tz == ':') {
236 int seconds;
237 tz = getTime(tz + 1, &seconds);
238 }
239 }
240
241 /* Extract any DST zone name, must be alpha */
242 if (isalpha((int) *tz)) {
243 zone[i++] = '/'; /* Separate the names */
244
245 while ((i < sizeof(zone) - 1) && isalpha((int) *tz)) {
246 zone[i++] = *tz++;
247 }
248 zone[i] = 0; /* Nil-terminate */
249 }
250
251 minutes += hours * 60;
252 minutes *= sign;
253
254 /* Look for start/stop dates - require neither or both */
255 tz = strchr(tz, ',');
256 if (!tz) { /* No daylight savings time here */
257 /* Format the env. variable */
258 sprintf(timezone, "TIMEZONE=%s::%d", zone, minutes);
259 }
260 else {
261 if (extractDate(tz, &current, start) != OK)
262 return ERROR;
263
264 tz = strchr(tz + 1, ',');
265 if (!tz)
266 return ERROR;
267 if (extractDate(tz, &current, stop) != OK)
268 return ERROR;
269
270 /* Format the env. variable */
271 sprintf(timezone, "TIMEZONE=%s::%d:%s:%s", zone, minutes, start, stop);
272 }
273
274 /* Make it live! */
275 putenv(timezone);
276
277 return OK;
278}
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 @@
23#include "taskwd.h"23#include "taskwd.h"
2424
25#define NSEC_PER_SEC 100000000025#define NSEC_PER_SEC 1000000000
26#define ClockTimeSyncInterval_value 60.026#define ClockTimeSyncInterval_initial 1.0
27#define ClockTimeSyncInterval_normal 60.0
2728
2829
29static struct {30static struct {
@@ -79,7 +80,7 @@ static void ClockTime_InitOnce(void *pfirst)
7980
80 ClockTimePvt.loopEvent = epicsEventMustCreate(epicsEventEmpty);81 ClockTimePvt.loopEvent = epicsEventMustCreate(epicsEventEmpty);
81 ClockTimePvt.lock = epicsMutexCreate();82 ClockTimePvt.lock = epicsMutexCreate();
82 ClockTimePvt.ClockTimeSyncInterval = 1.0; /* First sync */83 ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_initial;
8384
84 epicsAtExit(ClockTime_Shutdown, NULL);85 epicsAtExit(ClockTime_Shutdown, NULL);
8586
@@ -148,6 +149,8 @@ void ClockTime_GetProgramStart(epicsTimeStamp *pDest)
148/* Synchronization thread */149/* Synchronization thread */
149150
150#if defined(vxWorks) || defined(__rtems__)151#if defined(vxWorks) || defined(__rtems__)
152CLOCKTIME_SYNCHOOK ClockTime_syncHook = NULL;
153
151static void ClockTimeSync(void *dummy)154static void ClockTimeSync(void *dummy)
152{155{
153 taskwdInsert(0, NULL, NULL);156 taskwdInsert(0, NULL, NULL);
@@ -179,11 +182,16 @@ static void ClockTimeSync(void *dummy)
179 ClockTimePvt.syncTime = timeNow;182 ClockTimePvt.syncTime = timeNow;
180 epicsMutexUnlock(ClockTimePvt.lock);183 epicsMutexUnlock(ClockTimePvt.lock);
181184
182 ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_value;185 if (ClockTime_syncHook)
186 ClockTime_syncHook(1);
187
188 ClockTimePvt.ClockTimeSyncInterval = ClockTimeSyncInterval_normal;
183 }189 }
184 }190 }
185191
186 ClockTimePvt.synchronized = 0;192 ClockTimePvt.synchronized = 0;
193 if (ClockTime_syncHook)
194 ClockTime_syncHook(0);
187 taskwdRemove(0);195 taskwdRemove(0);
188}196}
189#endif197#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);
19void ClockTime_Shutdown(void *dummy);19void ClockTime_Shutdown(void *dummy);
20int ClockTime_Report(int level);20int ClockTime_Report(int level);
2121
22#if defined(vxWorks) || defined(__rtems__)
23typedef void (* CLOCKTIME_SYNCHOOK)(int synchronized);
24
25extern CLOCKTIME_SYNCHOOK ClockTime_syncHook;
26#endif
27
22#ifdef __cplusplus28#ifdef __cplusplus
23}29}
24#endif30#endif

Subscribers

People subscribed via source and target branches