diff --git a/src/libCom/osi/os/vxWorks/iocClock.c b/src/libCom/osi/os/vxWorks/iocClock.c new file mode 100644 index 000000000..e8a34e2dc --- /dev/null +++ b/src/libCom/osi/os/vxWorks/iocClock.c @@ -0,0 +1,211 @@ +/* iocClock.c */ + +/* Author: Marty Kraimer Date: 16JUN2000 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "epicsTypes.h" +#include "cantProceed.h" +#include "errlog.h" +#include "osiThread.h" +#include "osiSem.h" +#include "tsStamp.h" +#include "iocClock.h" + +#define BILLION 1000000000 +#define iocClockSyncRate 10.0 + +static int iocClockGetCurrent(TS_STAMP *pDest); +static int iocClockGetEvent(TS_STAMP *pDest, unsigned eventNumber); + +typedef struct iocClockPvt { + semMutexId lock; + TS_STAMP clock; + unsigned long lastTick; + epicsUInt32 nanosecondsPerTick; + int tickRate; + int ticksToSkip; + ptsStampGetCurrent getCurrent; + ptsStampGetEvent getEvent; + char *pserverAddr; +}iocClockPvt; +static iocClockPvt *piocClockPvt = 0; + +extern char* sysBootLine; + +static void syncNTP(void) +{ + struct timespec Currtime; + TS_STAMP epicsTime; + STATUS status; + int nConsecutiveBad = 0; + + while(1) { + status = sntpcTimeGet(piocClockPvt->pserverAddr, + piocClockPvt->tickRate,&Currtime); + if(status) { + if(++nConsecutiveBad>6) { + errlogPrintf("iocClockSyncWithNTPserver: sntpcTimeGet %s\n", + strerror(status)); + nConsecutiveBad = 0; + } + threadSleep(iocClockSyncRate); + continue; + } + nConsecutiveBad = 0; + semMutexMustTake(piocClockPvt->lock); + clock_settime(CLOCK_REALTIME,&Currtime); + tsStampFromTimespec(&piocClockPvt->clock,&Currtime); + piocClockPvt->lastTick = tickGet(); + semMutexGive(piocClockPvt->lock); + } + while(1) { + double diffTime; + threadSleep(iocClockSyncRate); + status = sntpcTimeGet(piocClockPvt->pserverAddr, + piocClockPvt->tickRate,&Currtime); + if(status) { + errlogPrintf("iocClockSyncWithNTPserver: sntpcTimeGet %s\n", + strerror(status)); + continue; + } + tsStampFromTimespec(&epicsTime,&Currtime); + semMutexMustTake(piocClockPvt->lock); + diffTime = tsStampDiffInSeconds(&epicsTime,&piocClockPvt->clock); + if(diffTime>=0.0) { + piocClockPvt->clock = epicsTime; + } else {/*dont go back in time*/ + piocClockPvt->ticksToSkip = (int) (diffTime*piocClockPvt->tickRate); + } + piocClockPvt->lastTick = tickGet(); + semMutexGive(piocClockPvt->lock); + } +} + +void iocClockInit() +{ + if(piocClockPvt) return; + piocClockPvt = callocMustSucceed(1,sizeof(iocClockPvt),"iocClockInit"); + piocClockPvt->lock = semMutexMustCreate(); + piocClockPvt->nanosecondsPerTick = BILLION/sysClkRateGet(); + piocClockPvt->tickRate = sysClkRateGet(); + piocClockPvt->getCurrent = iocClockGetCurrent; + piocClockPvt->getEvent = iocClockGetEvent; + /* look first for environment variable */ + piocClockPvt->pserverAddr = getenv("EPICS_TS_NTP_INET"); + if(!piocClockPvt->pserverAddr) { /* next look for boot server*/ + 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); + piocClockPvt->pserverAddr = host_addr; + } + if(!piocClockPvt->pserverAddr) { + errlogPrintf("No NTP server is defined. Clock does not work\n"); + return; + } + threadCreate("syncNTP", + threadPriorityHigh,threadGetStackSize(threadStackSmall), + (THREADFUNC)syncNTP,0); + return; +} + +void iocClockRegister(ptsStampGetCurrent getCurrent, + ptsStampGetEvent getEvent) +{ + if(piocClockPvt) { + printf("iocClockRegister: iocClock already initialized\n"); + return; + } + piocClockPvt = callocMustSucceed(1,sizeof(iocClockPvt),"iocClockRegister"); + piocClockPvt->getCurrent = getCurrent; + piocClockPvt->getEvent = getEvent; +} + +int iocClockGetCurrent(TS_STAMP *pDest) +{ + unsigned long currentTick,nticks,nsecs; + + semMutexMustTake(piocClockPvt->lock); + currentTick = tickGet(); + while(currentTick!=piocClockPvt->lastTick) { + nticks = (currentTick>piocClockPvt->lastTick) + ? (currentTick - piocClockPvt->lastTick) + : (currentTick + (ULONG_MAX - piocClockPvt->lastTick)); + if(piocClockPvt->ticksToSkip>0) {/*dont go back in time*/ + if(nticksticksToSkip) { + piocClockPvt->ticksToSkip -= nticks; + break; + } + nticks -= piocClockPvt->ticksToSkip; + } + piocClockPvt->lastTick = currentTick; + nsecs = nticks/piocClockPvt->tickRate; + nticks = nticks - nsecs*piocClockPvt->tickRate; + piocClockPvt->clock.nsec += nticks * piocClockPvt->nanosecondsPerTick; + if(piocClockPvt->clock.nsec>=BILLION) { + ++nsecs; + piocClockPvt->clock.nsec -= BILLION; + } + piocClockPvt->clock.secPastEpoch += nsecs; + } + *pDest = piocClockPvt->clock; + semMutexGive(piocClockPvt->lock); + return(0); +} + +int iocClockGetEvent(TS_STAMP *pDest, unsigned eventNumber) +{ + if (eventNumber==tsStampEventCurrentTime) { + *pDest = piocClockPvt->clock; + return(0); + } + return(tsStampERROR); +} + +int tsStampGetCurrent (TS_STAMP *pDest) +{ + if(piocClockPvt->getCurrent) return((*piocClockPvt->getCurrent)(pDest)); + return(tsStampERROR); +} + +int tsStampGetEvent (TS_STAMP *pDest, unsigned eventNumber) +{ + if(piocClockPvt->getEvent) + return((*piocClockPvt->getEvent)(pDest,eventNumber)); + return(tsStampERROR); +} + +void date() +{ + TS_STAMP now; + char nowText[40]; + size_t rtn; + + rtn = tsStampGetCurrent(&now); + if(rtn) { + printf("tsStampGetCurrent failed\n"); + return; + } + nowText[0] = 0; + rtn = tsStampToStrftime(nowText,sizeof(nowText), + "%Y/%m/%d %H:%M:%S.%06f",&now); + printf("%s\n",nowText); +} diff --git a/src/libCom/osi/os/vxWorks/iocClock.h b/src/libCom/osi/os/vxWorks/iocClock.h new file mode 100644 index 000000000..a470c8481 --- /dev/null +++ b/src/libCom/osi/os/vxWorks/iocClock.h @@ -0,0 +1,17 @@ +/* iocClock.h */ + +/* Author: Marty Kraimer Date: 16JUN2000 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +#include "tsStamp.h" + +typedef int (*ptsStampGetCurrent)(TS_STAMP *pDest); +typedef int (*ptsStampGetEvent)(TS_STAMP *pDest,unsigned eventNumber); + +void iocClockInit(void); +void iocClockRegister(ptsStampGetCurrent getCurrent,ptsStampGetEvent getEvent); diff --git a/src/libCom/osi/os/vxWorks/osdThread.c b/src/libCom/osi/os/vxWorks/osdThread.c index 36eeaf381..6817f3e95 100644 --- a/src/libCom/osi/os/vxWorks/osdThread.c +++ b/src/libCom/osi/os/vxWorks/osdThread.c @@ -98,9 +98,9 @@ void threadInit(void) threadOnceMutex = semMCreate( SEM_DELETE_SAFE|SEM_INVERSION_SAFE|SEM_Q_PRIORITY); assert(threadOnceMutex); - TSinit(); } lock = 0; + iocClockInit(); } void threadOnceOsd(threadOnceId *id, void (*func)(void *), void *arg) diff --git a/src/libCom/osi/os/vxWorks/osdTime.cpp b/src/libCom/osi/os/vxWorks/osdTime.cpp index b29dc33f2..636d33b1a 100644 --- a/src/libCom/osi/os/vxWorks/osdTime.cpp +++ b/src/libCom/osi/os/vxWorks/osdTime.cpp @@ -1,26 +1,2 @@ -#define epicsExportSharedSymbols -#include "osiTime.h" - -#ifdef __cplusplus -extern "C" { -#endif -extern long TSgetTimeStamp(int event_number,TS_STAMP* ts); -#ifdef __cplusplus -} -#endif - -// -// osiTime::osdGetCurrent () -// -extern "C" epicsShareFunc int tsStampGetCurrent (TS_STAMP *pDest) -{ - return(TSgetTimeStamp(0,pDest)); -} - -// -// tsStampGetEvent () -// -extern "C" epicsShareFunc int epicsShareAPI tsStampGetEvent (TS_STAMP *pDest, unsigned eventNumber) -{ - return(TSgetTimeStamp((int)eventNumber,pDest)); -} +// this is not needed +// tsStampGetCurrent and tsStampGetEvent are implemented in iocClock.c