Make the NTPTime provider optional on VxWorks

This commit is contained in:
Andrew Johnson
2015-10-05 17:44:26 -05:00
parent c74eb27474
commit d0875f4f12
4 changed files with 112 additions and 37 deletions

View File

@@ -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()

View File

@@ -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

View File

@@ -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)

View File

@@ -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);