OSI monotonic time source

Bug #1392516 reported by mdavidsaver
This bug affects 2 people
Affects Status Importance Assigned to Milestone
In Progress

Bug Description

There is a need for seperate real (wall clock) and monotonic time sources.

On 11/13/2014 04:18 PM, J. Lewis Muir wrote:> Hello, Tech-Talkers.
> Is there a way to get monotonic time from EPICS Base libCom?
> By "monotonic time," I mean a system time that increases at a steady
> rate and is not affected by a change to the system's RTC. The origin of
> the time is unspecified, but the difference between two monotonic times
> can be used to compute elapsed time. [1]
> I think the answer is no, but I thought I'd ask. I'd like a simple way
> to implement a timeout in a C function like this:
> start_time = epicsTimeGetMonotonic();
> for (;;) {
> if (is_data_ready()) goto out;
> elapsed_time = epicsTimeGetMonotonic() - start_time;
> if (elapsed_time > timeout) goto timeout;
> epicsThreadSleep(0.1);
> }
> Without monotonic time, the closest I can get to this in a simple way
> is to use epicsTimeGetCurrent and epicsTimeDiffInSeconds. This is
> suboptimal because I have to deal with time that can advance backward
> or forward in an unpredictable way, and it's not possible to correctly
> compensate for that. For example, if the elapsed time is negative, time
> has advanced backward, and I need to set the start time to the new time.
> This has the undesirable effect of extending the timeout to an actual
> amount of time longer than the caller requested. If time is slowly
> advancing backward, this could have the undesirable effect of extending
> the actual timeout indefinitely. And if time has advanced forward
> faster than normal (either by being set or due to a system suspend), it
> would have the undesirable effect of reducing the actual timeout to an
> amount of time shorter than the caller requested.
> Thank you!
> Lewis
> [1] It seems that most, if not all, implementations of monotonic time
> will suspend the monotonic clock during a system suspend. This
> way, programs using time from such a monotonic clock will function
> normally through a system suspend-resume cycle. However, if
> the process itself is suspended, when it resumes, it will see a
> monotonic time that has advanced "faster" than it expected. In
> other words, the monotonic time is per-system, not per-process. (I
> see that Linux has a CLOCK_PROCESS_CPUTIME_ID clock type that would
> overcome this, but I'm not sure something like this is available on
> the other OSes supported by EPICS.)

Related branches

Revision history for this message
mdavidsaver (mdavidsaver) wrote :

I think it wouldn't be difficult to add a real monotonic time source which defaults to epicsTimeGetCurrent() for platforms without such a time source. POSIX has clock_gettime w/ CLOCK_MONOTONIC and similar (RTEMS implements this). Windows has something as well. Not sure about vxWorks.

Revision history for this message
J. Lewis Muir (jlmuir) wrote :

PEP 418 <http://legacy.python.org/dev/peps/pep-0418/>, while obviously for Python, does include an overview of time functions available on different operating systems as well as some references on the subject, so it might be a help for implementing this on other platforms supported by EPICS.

Changed in epics-base:
assignee: nobody → mdavidsaver (mdavidsaver)
Revision history for this message
mdavidsaver (mdavidsaver) wrote :
Download full text (3.6 KiB)

Andrew asks:

> Can explain in writing which subsystems you think should be changed to use the monotonic clock? I suspect that may turn out to be a rather large can of worms (the like of which I have delved into before). I realize that's not relevant to this branch, but I would like to start thinking about it.

As previously stated the first candidate is the timer queue. Some worms can be expected here in trying to define behaviors for absolute and relative timers in one queue.

The FLL in dbScan should probably use monotonic time.

RSRV and logClient use epicsTimeGetCurrent() to test for timeouts. Strictly speaking this should be switched to monotonic time, but except for large jumps (resync after extended network partition) this wouldn't see any real work use.

I'd also like to revisit generalTime in a significant way. Performance wise I'd like to get rid of the global timeListLock and eventListLock locks. I'd also like to remove the current backwards time prevention check from the OSI layer, both because this is the primary reason for the locks, and because I think the design is inherently infeasible, and unnecessary for most targets.

The generalTime API tries to encompass two features which are conceptually separate.

1) epicsTimeGetEvent() Get the last (cached) time that some numbered event occurred.
2) epicsTimeGetCurrent() Provide real (wall clock) time an the moment the call is made.

There are also the associated support functions to add providers, and generalTimeGetExceptPriority() which is a slight generalization of epicsTimeGetCurrent().

And the variants epicsTimeGetEvent() and epicsTimeGetCurrentInt(), which only support a single provider, and promise to be safely callable in interrupt context.

1) epicsTimeGetEvent()

With epicsTimeGetEvent() I think it would be reasonable to remove support for multiple providers. Most IOCs have no event provider, some have one, but I'm not aware of any with more. Code-wise this could be identical to the ISR-safe variant, and could perhaps be deprecated in favor of the ISR safe variant.

It might also be interesting to combine this with the named events of dbScan and perhaps have Base maintain the event cache (in an ISR safe manner).

2) epicsTimeGetCurrent()

I think that epicsTimeGetCurrent() should become mostly OSD. The default except for RTEMS/vxWorks should be to use the OS current time calls with no backwards/jump protection. This would delegate maintenance of current time to the OS, which already has to do this.

Since RTEMS (and presumably vxWorks) lacks a common API for managing the OS tick timer, I would think to promote the present osiClockTime.c source as the default, perhaps with some ntpd-like logic to measure frequency and soften jumps by a linear scaling instead of just calling clock_settime().

Alternately, if RTEMS is the only holdout, maybe we fix RTEMS. While there is no uniform API, for PPC at least, there isn't much variation.

To handle the case where more than one real time source is available I would change the provider registration API to 1) only allow registration before iocInit(), 2) allow a newly registered provider to learn about the existing provide...


Andrew Johnson (anj)
Changed in epics-base:
status: New → In Progress
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.