Make the NTPTime provider optional on VxWorks
This commit is contained in:
@@ -14,6 +14,18 @@
|
||||
<h2 align="center">Changes between 3.15.2 and 3.15.3</h2>
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>Make the NTP Time provider optional on VxWorks</h3>
|
||||
|
||||
<p>Recent versions of VxWorks (sometime after VxWorks 6) provide facilities for
|
||||
automatically synchronizing the OS clock time with an NTP server. The EPICS time
|
||||
system used to assume that it had to provide time synchronization on VxWorks,
|
||||
but now it tests for the existance of either of the two OS synchronization
|
||||
threads before starting the NTP time provider. It is still possible to force the
|
||||
NTP provider to be started even if the OS synchronization is running by defining
|
||||
the environment variable <tt>EPICS_TS_FORCE_NTPTIME</tt> in the startup script
|
||||
before loading the IOC's .munch file. Forcing may be necessary if the VxWorks
|
||||
image is not correctly configured with the IP address of a local NTP server.</p>
|
||||
|
||||
<h3>Clean up after GNU readline()</h3>
|
||||
|
||||
<p>If EPICS Base is built with readline support, any IOC that calls epicsExit()
|
||||
|
||||
@@ -80,6 +80,10 @@ Com_SRCS += osiClockTime.c
|
||||
Com_SRCS_vxWorks += osiNTPTime.c
|
||||
Com_SRCS_RTEMS += osiNTPTime.c
|
||||
|
||||
ifeq ($(OS_CLASS),vxWorks)
|
||||
osdTime.o: USR_CXXFLAGS += -DBUILD_TIME=$(shell perl -e 'print time')
|
||||
endif
|
||||
|
||||
Com_SRCS += osdSock.c
|
||||
Com_SRCS += osdSockAddrReuse.cpp
|
||||
Com_SRCS += osiSock.c
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* Copyright (c) 2015 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
@@ -7,11 +7,14 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h>
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <sntpcLib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <taskLib.h>
|
||||
|
||||
#include "epicsTime.h"
|
||||
#include "osiNTPTime.h"
|
||||
@@ -21,6 +24,9 @@
|
||||
|
||||
#define NTP_REQUEST_TIMEOUT 4 /* seconds */
|
||||
|
||||
static char sntp_sync_task[] = "ipsntps";
|
||||
static char ntp_daemon[] = "ipntpd";
|
||||
|
||||
static const char *pserverAddr = NULL;
|
||||
extern char* sysBootLine;
|
||||
|
||||
@@ -30,18 +36,40 @@ static int timeRegister(void)
|
||||
if (getenv("TIMEZONE") == NULL) {
|
||||
const char *timezone = envGetConfigParamPtr(&EPICS_TIMEZONE);
|
||||
if (timezone == NULL) {
|
||||
printf("NTPTime_Init: No Time Zone Information\n");
|
||||
printf("timeRegister: No Time Zone Information\n");
|
||||
} else {
|
||||
epicsEnvSet("TIMEZONE", timezone);
|
||||
}
|
||||
}
|
||||
|
||||
NTPTime_Init(100); /* init NTP first so it can be used to sync SysTime */
|
||||
ClockTime_Init(CLOCKTIME_SYNC);
|
||||
// Define EPICS_TS_FORCE_NTPTIME to force use of NTPTime provider
|
||||
bool useNTP = getenv("EPICS_TS_FORCE_NTPTIME") != NULL;
|
||||
|
||||
if (!useNTP &&
|
||||
(taskNameToId(sntp_sync_task) != ERROR ||
|
||||
taskNameToId(ntp_daemon) != ERROR)) {
|
||||
// A VxWorks 6 SNTP/NTP sync task is running
|
||||
struct timespec clockNow;
|
||||
|
||||
useNTP = clock_gettime(CLOCK_REALTIME, &clockNow) != OK ||
|
||||
clockNow.tv_sec < BUILD_TIME;
|
||||
// Assumes VxWorks and the host OS have the same epoch
|
||||
}
|
||||
|
||||
if (useNTP) {
|
||||
// Start NTP first so it can be used to sync SysTime
|
||||
NTPTime_Init(100);
|
||||
ClockTime_Init(CLOCKTIME_SYNC);
|
||||
} else {
|
||||
ClockTime_Init(CLOCKTIME_NOSYNC);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static int done = timeRegister();
|
||||
|
||||
|
||||
// Routines for NTPTime provider
|
||||
|
||||
int osdNTPGet(struct timespec *ts)
|
||||
{
|
||||
return sntpcTimeGet(const_cast<char *>(pserverAddr),
|
||||
@@ -54,6 +82,7 @@ void osdNTPInit(void)
|
||||
if (!pserverAddr) { /* use the boot host */
|
||||
BOOT_PARAMS bootParms;
|
||||
static char host_addr[BOOT_ADDR_LEN];
|
||||
|
||||
bootStringToStruct(sysBootLine, &bootParms);
|
||||
/* bootParms.had = host IP address */
|
||||
strncpy(host_addr, bootParms.had, BOOT_ADDR_LEN);
|
||||
@@ -63,10 +92,13 @@ void osdNTPInit(void)
|
||||
|
||||
void osdNTPReport(void)
|
||||
{
|
||||
printf("NTP Server = %s\n", pserverAddr);
|
||||
if (pserverAddr)
|
||||
printf("NTP Server = %s\n", pserverAddr);
|
||||
}
|
||||
|
||||
|
||||
// Other Time Routines
|
||||
|
||||
// vxWorks localtime_r returns different things in different versions.
|
||||
// It can't fail though, so we just ignore the return value.
|
||||
int epicsTime_localtime(const time_t *clock, struct tm *result)
|
||||
|
||||
@@ -70,37 +70,54 @@ static void ShutdownCallFunc(const iocshArgBuf *args)
|
||||
|
||||
/* Initialization */
|
||||
|
||||
static void ClockTime_InitOnce(void *psync)
|
||||
static void ClockTime_InitOnce(void *pfirst)
|
||||
{
|
||||
ClockTimePvt.synchronize = *(int *)psync;
|
||||
*(int *) pfirst = 1;
|
||||
|
||||
ClockTimePvt.loopEvent = epicsEventMustCreate(epicsEventEmpty);
|
||||
ClockTimePvt.lock = epicsMutexCreate();
|
||||
|
||||
if (ClockTimePvt.synchronize) {
|
||||
/* Start the sync thread */
|
||||
epicsThreadCreate("ClockTimeSync", epicsThreadPriorityHigh,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
ClockTimeSync, NULL);
|
||||
}
|
||||
else {
|
||||
ClockTimeGetCurrent(&ClockTimePvt.startTime);
|
||||
}
|
||||
|
||||
epicsAtExit(ClockTime_Shutdown, NULL);
|
||||
|
||||
/* Register the iocsh commands */
|
||||
iocshRegister(&ReportFuncDef, ReportCallFunc);
|
||||
if (ClockTimePvt.synchronize)
|
||||
iocshRegister(&ShutdownFuncDef, ShutdownCallFunc);
|
||||
iocshRegister(&ShutdownFuncDef, ShutdownCallFunc);
|
||||
|
||||
/* Finally register as a time provider */
|
||||
/* Register as a time provider */
|
||||
generalTimeRegisterCurrentProvider("OS Clock", LAST_RESORT_PRIORITY,
|
||||
ClockTimeGetCurrent);
|
||||
}
|
||||
|
||||
void ClockTime_Init(int synchronize)
|
||||
{
|
||||
epicsThreadOnce(&onceId, ClockTime_InitOnce, &synchronize);
|
||||
int firstTime = 0;
|
||||
|
||||
epicsThreadOnce(&onceId, ClockTime_InitOnce, &firstTime);
|
||||
|
||||
if (synchronize == CLOCKTIME_SYNC) {
|
||||
if (ClockTimePvt.synchronize == CLOCKTIME_NOSYNC) {
|
||||
/* Start synchronizing */
|
||||
ClockTimePvt.synchronize = synchronize;
|
||||
|
||||
epicsThreadCreate("ClockTimeSync", epicsThreadPriorityHigh,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
ClockTimeSync, NULL);
|
||||
}
|
||||
else {
|
||||
/* No change, sync thread should already be running */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ClockTimePvt.synchronize == CLOCKTIME_SYNC) {
|
||||
/* Turn off synchronization thread */
|
||||
ClockTime_Shutdown(NULL);
|
||||
}
|
||||
else {
|
||||
/* No synchronization thread */
|
||||
if (firstTime)
|
||||
ClockTimeGetCurrent(&ClockTimePvt.startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +125,7 @@ void ClockTime_Init(int synchronize)
|
||||
|
||||
void ClockTime_Shutdown(void *dummy)
|
||||
{
|
||||
ClockTimePvt.synchronize = 0;
|
||||
ClockTimePvt.synchronize = CLOCKTIME_NOSYNC;
|
||||
epicsEventSignal(ClockTimePvt.loopEvent);
|
||||
}
|
||||
|
||||
@@ -126,7 +143,7 @@ static void ClockTimeSync(void *dummy)
|
||||
|
||||
for (epicsEventWaitWithTimeout(ClockTimePvt.loopEvent,
|
||||
ClockTimeSyncInterval);
|
||||
ClockTimePvt.synchronize;
|
||||
ClockTimePvt.synchronize == CLOCKTIME_SYNC;
|
||||
epicsEventWaitWithTimeout(ClockTimePvt.loopEvent,
|
||||
ClockTimeSyncInterval)) {
|
||||
epicsTimeStamp timeNow;
|
||||
@@ -144,8 +161,8 @@ static void ClockTimeSync(void *dummy)
|
||||
|
||||
epicsMutexMustLock(ClockTimePvt.lock);
|
||||
if (!ClockTimePvt.synchronized) {
|
||||
ClockTimePvt.startTime = timeNow;
|
||||
ClockTimePvt.synchronized = 1;
|
||||
ClockTimePvt.startTime = timeNow;
|
||||
ClockTimePvt.synchronized = 1;
|
||||
}
|
||||
ClockTimePvt.syncFromPriority = priority;
|
||||
ClockTimePvt.syncTime = timeNow;
|
||||
@@ -200,29 +217,39 @@ int ClockTime_Report(int level)
|
||||
#ifdef CLOCK_REALTIME
|
||||
"initialized"
|
||||
#else
|
||||
"included"
|
||||
"available"
|
||||
#endif /* CLOCK_REALTIME */
|
||||
);
|
||||
} else if (ClockTimePvt.synchronize) {
|
||||
}
|
||||
else if (ClockTimePvt.synchronize == CLOCKTIME_SYNC) {
|
||||
int synchronized, syncFromPriority;
|
||||
epicsTimeStamp startTime, syncTime;
|
||||
|
||||
epicsMutexMustLock(ClockTimePvt.lock);
|
||||
if (ClockTimePvt.synchronized) {
|
||||
printf("OS Clock driver has synchronized to a priority=%d provider\n",
|
||||
ClockTimePvt.syncFromPriority);
|
||||
synchronized = ClockTimePvt.synchronized;
|
||||
syncFromPriority = ClockTimePvt.syncFromPriority;
|
||||
startTime = ClockTimePvt.startTime;
|
||||
syncTime = ClockTimePvt.syncTime;
|
||||
epicsMutexUnlock(ClockTimePvt.lock);
|
||||
|
||||
if (synchronized) {
|
||||
printf("OS Clock driver is synchronized to a priority=%d provider\n",
|
||||
syncFromPriority);
|
||||
if (level) {
|
||||
epicsTimeToStrftime(timebuf, sizeof(timebuf),
|
||||
"%Y-%m-%d %H:%M:%S.%06f", &ClockTimePvt.startTime);
|
||||
"%Y-%m-%d %H:%M:%S.%06f", &startTime);
|
||||
printf("Initial sync was at %s\n", timebuf);
|
||||
epicsTimeToStrftime(timebuf, sizeof(timebuf),
|
||||
"%Y-%m-%d %H:%M:%S.%06f", &ClockTimePvt.syncTime);
|
||||
"%Y-%m-%d %H:%M:%S.%06f", &syncTime);
|
||||
printf("Last successful sync was at %s\n", timebuf);
|
||||
}
|
||||
printf("Syncronization interval = %.0f seconds\n",
|
||||
ClockTimeSyncInterval);
|
||||
} else
|
||||
printf("OS Clock driver has *not* yet synchronized\n");
|
||||
|
||||
epicsMutexUnlock(ClockTimePvt.lock);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
printf("OS Clock driver is *not* synchronized\n");
|
||||
}
|
||||
else {
|
||||
epicsTimeToStrftime(timebuf, sizeof(timebuf),
|
||||
"%Y-%m-%d %H:%M:%S.%06f", &ClockTimePvt.startTime);
|
||||
printf("Program started at %s\n", timebuf);
|
||||
|
||||
Reference in New Issue
Block a user