Motr
M0
|
Data Structures | |
struct | m0_chan |
struct | m0_clink |
struct | m0_chan_addb2 |
Typedefs | |
typedef bool(* | m0_chan_cb_t) (struct m0_clink *link) |
Functions | |
M0_TL_DESCR_DEFINE (clink, "chan clinks", static, struct m0_clink, cl_linkage, cl_magic, M0_LIB_CHAN_MAGIC, M0_LIB_CHAN_HEAD_MAGIC) | |
M0_TL_DEFINE (clink, static, struct m0_clink) | |
static bool | clink_is_head (const struct m0_clink *clink) |
M0_INTERNAL void | m0_chan_lock (struct m0_chan *ch) |
M0_INTERNAL void | m0_chan_unlock (struct m0_chan *ch) |
M0_INTERNAL bool | m0_chan_is_locked (const struct m0_chan *ch) |
static bool | m0_chan_invariant (struct m0_chan *chan) |
M0_INTERNAL void | m0_chan_init (struct m0_chan *chan, struct m0_mutex *ch_guard) |
M0_INTERNAL void | m0_chan_fini (struct m0_chan *chan) |
M0_INTERNAL void | m0_chan_fini_lock (struct m0_chan *chan) |
static void | clink_signal (struct m0_clink *clink) |
static void | chan_signal_nr (struct m0_chan *chan, uint32_t nr) |
M0_INTERNAL void | m0_chan_signal (struct m0_chan *chan) |
M0_INTERNAL void | m0_chan_signal_lock (struct m0_chan *chan) |
M0_INTERNAL void | m0_chan_broadcast (struct m0_chan *chan) |
M0_INTERNAL void | m0_chan_broadcast_lock (struct m0_chan *chan) |
M0_INTERNAL bool | m0_chan_has_waiters (struct m0_chan *chan) |
static void | clink_init (struct m0_clink *link, struct m0_clink *group, m0_chan_cb_t cb) |
M0_INTERNAL void | m0_clink_init (struct m0_clink *link, m0_chan_cb_t cb) |
M0_INTERNAL void | m0_clink_fini (struct m0_clink *link) |
M0_INTERNAL void | m0_clink_attach (struct m0_clink *link, struct m0_clink *group, m0_chan_cb_t cb) |
M0_INTERNAL void | m0_clink_add (struct m0_chan *chan, struct m0_clink *link) |
void | m0_clink_add_lock (struct m0_chan *chan, struct m0_clink *link) |
M0_INTERNAL void | m0_clink_del (struct m0_clink *link) |
M0_INTERNAL void | m0_clink_del_lock (struct m0_clink *link) |
M0_INTERNAL bool | m0_clink_is_armed (const struct m0_clink *link) |
M0_INTERNAL void | m0_clink_cleanup (struct m0_clink *link) |
M0_INTERNAL void | m0_clink_cleanup_locked (struct m0_clink *link) |
M0_INTERNAL void | m0_clink_signal (struct m0_clink *clink) |
M0_INTERNAL bool | m0_chan_trywait (struct m0_clink *link) |
M0_INTERNAL void | m0_chan_wait (struct m0_clink *link) |
M0_INTERNAL bool | m0_chan_timedwait (struct m0_clink *link, const m0_time_t abs_timeout) |
Variables | |
struct m0_chan | M0_XCA_DOMAIN |
Waiting channel.
A channel (m0_chan) is a stream of asynchronous events that a channel user can wait or register a call-back for.
A clink (m0_clink) is a record of interest in events on a particular channel. A user adds a clink to a channel and appearance of new events in the stream is recorded in the clink.
There are two interfaces related to channels:
- producer interface. It consists of m0_chan_signal(), m0_clink_signal() and m0_chan_broadcast() functions. These functions are called to declare that new asynchronous event happened in the stream. - consumer interface. It consists of m0_clink_add(), m0_clink_del(), m0_chan_wait() and m0_chan_trywait() functions.
When a producer declares an event on a channel, this event is delivered. If event is a broadcast (m0_chan_broadcast()) it is delivered to all clinks registered with the channel. If event is a signal (m0_chan_signal()) it is delivered to a single clink (if any) registered with the channel. Clinks for delivery of consecutive signals are selected in a round-robin manner.
A special m0_clink_signal() function is provided to signal a particular clink. m0_clink_signal() delivers a signal to its argument clink. This function does not take any locks and is designed to be used in "awkward" contexts, like interrupt handler or timer call-backs, where blocking on a lock is not allowed. Use sparingly.
The method of delivery depends on the clink interface used (m0_clink). If clink has a call-back, the delivery starts with calling this call-back. If a clink has no call-back or the call-back returns false, the delivered event becomes pending on the clink. Pending events can be consumed by calls to m0_chan_wait(), m0_chan_timedwait() and m0_chan_trywait().
Filtered wake-ups.
By returning true from a call-back, it is possible to "filter" some events out and avoid potentially expensive thread wake-up. A typical use case for this is the following:
The idea behind this idiom is that the call-back is called in the same context where the event is declared and it is much cheaper to test whether a condition is right than to wake up a waiting thread that would check this and go back to sleep if it is not.
Multiple channels.
It is possible to wait for an event to be announced on a channel from a set. To this end, first a clink is created as usual. Then, additional (unintialised) clinks are attached to the first by a call to m0_clink_attach(), forming a "clink group" consisting of the original clink and all clinks attached. Clinks from the group can be registered with multiple (or the same) channels. Events announced on any channel are delivered to all clinks in the group.
Groups are used as following:
- initialise a "group head" clink; - attach other clinks to the group, without initialising them; - register the group clinks with their channels, starting with the head; - to wait for an event on any channel, wait on the group head. - call-backs can be used for event filtering on any channel as usual; - de-register the clinks, head last.
A simplistic user space implementation of m0_chan and m0_clink interfaces based on POSIX semaphores.
A list of registered clinks is maintained for each channel. Each clink has a semaphore, used to wait for pending events. When an event is declared on the channel, a number (depending on whether event is signalled or broadcast) of clinks on the channel list is scanned and for each of them either call-back is called or semaphore is upped.
To wait for an event, a user downs clink semaphore.
Semaphore is initialized every time when the clink is registered with a channel (m0_clink_add()) and destroyed every time the clink is deleted from a channel (m0_clink_del()). This guarantees that semaphore counter is exactly equal to the number of pending events declared on the channel.
typedef bool(* m0_chan_cb_t) (struct m0_clink *link) |
|
static |
|
static |
|
static |
|
static |
M0_INTERNAL void m0_chan_broadcast | ( | struct m0_chan * | chan | ) |
Notifies all clinks currently registered with the channel that a new event happened.
No guarantees about behaviour in the case when clinks are added or removed while m0_chan_broadcast() is running.
If clinks with call-backs (m0_clink::cl_cb) are registered with the channel at the time of this call, the call-backs are run to completion as part of broadcast.
Definition at line 172 of file chan.c.
M0_INTERNAL void m0_chan_broadcast_lock | ( | struct m0_chan * | chan | ) |
Calls m0_chan_broadcast() with ch_guard locked.
Definition at line 178 of file chan.c.
M0_INTERNAL void m0_chan_fini | ( | struct m0_chan * | chan | ) |
M0_INTERNAL void m0_chan_fini_lock | ( | struct m0_chan * | chan | ) |
M0_INTERNAL bool m0_chan_has_waiters | ( | struct m0_chan * | chan | ) |
True iff there are clinks registered with the chan.
Definition at line 185 of file chan.c.
|
static |
M0_INTERNAL bool m0_chan_is_locked | ( | const struct m0_chan * | ch | ) |
M0_INTERNAL void m0_chan_lock | ( | struct m0_chan * | ch | ) |
M0_INTERNAL void m0_chan_signal | ( | struct m0_chan * | chan | ) |
Notifies a clink currently registered with the channel that a new event happened.
Definition at line 159 of file chan.c.
M0_INTERNAL void m0_chan_signal_lock | ( | struct m0_chan * | chan | ) |
Calls m0_chan_signal() with ch_guard locked.
Definition at line 165 of file chan.c.
This is the same as m0_chan_wait, except that it has an expire time. If the time expires before event is pending, this function will return false.
abs_timeout | absolute time since Epoch (00:00:00, 1 January 1970) |
Definition at line 349 of file chan.c.
M0_INTERNAL bool m0_chan_trywait | ( | struct m0_clink * | link | ) |
True there is an event pending in the clink. When this function returns true, the event is consumed, exactly like if m0_chan_wait() were called instead.
Definition at line 331 of file chan.c.
M0_INTERNAL void m0_chan_unlock | ( | struct m0_chan * | ch | ) |
M0_INTERNAL void m0_chan_wait | ( | struct m0_clink * | link | ) |
Returns when there is an event pending in the clink. The event is consumed before the call returns.
Note that this implies that if an event happened after the clink has been registered (by a call to m0_clink_add()) and before call to m0_chan_wait(), the latter returns immediately.
User must guarantee that no more than one thread waits on the clink.
Definition at line 336 of file chan.c.
Calls m0_clink_add() with ch_guard locked.
Definition at line 255 of file chan.c.
M0_INTERNAL void m0_clink_attach | ( | struct m0_clink * | link, |
struct m0_clink * | group, | ||
m0_chan_cb_t | cb | ||
) |
Attaches a clink group. is the original clink in the group.
Definition at line 215 of file chan.c.
M0_INTERNAL void m0_clink_cleanup | ( | struct m0_clink * | link | ) |
M0_INTERNAL void m0_clink_cleanup_locked | ( | struct m0_clink * | link | ) |
M0_INTERNAL void m0_clink_del | ( | struct m0_clink * | link | ) |
M0_INTERNAL void m0_clink_del_lock | ( | struct m0_clink * | link | ) |
Calls m0_clink_del() with ch_guard locked.
Definition at line 293 of file chan.c.
M0_INTERNAL void m0_clink_init | ( | struct m0_clink * | link, |
m0_chan_cb_t | cb | ||
) |
M0_INTERNAL bool m0_clink_is_armed | ( | const struct m0_clink * | link | ) |
M0_INTERNAL void m0_clink_signal | ( | struct m0_clink * | clink | ) |
Notifies a given clink that a new event happened.
This function takes no locks.
m0_chan_signal() should be used instead, unless the event is announced in a context where blocking is not allowed.
Definition at line 326 of file chan.c.
M0_TL_DESCR_DEFINE | ( | clink | , |
"chan clinks" | , | ||
static | , | ||
struct m0_clink | , | ||
cl_linkage | , | ||
cl_magic | , | ||
M0_LIB_CHAN_MAGIC | , | ||
M0_LIB_CHAN_HEAD_MAGIC | |||
) |
struct m0_chan M0_XCA_DOMAIN |