An EVL kernel flag is a basic synchronization mechanism based on the EVL wait queue, which can be used to wait for a boolean state to be notified. This is typically used in interrupt to thread synchronization, with the former posting a wakeup event to the latter by mean of raising a flag.
This call initializes a kernel flag.
A flag descriptor is constructed by evl_init_flag(), which contains ancillary information other
calls will need. wf
is a pointer to such descriptor of type
struct evl_flag
.
This call destroys an existing EVL kernel flag. Any thread which might blocked waiting on the flag is woken up by this call, receiving a ‘resource removed’ status (-EIDRM).
The descriptor of the kernel flag to be destroyed.
This service waits for the flag to be raised. Until this happens, the caller is blocked until a call to evl_raise_flag() eventually releases it. If the flag was already raised on entry, the caller returns immediately. Waiters are queued by order of scheduling priority.
The flag descriptor constructed by either evl_init_flag(), or statically built with EVL_FLAG_INITIALIZER.
Zero is returned on success, otherwise:
-EIDRM The flag was deleted while the caller was sleeping on it. When this status is returned, the flag must be considered stale and should not be accessed anymore.
-EINTR The sleep was interrupted or forcibly unblocked.
This call is a variant of evl_wait_flag() which allows specifying a timeout on the operation, so that the caller is automatically unblocked when a time limit is reached.
The flag descriptor constructed by either evl_init_flag(), or statically built with EVL_FLAG_INITIALIZER.
A time limit for the call. There are two special values:
EVL_NONBLOCK
tells the core NOT to block the caller if the flag
is not raised on entry, EVL_INFINITE
means no time limit only if
timeout_mode
is EVL_REL
(See evl_wait_flag()).
A timeout mode, telling the core whether timeout
should be
interpreted as a relative value representing a delay (EVL_REL
), or
an absolute date (EVL_ABS
).
Zero is returned on success, otherwise:
-ETIMEDOUT The timeout fired, after the amount of time specified by
timeout
.
-EAGAIN EVL_NONBLOCK
was given in timeout
but the flag
was not in a signaled state on entry.
-EIDRM The flag was deleted while the caller was sleeping on it. When this status is returned, the flag must be considered stale and should not be accessed anymore.
-EINTR The sleep was interrupted or forcibly unblocked.
Returns the descriptor of the EVL kernel thread leading the wait queue.
The flag descriptor constructed by either evl_init_flag(), or statically built with EVL_FLAG_INITIALIZER.
The flag must have been locked by a call to evl_lock_flag() prior to calling this routine.
The thread descriptor returned by this call is guaranteed valid only
while such lock is held by the caller. A reference can be taken on
that thread via a call to evl_get_element()
while the flag is
locked, in order to extend the guarantee until the last reference is
dropped by a call to evl_put_element()
. In the meantime, the flag
may be unlocked safely, without the thread going stale.
int peek_at_flag(struct evl_flag *wf)
{
struct evl_thread *t = NULL;
unsigned long flags;
evl_lock_flag(wf, flags);
t = evl_wait_flag_head(wf);
if (t) /* Prevent 't' from going stale once the flag is unlocked. */
evl_get_element(&t->element);
evl_unlock_flag(wf, flags);
if (!t)
return -EAGAIN;
do_stuff(t);
evl_put_element(&t->element); /* Drop the reference. */
return 0;
}
evl_wait_flag_head() returns a pointer to the descriptor of the EVL thread currently leading the wait queue, or NULL if none.
evl_raise_flag_nosched() transitions the flag to the notified state, allowing all waiters to compete for consuming the notification. The thread winning this race resets the flag then unblocks from evl_wait_flag(), others go back sleeping until the next event is signaled. The rescheduling procedure is not called by this routine, which makes it usable in sections of code guarded by spinlocks.
This call transitions the flag to a notified state until the event is consumed by one of the waiters which is unblocked as a result. If you look for a pulse-mode notification which unblocks all threads waiting for the next notification, you should refer to evl_pulse_flag_nosched() instead.
The flag descriptor constructed by either evl_init_flag(), or statically built with EVL_FLAG_INITIALIZER.
The caller MUST call evl_schedule() afterwards, as soon as all locks have been dropped.
evl_raise_flag() has the same synchronization effect than evl_raise_flag_nosched() but does invoke the rescheduling procedure implicitly in case a thread was resumed as a result of the operation.
The flag descriptor constructed by either evl_init_flag(), or statically built with EVL_FLAG_INITIALIZER.
evl_pulse_flag_nosched() broadcasts a notification so that all waiters can consume the same event, differing from evl_raise_flag_nosched() which only allows a single waiter to do so. This operation does not transition the flag to the notified state. The rescheduling procedure is not called by this routine, which makes it usable in sections of code guarded by spinlocks.
The flag descriptor constructed by either evl_init_flag(), or statically built with EVL_FLAG_INITIALIZER.
evl_pulse_flag() has the same synchronization effect than evl_pulse_flag_nosched() but does invoke the rescheduling procedure implicitly in case a thread was resumed as a result of the operation.
The flag descriptor constructed by either evl_init_flag(), or statically built with EVL_FLAG_INITIALIZER.
evl_flush_flag_nosched() is a variant of evl_pulse_flag_nosched() which allows the caller to specify the wake up bitmask passed to the underlying wait queue, instead of T_BCAST. This bitmask describes the reason for the wake up.
This call is part of the inner EVL kernel API, any misusage can lead to serious trouble. If you do not know about the internal wake up logic, then you should refrain from using it.
The flag descriptor constructed by either evl_init_flag(), or statically built with EVL_FLAG_INITIALIZER.
A bitmask which gives additional information to the resuming threads
about the reason why they were 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 for
evl_wait_schedule().
evl_flush_flag() has the same synchronization effect than evl_flush_flag_nosched() but does invoke the rescheduling procedure implicitly in case a thread was resumed as a result of the operation.
Reset the flag state to unnotified.
The flag descriptor constructed by either evl_init_flag(), or statically built with EVL_FLAG_INITIALIZER.
A macro which expands as a static initializer you can use in a C statement creating an EVL kernel flag.
The C variable name to which the initializer should be assigned.
struct evl_flag foo = EVL_FLAG_INITIALIZER(foo);
A macro which expands as a C statement defining an initialized EVL kernel flag.
The C variable name of the kernel flag to define.
/*
* The following expands as:
* static struct evl_flag bar = EVL_FLAG_INITIALIZER(bar);
*/
static DEFINE_EVL_FLAG(bar);