Core thread

EVL core threads

Both user space and kernel threads are based on EVL core threads, which descriptor is struct evl_thread in the implementation. An EVL thread running in user space is fully described by the struct evl_thread type. On the other hand, an EVL kernel thread extends a struct evl_thread core thread, i.e.:

struct evl_kthread {
	struct evl_thread thread;
	...
};

This document describes the public API which is usable with any EVL thread, running in user or kernel space. Anywhere struct evl_thread * is accepted in the API, given a struct evl_kthread kthread descriptor, you may pass &kthread.thread to refer to the core thread underlying that kernel thread.


int evl_sleep(ktime_t delay)

Delay the calling EVL thread for a specified amount of time, such thread sleeps without consuming any CPU.

  • delay

    The delay value (relative timeout value). The special value EVL_INFINITE means infinite sleep, in which case the thread can resume only if forcibly unblocked by a call to evl_unblock_thread().

  • Returns zero after a complete sleep, or -EINTR if the call was forcibly unblocked.


    int evl_sleep_until(ktime_t timeout)

    Block the calling EVL thread until a given date.

  • timeout

    The wake up date (absolute timeout value), which is implicitly based on the monotonic clock evl_mono_clock.

  • Returns zero after a complete sleep, or -EINTR if the call was forcibly unblocked.


    void evl_unblock_thread(struct evl_thread *thread, int reason)

    Forcibly unblock the thread referred to by thread. In other words, the blocking system call is forced to fail, and as a result the target thread receives the -EINTR error on return. If the thread is not blocked, this call is a nop.

  • thread

    The descriptor of the EVL thread to unblock.

  • reason

    A bitmask which gives additional information to the thread about the reason why it was forcibly unblocked. In the common case, reason should be zero. A non-zero value contains a flag bit matching a particular situation, which translates to a specific error status.


  • int evl_set_period(struct evl_clock *clock, ktime_t idate, ktime_t period)

    Running a periodic work loop is common practice for real-time applications. evl_set_period() enables the calling thread’s private periodic timer by programming its first release point and its period in the processor time line. Subsequent calls to evl_wait_period() delay the caller until the next periodic release point in the timeline is reached. In other words, the periodic work takes place between two invocations of evl_wait_period(), and such work must not last longer than the planned period. Whenever a periodic thread does not call evl_wait_period() soon enough to consume the latest notification before the current period ends, an overrun is said to occur.

  • clock

    The descriptor of the EVL clock device which should be used for timings. You would use &evl_mono_clock for a monotonic clock based on the clock device the EVL core provides.

  • idate

    The initial (absolute) date of the first release point, based on clock. The caller is delayed by the first call to evl_wait_period() until this point is reached. If idate equals EVL_INFINITE, the first release point is set to period nanoseconds after the current date.

  • period

    The period of the thread, based on the clock unit. Passing EVL_INFINITE can be used to stop the caller’s periodic timer, leaving periodic mode.

  • Zero is returned upon success, otherwise:

    • -ETIMEDOUT is returned if idate is different from EVL_INFINITE and represents a date in the past.

    • -EINVAL is returned if period is different from EVL_INFINITE but shorter than the monotonic clock gravity value.

    • -EPERM is returned if the caller is not an EVL thread.


    int evl_wait_period(unsigned long *overruns_r)

    Block the caller until the next periodic release point in the processor time line. This call is paired with evl_set_period() which sets the period. This call detects missed wake ups, aka overruns.

  • overruns_r

    If non-NULL, the count of pending overruns is copied to that address unless -EINTR was received (see errors below). The copied value is non-zero if -ETIMEDOUT is returned, zero otherwise.

  • Zero is returned upon success, otherwise:

    • -EAGAIN is returned if the caller did not set the period using evl_set_period().

    • -EINTR is returned if the caller was forcibly unblocked by a call to evl_thread_unblock() before the release point was reached. The overrun count is meaningless in this case.

    • -ETIMEDOUT is returned if the caller has overrun, which indicates that one or more previous release points have been missed. If overruns_r is valid, the count of pending overruns is copied to the memory location.


    struct evl_thread *evl_current(void)

    Return the EVL core thread descriptor of the caller. NULL is returned if the caller is not an EVL thread.

    Both user and kernel space threads would receive a non-NULL pointer. Common Linux threads would receive NULL.


    Last modified: Thu, 06 Apr 2023 15:08:57 +0200