37 #include <epicsTime.h> 38 #include <epicsVersion.h> 39 #include <epicsMutex.h> 40 #include <epicsThread.h> 41 #include <epicsStdio.h> 45 #include <longinRecord.h> 47 #include <menuConvert.h> 50 #include <initHooks.h> 57 # if ( ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 401 ) 58 # define SYNC() __sync_synchronize() 60 # define SYNC() __asm__ __volatile__ ("":::"memory") 64 # define SYNC() do{}while(0) 68 #define NTPD_SEG0 0x4E545030 70 #define RETRY_TIME 30.0 94 static epicsThreadOnceId ntponce = EPICS_THREAD_ONCE_INIT;
124 static void incFail()
126 epicsMutexMustLock(ntpShm.
ntplock);
129 epicsMutexUnlock(ntpShm.
ntplock);
132 static void ntpshmupdate(
void*, epicsUInt32 event)
134 if(event!=ntpShm.
event) {
138 epicsTimeStamp evrts;
145 struct timeval cputs;
146 if(gettimeofday(&cputs, 0))
152 struct timeval evrts_posix;
153 evrts_posix.tv_sec = evrts.secPastEpoch + POSIX_TIME_AT_EPICS_EPOCH;
154 evrts_posix.tv_usec = evrts.nsec / 1000;
156 if(evrts.nsec % 1000 >= 500) {
157 evrts_posix.tv_usec += 1;
158 if(evrts_posix.tv_usec>=1000000) {
159 evrts_posix.tv_sec += 1;
160 evrts_posix.tv_usec = 0;
169 int c1 = seg->
count++;
172 seg->
rxSec = cputs.tv_sec;
173 seg->
rxUsec = cputs.tv_usec;
174 int c2 = seg->
count++;
176 fprintf(stderr,
"ntpshmupdate: possible collision with another writer!\n");
182 epicsMutexMustLock(ntpShm.
ntplock);
186 ntpShm.
lastRx = epicsTime(cputs);
187 epicsMutexUnlock(ntpShm.
ntplock);
192 fprintf(stderr,
"First update ready for NTPD\n");
199 static void ntpsetup(CALLBACK *)
203 int mode = ntpShm.
segid <=1 ? 0600 : 0666;
210 fprintf(stderr,
"Can't find shared memory segment. Either NTPD hasn't started," 211 " or is not configured correctly. Will retry later.");
216 perror(
"ntpshmsetup: shmget");
223 perror(
"ntpshmsetup: shmat");
237 }
catch(std::exception& e) {
238 fprintf(stderr,
"Error registering for 1Hz event: %s\n", e.what());
242 static void ntpshminit(
void*)
244 ntpShm.
ntplock = epicsMutexMustCreate();
246 callbackSetPriority(priorityLow, &ntpShm.
ntp_cb);
247 callbackSetCallback(&ntpsetup, &ntpShm.
ntp_cb);
248 callbackSetUser(0, &ntpShm.
ntp_cb);
251 static void ntpshmhooks(initHookState state)
253 if(state!=initHookAfterIocRunning)
256 epicsThreadOnce(&ntponce, &ntpshminit, 0);
258 epicsMutexMustLock(ntpShm.
ntplock);
260 callbackRequest(&ntpShm.
ntp_cb);
261 fprintf(stderr,
"Starting NTP SHM writer for segment %d\n", ntpShm.
segid);
263 epicsMutexUnlock(ntpShm.
ntplock);
266 void time2ntp(
const char* evrname,
int segid,
int event)
271 else if(event<=0 || event >255) {
272 fprintf(stderr,
"Invalid 1Hz event # %d\n", event);
275 if(segid<0 || segid>4) {
276 fprintf(stderr,
"Invalid segment ID %d\n", segid);
281 fprintf(stderr,
"Unknown EVR: %s\n", evrname);
285 EVR *evr =
dynamic_cast<EVR*
>(obj);
287 fprintf(stderr,
"\"%s\" is not an EVR\n", evrname);
291 epicsThreadOnce(&ntponce, &ntpshminit, 0);
293 epicsMutexMustLock(ntpShm.
ntplock);
296 epicsMutexUnlock(ntpShm.
ntplock);
297 fprintf(stderr,
"ntpShm already initialized.\n");
301 ntpShm.
event = event;
303 ntpShm.
segid = segid;
305 epicsMutexUnlock(ntpShm.
ntplock);
306 }
catch(std::exception& e) {
307 fprintf(stderr,
"Error: %s\n", e.what());
311 static const iocshArg time2ntpArg0 = {
"evr name",iocshArgString};
312 static const iocshArg time2ntpArg1 = {
"NTP segment id",iocshArgInt};
313 static const iocshArg time2ntpArg2 = {
"1Hz Event code",iocshArgInt};
314 static const iocshArg *
const time2ntpArgs[3] =
315 {&time2ntpArg0,&time2ntpArg1,&time2ntpArg2};
316 static const iocshFuncDef time2ntpFuncDef =
317 {
"time2ntp",3,time2ntpArgs};
318 static void time2ntpCallFunc(
const iocshArgBuf *
args)
320 time2ntp(args[0].sval,args[1].ival,args[2].ival);
331 static long read_ok(longinRecord* prec)
333 epicsMutexMustLock(ntpShm.
ntplock);
334 prec->val = ntpShm.
numOk;
335 epicsMutexUnlock(ntpShm.
ntplock);
339 static long read_fail(longinRecord* prec)
341 epicsMutexMustLock(ntpShm.
ntplock);
343 epicsMutexUnlock(ntpShm.
ntplock);
347 static long read_delta(aiRecord* prec)
349 epicsMutexMustLock(ntpShm.
ntplock);
354 recGblSetSevr(prec, READ_ALARM, INVALID_ALARM);
355 if(prec->tse==epicsTimeEventDeviceTime) {
358 epicsMutexUnlock(ntpShm.
ntplock);
360 if(prec->linr==menuConvertLINEAR){
374 static void ntpShmReport(
int)
376 epicsMutexMustLock(ntpShm.
ntplock);
378 unsigned int ok=ntpShm.
numOk,
380 epicsMutexUnlock(ntpShm.
ntplock);
383 printf(
"Driver is active\n ok#: %u\n fail#: %u\n", ok, fail);
385 printf(
"Driver is not active\n");
389 static void ntpShmInit()
394 static void ntpShmRegister()
396 initHookRegister(&ntpshmhooks);
397 iocshRegister(&time2ntpFuncDef,&time2ntpCallFunc);
414 (DEVSUPFUN)&read_fail,
420 (DEVSUPFUN)&read_delta,
424 static drvet ntpShared = {
426 (DRVSUPFUN)&ntpShmReport,
427 (DRVSUPFUN)&ntpShmInit,
430 #include <epicsExport.h>
epicsExportAddress(drvet, ntpShared)
epicsExportRegistrar(ntpShmRegister)
void time2ntp(const char *evrname, int segid, int event)
static Object * getObject(const std::string &name)
#define MRF_EVENT_TS_COUNTER_RST
virtual void eventNotifyAdd(epicsUInt32 event, eventCallback, void *)=0
virtual bool getTimeStamp(epicsTimeStamp *ts, epicsUInt32 event)=0