The EVL core can run common kernel threads on the out-of-band stage
(i.e. the equivalent of the struct kthread
from the regular kernel),
which you can use in out-of-band capable drivers when ultra-low response time is
required.
The API we are discussing in this page specifically belongs to the kernel thread support for EVL. If you are looking for the public API to deal from a driver with any type of EVL thread - either running in user or kernel space - then this document is appropriate.
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.
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.
The routine to run in the new thread context.
A user-defined opaque pointer which is passed unmodified to threadfn as its sole argument.
If greater than zero, the value is interpreted as the priority of the new thread in the EVL SCHED_FIFO class. Otherwise, the SCHED_WEAK policy is assumed.
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.
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 clone_flags.
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 clone_flags 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.
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.
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:
This call requests the EVL kernel thread 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().
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.
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())
break;
/* wait for the next processing signal */
ret = evl_wait_flag(&some_flag);
if (ret == -EINTR)
break;
/* do some useful stuff */
}
/* about to leave, do some cleanup */
}
Change the priority of an EVL kernel thread.
The descriptor of the EVL kernel thread.
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
.
Return 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.
Wait for an EVL kernel thread to exit. The caller returns immediately
if kthread
is already in a dormant state. Otherwise, it blocks until
kthread
returns from its base function. This routine may be called
only from the in-band stage.
The descriptor of the EVL kernel thread.
A boolean telling whether the caller may be interrupted while
sleeping, causing the routine to return with -EINTR. If true
, the
caller cannot be interrupted.
Zero is returned on success, otherwise:
-EINTR is returned if the caller received a signal while
sleeping. This can happen only if uninterruptible
is false
.
-EINVAL is returned if the caller is returned if kthread
is the
root placeholder for the current CPU. The latter is an internal
descriptor which drivers should never have to refer to anyway.
-EDEADLK is returned if kthread
is mapped to the calling context,
meaning the caller attempts to wait for its own exit, which is not
going to happen anytime soon.
Return the EVL kernel thread descriptor of the caller. NULL is returned if the caller is not an EVL kernel thread.
Only a kernel space thread started with evl_run_kthread() would receive a non-NULL pointer. EVL user thread and common Linux threads would receive NULL.