Kernel thread

Out-of-band threads in kernel space

The EVL core can run common kernel threads on the out-of-band stage, which can be used in out-of-band capable drivers when ultra-low response time is required.

int evl_run_kthread(struct evl_kthread *kthread, void (*threadfn)(void *arg), void *arg, int priority, int clone_flags, const char *fmt, ...)

evl_run_kthread() is a macro-definition which spawns an EVL kernel thread, which is the EVL equivalent of its in-band kernel counterpart named kthread_run().

The new thread may be pinned on any of the out-of-band capable CPUs (See the evl.oob_cpus kernel parameter). If you need to spawn a kernel thread on a particular CPU, you may want to use evl_run_kthread_on_cpu() instead.

  • kthread

    A kernel thread descriptor where the core will maintain the per-thread context information. This memory area must remain valid as long as the associated kernel thread runs.

  • threadfn

    The routine to run in the new thread context.

  • arg

    A user-defined opaque pointer which is passed unmodified to threadfn as its sole argument.

  • priority

    The priority of the new thread, which is assumed to refer to the SCHED_FIFO class.

  • clone_flags

    A set of creation flags for the new kernel thread, defining its visibility: - EVL_CLONE_PUBLIC denotes a public thread which is represented by a device file in the /dev/evl file hierarchy, which makes it visible to application processes for sharing.

    • EVL_CLONE_PRIVATE denotes a thread which is private to the kernel. No device file appears for it in the /dev/evl file hierarchy.
  • fmt

    A ksprintf()-like format string to generate the thread name. Unlike evl_attach_thread() from the user API, evl_run_kthread() does not look for any shorthand defined by the naming convention for application threads. Thread visibility can be set exclusively by using the _cloneflags.

  • ...

    The optional variable argument list completing the format.

  • evl_run_kthread() returns zero on success, or a negated error code otherwise:

    • -EEXIST The generated name is conflicting with an existing thread name.

    • -EINVAL Either _cloneflags or priority are wrong.

    • -ENAMETOOLONG The overall length of the device element’s file path including the generated name exceeds PATH_MAX.

    • -ENOMEM Not enough memory available. Buckle up.

    int evl_run_kthread_on_cpu(struct evl_kthread *kthread, int cpu, void (*threadfn)(void *arg), void *arg, int priority, int clone_flags, const char *fmt, ...)

    As its name suggests, evl_run_kthread_on_cpu() is a variant of evl_run_kthread() which lets you pick a particular CPU for pinning the new kernel thread.

  • cpu

    The CPU number the new thread should be pinned to, among the out-of-band capable ones (See the evl.oob_cpus kernel parameter).

  • evl_run_kthread_on_cpu() returns zero on success, or a negated error code. The set of error conditions for evl_run_kthread() apply to evl_run_kthread_on_cpu(), plus:

    • -EINVAL cpu is not a valid, out-of-band capable CPU.

    void evl_stop_kthread(struct evl_kthread *kthread)

    This call requests the EVL kthread to exit at the first opportunity. It may be called from any stage, but only from a kernel thread context, regular in-band or EVL.

    This is an advisory method for stopping EVL kernel threads, which requires kthread to call evl_kthread_should_stop() as part of its regular work loop, exiting when such test returns true. In other words, evl_stop_kthread() raises the condition which evl_kthread_should_stop() returns to its caller.

    evl_stop_kthread() first unblocks kthread from any blocking call, then waits for kthread to actually exit before returning to the caller. Therefore, an EVL kernel thread which receives a request for termination while sleeping on some EVL call unblocks with -EINTR as a result.

    There is no way to forcibly terminate kernel threads since this would potentially leave the kernel system in a broken, unstable state. Both the requestor and the subject kernel thread must cooperate for the later to follow an orderly process for exiting. The in-band equivalent is achieved with kthread_stop(), kthread_should_stop().

  • kthread

    The EVL kernel thread to send a stop request to. If kthread represents the calling context (i.e. self-termination), the call does not return and the caller is exited immediately. Otherwise, the stop request is left pending until kthread eventually calls evl_kthread_should_stop(), at which point it should act upon this event by exiting.

  • bool evl_kthread_should_stop(void)

    This call is paired with evl_stop_kthread(). It should be called by any EVL kernel thread which intends to accept termination requests from other threads.

    Whenever evl_kthread_should_stop() returns true, the caller should plan for exiting as soon as possible, typically by returning from its entry routine. Otherwise, it may continue.

    A typical usage pattern is as follows:

    #include <evl/thread.h>
    #include <evl/flag.h>
    static DEFINE_EVL_FLAG(some_flag);
    void some_kthread(struct evl_kthread *kthread)
    	int ret;
    	for (;;) {
    		if (evl_kthread_should_stop())
    		/* wait for the next processing signal */
    		ret = evl_wait_flag(&some_flag);
    		if (ret == -EINTR)
    		/* do some useful stuff */
    	/* about to leave, do some cleanup */

    int evl_set_kthread_priority(struct evl_kthread *kthread, int priority)

    This service changes the priority of an EVL kernel thread.

  • kthread

    The descriptor of the EVL kernel thread.

  • priority

    The new priority of kthread, which is assumed to refer to the SCHED_FIFO class.

  • evl_set_kthread_priority() returns zero on success, otherwise a negated error code is returned:

    -EINVAL priority is invalid. Check the documentation of the SCHED_FIFO class for details.

    evl_set_kthread_priority() immediately applies the changes to the scheduling attributes of kthread.

    struct evl_kthread *evl_current_kthread(void)

    Returns the descriptor of the current EVL kernel thread. NULL is returned when calling this service from any other type of thread context (i.e. EVL user thread, non-EVL thread).

    evl_current_kthread() does not account for the interrupt context; a non-NULL pointer to the interrupted kernel thread may be returned if called from the IRQ handler.

    Alt text

    ktime_t evl_delay(ktime_t timeout, enum evl_tmode timeout_mode, struct evl_clock *clock)

    int evl_sleep_until(ktime_t timeout)

    int evl_sleep(ktime_t delay)

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

    int evl_wait_period(unsigned long *overruns_r)

    Last modified: Tue, 22 Dec 2020 17:32:06 CET