Clock element

The target platform can provide particular clock chips and/or clock source drivers in addition to the architecture-specific ones. For instance, some device on a PCI bus could provide a timer which the application wants to use for timing its threads, in addition to the architected timer found on ARM64 and some ARM-based SoCs. The timer hardware would be accessed through the EVL core via a dedicated kernel driver.

EVL’s clock element ensures all clock drivers present the same interface to applications in user-space. In addition, the clock element can export individual software timers to applications which comes in handy for running periodic loops or waiting for oneshot events on a specific time base.

Some built-in clocks are pre-defined by the EVL core for reading the monotonic and wallclock time of the system.

EVL abstracts clock event devices and clock sources (timekeeping hardware) into a single clock element.

Clock services

int evl_read_clock(int clockfd, struct timespec *tp)

This call is the EVL equivalent of the POSIX clock_gettime(3) service, for reading the time from a specified EVL clock. It reads the current time maintained by the EVL clock, which is returned as counts of seconds and microseconds since the clock’s epoch.

  • clockfd

    The clock file descriptor, which can be:

    • any valid file descriptor received as a result of opening a clock device in /dev/evl/clock.

    • the identifier of a built-in EVL clock, such as EVL_CLOCK_MONOTONIC or EVL_CLOCK_REALTIME.

  • tp

    A pointer to a timespec structure which should receive the time stamp.

  • evl_read_clock() writes the timestamp to tp then returns zero on success, otherwise:

    • -EBADF if clockfd is neither a built-in clock identifier or a valid file descriptor.

    • -ENOTTY if clockfd does not refer to an EVL clock device.

    • -EFAULT if tp points to invalid memory.


    int evl_set_clock(int clockfd, const struct timespec *tp)

    This call is the EVL equivalent of the POSIX clock_settime(3) service, for setting the time of a specified EVL clock.

  • clockfd

    The clock file descriptor, which can be:

    • any valid file descriptor received as a result of opening a clock device in /dev/evl/clock.

    • the identifier of a built-in EVL clock, such as EVL_CLOCK_MONOTONIC or EVL_CLOCK_REALTIME.

  • tp

    A pointer to a timespec structure which should receive the time stamp.

  • evl_set_clock() returns zero and the clock is set to the specified time on success, otherwise:

    • -EINVAL if the time specification referred to by ts is invalid (e.g. ts->tv_nsec not in the [0..1e9] range).

    • -EBADF if clockfd is neither a built-in clock identifier or a valid file descriptor.

    • -EPERM if the caller does not have the permission to set some built-in clock via clock_settime(3). See note.

    • -ENOTTY if clockfd does not refer to an EVL clock device.

    • -EFAULT if tp points to invalid memory.

    Setting EVL_CLOCK_MONOTONIC or EVL_CLOCK_REALTIME may imply a transition to the in-band execution stage as clock_settime() is called internally for carrying out the request.


    int evl_get_clock_resolution(int clockfd, struct timespec *tp)

    This call is the EVL equivalent of the POSIX clock_getres(3) service, for reading the resolution of a specified EVL clock. It returns this value as counts of seconds and microseconds. The resolution of clocks depends on the implementation and cannot be configured.

  • clockfd

    The clock file descriptor, which can be:

    • any valid file descriptor received as a result of opening a clock device in /dev/evl/clock.

    • the identifier of a built-in EVL clock, such as EVL_CLOCK_MONOTONIC or EVL_CLOCK_REALTIME.

  • tp

    A pointer to a timespec structure which should receive the resolution.

  • evl_get_clock_resolution() writes the resolution to tp then returns zero on success, otherwise:

    • -EBADF if clockfd is neither a built-in clock identifier or a valid file descriptor.

    • -ENOTTY if clockfd does not refer to an EVL clock device.

    • -EFAULT if tp points to invalid memory.

    Setting EVL_CLOCK_MONOTONIC or EVL_CLOCK_REALTIME may imply a transition to the in-band execution stage as clock_getres(3) is called internally for carrying out the request.


    int evl_sleep_until(int clockfd, const struct timespec *timeout)

    This call is the EVL equivalent of the POSIX clock_nanosleep(3) service, for blocking the caller until an arbitrary date expires on a specified EVL clock. Unlike its POSIX counterpart, evl_sleep_until() only accepts absolute timeout specifications though.

  • clockfd

    The clock file descriptor, which can be:

    • any valid file descriptor received as a result of opening a clock device in /dev/evl/clock.

    • the identifier of a built-in EVL clock, such as EVL_CLOCK_MONOTONIC or EVL_CLOCK_REALTIME.

  • timeout

    A pointer to a timespec structure which specifies the wake up date.

  • evl_sleep_until() blocks the caller until the wake up date expires then returns zero on success, otherwise:

    • -EBADF if clockfd is neither a built-in clock identifier or a valid file descriptor.

    • -ENOTTY if clockfd does not refer to an EVL clock device.

    • -EFAULT if timeout points to invalid memory.

    • -EINTR if the call was interrupted by an in-band signal, or forcibly unblocked by the EVL core.


    int evl_usleep(useconds_t usecs)

    This call puts the caller to sleep until a count of microseconds has elapsed. evl_usleep() invokes evl_sleep_until() for sleeping until the delay expires on the EVL_CLOCK_MONOTONIC clock.

  • usecs

    The count of microseconds to sleep for. This value should not exceed 1000000 (i.e. one second timeout). If zero, the call has no effect and returns immediately with a success status.

  • evl_usleep() blocks the caller until the delay expires then returns zero on success, otherwise:

    • -EINTR if the call was interrupted by an in-band signal, or forcibly unblocked by the EVL core.

    • -EINVAL if usecs is greater than 1000000.

    Pre-defined clocks

    EVL defines two built-in clocks, you can pass any of the following identifiers to EVL calls which ask for a clock file descriptor (usually noted as clockfd):

    • EVL_CLOCK_MONOTONIC is identical to the CLOCK_MONOTONIC POSIX clock, which is a monotonically increasing clock that cannot be set and represents time since some unspecified starting point (aka the epoch). This identifier has the same meaning than a file descriptor opened on /dev/evl/clock/monotonic.

    • EVL_CLOCK_REALTIME is identical to the CLOCK_REALTIME POSIX clock, which is a non-monotonic wall clock which can be manually set to an arbitrary value with proper privileges, and can also be subject to dynamic adjustements by the NTP system. This identifier has the same meaning than a file descriptor opened on /dev/evl/clock/realtime.

    If you are to measure the elapsed time between two events, you definitely want to use EVL_CLOCK_MONOTONIC.


    Last modified: Wed, 10 Jul 2024 15:05:01 +0200