|
M0_INTERNAL void | m0_sm_group_init (struct m0_sm_group *grp) |
|
M0_INTERNAL void | m0_sm_group_fini (struct m0_sm_group *grp) |
|
static void | _sm_group_lock (struct m0_sm_group *grp) |
|
M0_INTERNAL void | m0_sm_group_lock (struct m0_sm_group *grp) |
|
static void | _sm_group_unlock (struct m0_sm_group *grp) |
|
M0_INTERNAL void | m0_sm_group_unlock (struct m0_sm_group *grp) |
|
static bool | grp_is_locked (const struct m0_sm_group *grp) |
|
M0_INTERNAL bool | m0_sm_group_is_locked (const struct m0_sm_group *grp) |
|
M0_INTERNAL void | m0_sm_group_lock_rec (struct m0_sm_group *grp, bool runast) |
|
M0_INTERNAL void | m0_sm_group_unlock_rec (struct m0_sm_group *grp, bool runast) |
|
M0_INTERNAL void | m0_sm_ast_post (struct m0_sm_group *grp, struct m0_sm_ast *ast) |
|
M0_INTERNAL void | m0_sm_asts_run (struct m0_sm_group *grp) |
|
M0_INTERNAL void | m0_sm_ast_cancel (struct m0_sm_group *grp, struct m0_sm_ast *ast) |
|
static void | sm_lock (struct m0_sm *mach) |
|
static void | sm_unlock (struct m0_sm *mach) |
|
static bool | sm_is_locked (const struct m0_sm *mach) |
|
static bool | state_is_valid (const struct m0_sm_conf *conf, uint32_t state) |
|
static const struct m0_sm_state_descr * | state_get (const struct m0_sm *mach, uint32_t state) |
|
static const struct m0_sm_state_descr * | sm_state (const struct m0_sm *mach) |
|
M0_INTERNAL bool | sm_invariant0 (const struct m0_sm *mach) |
|
M0_INTERNAL bool | m0_sm_invariant (const struct m0_sm *mach) |
|
static bool | conf_invariant (const struct m0_sm_conf *conf) |
|
M0_INTERNAL void | m0_sm_init (struct m0_sm *mach, const struct m0_sm_conf *conf, uint32_t state, struct m0_sm_group *grp) |
|
M0_INTERNAL void | m0_sm_fini (struct m0_sm *mach) |
|
M0_INTERNAL void | m0_sm_conf_init (struct m0_sm_conf *conf) |
|
M0_INTERNAL void | m0_sm_conf_fini (struct m0_sm_conf *conf) |
|
M0_INTERNAL bool | m0_sm_conf_is_initialized (const struct m0_sm_conf *conf) |
|
M0_INTERNAL int | m0_sm_timedwait (struct m0_sm *mach, uint64_t states, m0_time_t deadline) |
|
static void | state_set (struct m0_sm *mach, int state, int32_t rc) |
|
M0_INTERNAL void | m0_sm_fail (struct m0_sm *mach, int fail_state, int32_t rc) |
|
void | m0_sm_state_set (struct m0_sm *mach, int state) |
|
M0_INTERNAL void | m0_sm_move (struct m0_sm *mach, int32_t rc, int state) |
|
static unsigned long | sm_timer_top (unsigned long data) |
|
static void | timer_done (struct m0_sm_timer *timer) |
|
static void | sm_timer_bottom (struct m0_sm_group *grp, struct m0_sm_ast *ast) |
|
M0_INTERNAL void | m0_sm_timer_init (struct m0_sm_timer *timer) |
|
M0_INTERNAL void | m0_sm_timer_fini (struct m0_sm_timer *timer) |
|
M0_INTERNAL int | m0_sm_timer_start (struct m0_sm_timer *timer, struct m0_sm_group *group, void(*cb)(struct m0_sm_timer *), m0_time_t deadline) |
|
M0_INTERNAL void | m0_sm_timer_cancel (struct m0_sm_timer *timer) |
|
M0_INTERNAL bool | m0_sm_timer_is_armed (const struct m0_sm_timer *timer) |
|
static void | timeout_ast (struct m0_sm_timer *timer) |
|
static bool | sm_timeout_cancel (struct m0_clink *link) |
|
M0_INTERNAL void | m0_sm_timeout_init (struct m0_sm_timeout *to) |
|
M0_INTERNAL int | m0_sm_timeout_arm (struct m0_sm *mach, struct m0_sm_timeout *to, m0_time_t timeout, int state, uint64_t bitmask) |
|
M0_INTERNAL void | m0_sm_timeout_fini (struct m0_sm_timeout *to) |
|
M0_INTERNAL bool | m0_sm_timeout_is_armed (const struct m0_sm_timeout *to) |
|
static bool | trans_exists (const struct m0_sm_conf *conf, uint32_t src, uint32_t tgt) |
|
M0_INTERNAL void | m0_sm_conf_trans_extend (const struct m0_sm_conf *base, struct m0_sm_conf *sub) |
|
M0_INTERNAL void | m0_sm_conf_extend (const struct m0_sm_state_descr *base, struct m0_sm_state_descr *sub, uint32_t nr) |
|
M0_INTERNAL const char * | m0_sm_conf_state_name (const struct m0_sm_conf *conf, int state) |
|
M0_INTERNAL const char * | m0_sm_state_name (const struct m0_sm *mach, int state) |
|
static void | sm_call_ast (struct m0_sm_group *grp, struct m0_sm_ast *ast) |
|
int | m0_sm_group_call (struct m0_sm_group *group, int(*cb)(void *), void *data) |
|
static int | sm_addb2_ctor (struct m0_sm_addb2_stats *stats, const struct m0_sm_conf *c) |
|
static void | sm_addb2_dtor (struct m0_sm_addb2_stats *stats, const struct m0_sm_conf *c) |
|
M0_INTERNAL int | m0_sm_addb2_init (struct m0_sm_conf *conf, uint64_t id, uint64_t counter) |
|
M0_INTERNAL void | m0_sm_addb2_fini (struct m0_sm_conf *conf) |
|
static void | sm_addb2_counter_init_add (struct m0_sm *sm) |
|
M0_INTERNAL bool | m0_sm_addb2_counter_init (struct m0_sm *sm) |
|
M0_INTERNAL void | m0_sm_ast_wait_init (struct m0_sm_ast_wait *wait, struct m0_mutex *ch_guard) |
|
M0_INTERNAL void | m0_sm_ast_wait_fini (struct m0_sm_ast_wait *wait) |
|
M0_INTERNAL void | m0_sm_ast_wait_prepare (struct m0_sm_ast_wait *wait, struct m0_clink *clink) |
|
M0_INTERNAL void | m0_sm_ast_wait_complete (struct m0_sm_ast_wait *wait, struct m0_clink *clink) |
|
M0_INTERNAL void | m0_sm_ast_wait_loop (struct m0_sm_ast_wait *wait, struct m0_clink *clink) |
|
M0_INTERNAL void | m0_sm_ast_wait (struct m0_sm_ast_wait *wait) |
|
M0_INTERNAL void | m0_sm_ast_wait_post (struct m0_sm_ast_wait *wait, struct m0_sm_group *grp, struct m0_sm_ast *ast) |
|
M0_INTERNAL void | m0_sm_ast_wait_signal (struct m0_sm_ast_wait *wait) |
|
M0_INTERNAL void | m0_sm_conf_print (const struct m0_sm_conf *conf) |
|
M0_INTERNAL uint64_t | m0_sm_id_get (const struct m0_sm *sm) |
|
This modules defines interfaces to functionality common to typical non-blocking state machines extensively used by Motr.
The main difference between "state machine" (non-blocking) code and "threaded" (blocking) code is that the latter blocks waiting for some events while having some computational state stored in the "native" C language stack (in the form of automatic variables allocated across the call-chain). Because of this the thread must remain dedicated to the same threaded activity not only during actual "computation", when processor is actively used, but also for the duration of wait. In many circumstances this is too expensive, because threads are heavy objects.
Non-blocking code, on the other hand, packs all its state into a special data-structures before some potential blocking points and unpacks it after the event of interest occurs. This allows the same thread to be re-used for multiple non-blocking computations.
Which blocking points deserve packing-unpacking depends on circumstances. Long-term waits for network or storage communication are prime candidates for non-blocking handling. Memory accesses, which can incur blocking page faults in a user space process are probably too ubiquitous for this. Memory allocations and data-structure locks fall into an intermediate group.
This module defines data-structures and interfaces to handle common non-blocking state-machine functionality:
- state tracking and state transitions;
- concurrency;
- interaction between a state machine and external world (both
non-blocking and threaded);
- accounting and statistics collection.
State and transitions.
State machine state is recorded in m0_sm::sm_state. This is supposed to be a relatively coarse-grained high level state, broadly determining state machine behaviour. An instance of m0_sm will typically be embedded into a larger structure containing fields fully determining state machine behaviour. Each state comes with a description. All descriptions for a particular state machine are packed into a m0_sm_conf::scf_state[] array.
State machine is transferred from one state to another by a call to m0_sm_state_set() (or its variant m0_sm_fail()) or via "chained" transitions, see below.
Concurrency.
State machine is a part of a state machine group (m0_sm_group). All state machines in a group use group's mutex to serialise their state transitions. One possible scenario is to have a group for all state machines associated with a given locality (m0_fom_locality). Alternatively a group-per-machine can be used.
Interaction.
The only "output" event that a state machine communicates to the external world is (from this module's point of view) its state transition. State transitions are announced on a per-machine channel (m0_sm::sm_chan). This mechanism works both for threaded and non-blocking event consumers. The formers use m0_sm_timedwait() to wait until the state machine reaches desirable state, the latter register a clink with m0_sm::sm_chan.
"Input" events cause state transitions. Typical examples of such events are: completion of a network or storage communication, timeout or a state transition in a different state machine. Such events often happen in "awkward" context: signal and interrupt handlers, timer call-backs and similar. Acquiring the group's mutex, necessary for state transition in such places is undesirable for multiple reasons:
- to avoid self-deadlock in a case where an interrupt or signal is
serviced by a thread that already holds the mutex, the latter must be
made "async-safe", which is quite expensive;
- implementation of a module that provides a call-back must take into
account the possibility of the call-back blocking waiting for a
mutex. This is also quite expensive;
- locking order dependencies arise between otherwise unrelated
components;
- all these issues are exasperated in a situation where state transition
must take additional locks, which it often does.
The solution to these problems comes from operating system kernels design, see the AST section below.
There are 2 ways to implement state machine input event processing:
- "external" state transition, where input event processing is done
outside of state machine, and m0_sm_state_set() is called to record
state change:
...
};
void event_X(
struct foo *
f)
{
}
- "chained" state transition, where event processing logic is encoded in
m0_sm_state_descr::sd_in() methods and a call to m0_sm_state_set() causes
actual event processing to happen:
{
return NEXT_STATE;
}
...
};
...
[STATE_X] = {
...
},
...
};
void event_X(
struct foo *
f)
{
}
Accounting and statistics.
This module accumulates statistics about state transitions and time spent in particular states. Statistics are reported through m0_sm_addb2_stats structure, associated with the state machine.
AST.
Asynchronous System Trap (AST) is a mechanism that allows a code running in an "awkward context" (see above) to post a call-back to be executed at the "base level" under a group mutex. UNIX kernels traditionally used a similar mechanism, where an interrupt handler does little more than setting a flag and returning. This flag is checked when the kernel is just about to return to the user space. If the flag is set, the rest of interrupt processing happens. In Linux a similar mechanism is called a "top-half" and "bottom-half" of interrupt processing. In Windows it is a DPC (http://en.wikipedia.org/wiki/Deferred_Procedure_Call) mechanism, in older DEC kernels it was called a "fork queue".
m0_sm_ast structure represents a call-back to be invoked under group mutex. An ast is "posted" to a state machine group by a call to m0_sm_ast_post(), which can be done in any context, in the sense that it doesn't take any locks. Posted asts are executed
- just after group mutex is taken;
- just before group mutex is released;
- whenever m0_sm_asts_run() is called.
Ast mechanism solves the problems with input events mentioned above at the expense of
- an increased latency: the call-back is not executed immediately;
- an additional burden of ast-related book-keeping: it is up to the ast
user to free ast structure when it is safe to do so (i.e., after the
ast completed execution).
To deal with the latency problem, a user must arrange m0_sm_asts_run() to be called during long state transitions (typically within loops).
There are a few ways to deal with the ast book-keeping problem:
- majority of asts will be embedded in some longer living data-structures
like foms and won't need separate allocation of freeing;
- some ast users might allocate asts dynamically;
- the users which have neither a long-living data-structure to embed ast
in nor can call dynamic allocator, have to pre-allocate a pool of asts
and to guarantee somehow that it is never exhausted.
If an ast is posted a m0_sm_group::s_clink clink is signalled. A user managing a state machine group might arrange a special "ast" thread (or a group of threads) to wait on this channel and to call m0_sm_asts_run() when the channel is signalled:
A special "ast" thread is not needed if there is an always running "worker" thread or pool of threads associated with the state machine group. In the latter case, the worker thread can wait on m0_sm_group::s_clink in addition to other channels it waits on (see m0_clink_attach()).
m0_sm_group_init() initialises m0_sm_group::s_clink with a NULL call-back. If a user wants to re-initialise it with a different call-back or to attach it to a clink group, it should call m0_clink_fini() followed by m0_clink_init() or m0_link_attach() before any state machine is created in the group.
◆ anonymous enum
Enumerator |
---|
M0_SM_MAX_STATES | |
Definition at line 366 of file sm.h.
◆ m0_sm_return
Enumerator |
---|
M0_SM_BREAK | Negative mumbers are used to return from state function without transitioning to next state.
|
Definition at line 735 of file sm.h.
◆ m0_sm_state_descr_flags
Flags for state classification, used in m0_sm_state_descr::sd_flags.
Enumerator |
---|
M0_SDF_INITIAL | An initial state.
State machine, must start execution in a state marked with this flag. Multiple states can be marked with this flag, for example, to share a code between similar state machines, that only differ in initial conditions.
- See also
- m0_sm_init()
|
M0_SDF_FAILURE | A state marked with this flag is a failure state. m0_sm::sm_rc is set to a non-zero value on entering this state.
In a such state, state machine is supposed to handle or report the error indicated by m0_sm::sm_rc. Typically (but not necessary), the state machine will transit into am M0_SDF_TERMINAL state immediately after a failure state.
- See also
- m0_sm_fail()
|
M0_SDF_TERMINAL | A state marked with this flag is a terminal state. No transitions out of this state are allowed (checked by m0_sm_conf_invariant()) and an attempt to wait for a state transition, while the state machine is in a terminal state, immediately returns -ESRCH.
- See also
- m0_sm_timedwait()
|
M0_SDF_FINAL | A state marked with this flag is a "final" state. State machine can be finalised iff it is in state marked as M0_SDF_FINAL or M0_SDF_TERMINAL. There can be multiple states marked as M0_SDF_FINAL. M0_SDF_FINAL differs from M0_SDF_TERMINAL in that, state machine can transition out of a final state.
|
Definition at line 439 of file sm.h.
◆ timer_state
m0_sm_timer state machine
* INIT
* |
* +-----+ | m0_sm_timer_start()
* sm_timer_top() | | |
* | V V
* +----ARMED
* | |
* m0_sm_timer_cancel() | | sm_timer_bottom()
* | |
* V V
* DONE
*
Enumerator |
---|
INIT | |
ARMED | |
DONE | |
Definition at line 508 of file sm.c.
◆ _sm_group_lock()
Definition at line 76 of file sm.c.
◆ _sm_group_unlock()
static void _sm_group_unlock |
( |
struct m0_sm_group * |
grp | ) |
|
|
static |
Definition at line 89 of file sm.c.
◆ conf_invariant()
static bool conf_invariant |
( |
const struct m0_sm_conf * |
conf | ) |
|
|
static |
Definition at line 274 of file sm.c.
◆ grp_is_locked()
static bool grp_is_locked |
( |
const struct m0_sm_group * |
grp | ) |
|
|
static |
Definition at line 102 of file sm.c.
◆ m0_sm_addb2_counter_init()
M0_INTERNAL bool m0_sm_addb2_counter_init |
( |
struct m0_sm * |
sm | ) |
|
Definition at line 891 of file sm.c.
◆ m0_sm_addb2_fini()
M0_INTERNAL void m0_sm_addb2_fini |
( |
struct m0_sm_conf * |
conf | ) |
|
Definition at line 870 of file sm.c.
◆ m0_sm_addb2_init()
M0_INTERNAL int m0_sm_addb2_init |
( |
struct m0_sm_conf * |
conf, |
|
|
uint64_t |
id, |
|
|
uint64_t |
counter |
|
) |
| |
Definition at line 846 of file sm.c.
◆ m0_sm_ast_cancel()
Cancels a posted AST.
If the AST has already been executed, nothing is done.
- Postcondition
- ast->sa_next == NULL
Definition at line 183 of file sm.c.
◆ m0_sm_ast_post()
Posts an AST to a group.
An AST must not be re-posted until its previous (already posted) execution completes.
Definition at line 135 of file sm.c.
◆ m0_sm_ast_wait()
Waits until all m0_sm_ast_wait_post()ed ASTs are executed.
- Precondition
- m0_chan_is_locked(&wait->aw_chan)
Definition at line 950 of file sm.c.
◆ m0_sm_ast_wait_complete()
Definition at line 935 of file sm.c.
◆ m0_sm_ast_wait_fini()
Definition at line 910 of file sm.c.
◆ m0_sm_ast_wait_init()
Definition at line 903 of file sm.c.
◆ m0_sm_ast_wait_loop()
Definition at line 942 of file sm.c.
◆ m0_sm_ast_wait_post()
◆ m0_sm_ast_wait_prepare()
Definition at line 917 of file sm.c.
◆ m0_sm_ast_wait_signal()
M0_INTERNAL void m0_sm_ast_wait_signal |
( |
struct m0_sm_ast_wait * |
wait | ) |
|
Signifies completion of an AST, posted with m0_sm_ast_wait_post().
- Precondition
- m0_chan_is_locked(&wait->aw_chan)
Definition at line 985 of file sm.c.
◆ m0_sm_asts_run()
M0_INTERNAL void m0_sm_asts_run |
( |
struct m0_sm_group * |
grp | ) |
|
Runs posted, but not yet executed ASTs.
- Precondition
- m0_mutex_is_locked(&grp->s_lock)
- Postcondition
- m0_mutex_is_locked(&grp->s_lock)
Definition at line 150 of file sm.c.
◆ m0_sm_conf_extend()
"Extends" base state descriptions with the given sub descriptions.
Updates sub in place to become a merged state machine descriptions array that uses base state descriptors, unless overridden by sub.
Definition at line 763 of file sm.c.
◆ m0_sm_conf_fini()
M0_INTERNAL void m0_sm_conf_fini |
( |
struct m0_sm_conf * |
conf | ) |
|
Finalises state machine configuration.
- See also
- m0_addb_rec_type_umregister()
- Precondition
- conf->scf_magic == M0_SM_CONF_MAGIC
Definition at line 376 of file sm.c.
◆ m0_sm_conf_init()
M0_INTERNAL void m0_sm_conf_init |
( |
struct m0_sm_conf * |
conf | ) |
|
Initialises state machine configuration.
Traverses transitions description array and constructs m0_sm_state_descr::sd_trans transitions map array for each state. It also makes sure (asserts) that transitions configuration in transitions description array matches with the same at states description array according to m0_sm_state_descr::sd_allowed flags.
- Precondition
- !m0_sm_conf_is_initialized(conf)
-
conf->scf_trans_nr > 0
Definition at line 340 of file sm.c.
◆ m0_sm_conf_is_initialized()
M0_INTERNAL bool m0_sm_conf_is_initialized |
( |
const struct m0_sm_conf * |
conf | ) |
|
Returns true if sm configuration was initialized already.
Definition at line 382 of file sm.c.
◆ m0_sm_conf_print()
M0_INTERNAL void m0_sm_conf_print |
( |
const struct m0_sm_conf * |
conf | ) |
|
Outputs the dot-language description of the configuration to the console.
Definition at line 993 of file sm.c.
◆ m0_sm_conf_state_name()
M0_INTERNAL const char * m0_sm_conf_state_name |
( |
const struct m0_sm_conf * |
conf, |
|
|
int |
state |
|
) |
| |
Definition at line 774 of file sm.c.
◆ m0_sm_conf_trans_extend()
M0_INTERNAL void m0_sm_conf_trans_extend |
( |
const struct m0_sm_conf * |
base, |
|
|
struct m0_sm_conf * |
sub |
|
) |
| |
Extends transition table of "base" with new transitions from "sub".
Resulting table is stored in "sub", which should be of sufficient size. Transitions in "sub" override matching transitions in "base".
sub->scf_trans[] reserves array elements for base. Empty slots in sub->scf_trans[] could be in arbitrary places.
Definition at line 726 of file sm.c.
◆ m0_sm_fail()
M0_INTERNAL void m0_sm_fail |
( |
struct m0_sm * |
mach, |
|
|
int |
fail_state, |
|
|
int32_t |
rc |
|
) |
| |
Moves a state machine into fail_state state atomically with setting rc code.
- Precondition
- rc != 0
-
m0_mutex_is_locked(&mach->sm_grp->s_lock)
-
mach->sm_rc == 0
-
mach->sm_conf->scf_state[fail_state].sd_flags & M0_SDF_FAILURE
- Postcondition
- mach->sm_rc == rc
-
mach->sm_state == fail_state
-
m0_mutex_is_locked(&mach->sm_grp->s_lock)
Definition at line 468 of file sm.c.
◆ m0_sm_fini()
M0_INTERNAL void m0_sm_fini |
( |
struct m0_sm * |
mach | ) |
|
Finalises a state machine.
- Precondition
- conf->scf_state[state].sd_flags & (M0_SDF_TERMINAL | M0_SDF_FINAL)
Definition at line 331 of file sm.c.
◆ m0_sm_group_call()
int m0_sm_group_call |
( |
struct m0_sm_group * |
group, |
|
|
int(*)(void *) |
cb, |
|
|
void * |
data |
|
) |
| |
Definition at line 801 of file sm.c.
◆ m0_sm_group_fini()
M0_INTERNAL void m0_sm_group_fini |
( |
struct m0_sm_group * |
grp | ) |
|
Definition at line 65 of file sm.c.
◆ m0_sm_group_init()
M0_INTERNAL void m0_sm_group_init |
( |
struct m0_sm_group * |
grp | ) |
|
Definition at line 53 of file sm.c.
◆ m0_sm_group_is_locked()
M0_INTERNAL bool m0_sm_group_is_locked |
( |
const struct m0_sm_group * |
grp | ) |
|
Definition at line 107 of file sm.c.
◆ m0_sm_group_lock()
M0_INTERNAL void m0_sm_group_lock |
( |
struct m0_sm_group * |
grp | ) |
|
Definition at line 83 of file sm.c.
◆ m0_sm_group_lock_rec()
M0_INTERNAL void m0_sm_group_lock_rec |
( |
struct m0_sm_group * |
grp, |
|
|
bool |
runast |
|
) |
| |
Definition at line 112 of file sm.c.
◆ m0_sm_group_unlock()
M0_INTERNAL void m0_sm_group_unlock |
( |
struct m0_sm_group * |
grp | ) |
|
Definition at line 96 of file sm.c.
◆ m0_sm_group_unlock_rec()
M0_INTERNAL void m0_sm_group_unlock_rec |
( |
struct m0_sm_group * |
grp, |
|
|
bool |
runast |
|
) |
| |
Definition at line 123 of file sm.c.
◆ m0_sm_id_get()
M0_INTERNAL uint64_t m0_sm_id_get |
( |
const struct m0_sm * |
sm | ) |
|
- Returns
- given SM identifier.
Definition at line 1021 of file sm.c.
◆ m0_sm_init()
Initialises a state machine.
- Precondition
- conf->scf_state[state].sd_flags & M0_SDF_INITIAL
Definition at line 313 of file sm.c.
◆ m0_sm_invariant()
M0_INTERNAL bool m0_sm_invariant |
( |
const struct m0_sm * |
mach | ) |
|
Definition at line 267 of file sm.c.
◆ m0_sm_move()
M0_INTERNAL void m0_sm_move |
( |
struct m0_sm * |
mach, |
|
|
int32_t |
rc, |
|
|
int |
state |
|
) |
| |
◆ m0_sm_state_name()
M0_INTERNAL const char * m0_sm_state_name |
( |
const struct m0_sm * |
mach, |
|
|
int |
state |
|
) |
| |
◆ m0_sm_state_set()
void m0_sm_state_set |
( |
struct m0_sm * |
mach, |
|
|
int |
state |
|
) |
| |
Transits a state machine into the indicated state.
Calls ex- and in- methods of the corresponding states (even if the state doesn't change after all).
The (mach->sm_state == state) post-condition cannot be asserted, because of chained state transitions.
Updates m0_sm_state_stats::smss_times statistics for the current state and sets the m0_sm::sm_state_epoch for the next state.
- Precondition
- m0_mutex_is_locked(&mach->sm_grp->s_lock)
- Postcondition
- m0_mutex_is_locked(&mach->sm_grp->s_lock)
Definition at line 478 of file sm.c.
◆ m0_sm_timedwait()
M0_INTERNAL int m0_sm_timedwait |
( |
struct m0_sm * |
mach, |
|
|
uint64_t |
states, |
|
|
m0_time_t |
deadline |
|
) |
| |
Waits until a given state machine enters any of states enumerated by a given bit-mask.
- Return values
-
0 | - one of the states reached |
-ESRCH | - terminal state reached, see m0_sm_state_descr_flags::M0_SDF_TERMINAL |
-ETIMEDOUT | - deadline passed |
In case where multiple wait termination conditions hold simultaneously (e.g., includes a terminal state), the result is implementation dependent.
- Note
- this interface assumes that states are numbered by numbers less than 64.
Definition at line 387 of file sm.c.
◆ m0_sm_timeout_arm()
Arms a timer to move a machine into a given state after a given timeout.
If a state transition happens before the timeout expires, the timeout is cancelled, unless the transition is to a state from "bitmask" parameter.
It is possible to arm multiple timeouts against the same state machine.
The m0_sm_timeout instance, supplied to this call can be freed after timeout expires or is cancelled.
- Parameters
-
timeout | absolute time at which the state transition will take place |
state | the state to which the state machine will transition after the timeout. |
bitmask | a mask of state machine states, transitions which won't cancel the timeout. |
- Precondition
- m0_mutex_is_locked(&mach->sm_grp->s_lock)
-
sm_state(mach)->sd_allowed & M0_BITS(state)
-
m0_forall(i, mach->sm_conf->scf_nr_states, ergo(M0_BITS(i) & bitmask, state_get(mach, i)->sd_allowed & M0_BITS(state)))
- Postcondition
- m0_mutex_is_locked(&mach->sm_grp->s_lock)
Definition at line 674 of file sm.c.
◆ m0_sm_timeout_fini()
Finaliser that must be called before can be freed.
Definition at line 705 of file sm.c.
◆ m0_sm_timeout_init()
Initialises a timer structure with a given timeout.
Definition at line 667 of file sm.c.
◆ m0_sm_timeout_is_armed()
M0_INTERNAL bool m0_sm_timeout_is_armed |
( |
const struct m0_sm_timeout * |
to | ) |
|
Returns true iff timer associated with the timeout is running.
Definition at line 713 of file sm.c.
◆ m0_sm_timer_cancel()
M0_INTERNAL void m0_sm_timer_cancel |
( |
struct m0_sm_timer * |
timer | ) |
|
Definition at line 610 of file sm.c.
◆ m0_sm_timer_fini()
M0_INTERNAL void m0_sm_timer_fini |
( |
struct m0_sm_timer * |
timer | ) |
|
Definition at line 566 of file sm.c.
◆ m0_sm_timer_init()
M0_INTERNAL void m0_sm_timer_init |
( |
struct m0_sm_timer * |
timer | ) |
|
Definition at line 559 of file sm.c.
◆ m0_sm_timer_is_armed()
M0_INTERNAL bool m0_sm_timer_is_armed |
( |
const struct m0_sm_timer * |
timer | ) |
|
Definition at line 628 of file sm.c.
◆ m0_sm_timer_start()
Starts the timer.
When the specified (absolute) deadline expires, an AST is posted in the specified state machine group. When this AST is executed, it calls the user-supplied call-back.
If the deadline is already in the past by the time this is called, the AST is posted as soon as possible.
Definition at line 577 of file sm.c.
◆ sm_addb2_counter_init_add()
static void sm_addb2_counter_init_add |
( |
struct m0_sm * |
sm | ) |
|
|
static |
Definition at line 880 of file sm.c.
◆ sm_addb2_ctor()
Definition at line 817 of file sm.c.
◆ sm_addb2_dtor()
Definition at line 837 of file sm.c.
◆ sm_call_ast()
Definition at line 793 of file sm.c.
◆ sm_invariant0()
M0_INTERNAL bool sm_invariant0 |
( |
const struct m0_sm * |
mach | ) |
|
Weaker form of state machine invariant, that doesn't check that the group lock is held. Used in m0_sm_init() and m0_sm_fini().
Definition at line 260 of file sm.c.
◆ sm_is_locked()
static bool sm_is_locked |
( |
const struct m0_sm * |
mach | ) |
|
|
static |
Definition at line 232 of file sm.c.
◆ sm_lock()
static void sm_lock |
( |
struct m0_sm * |
mach | ) |
|
|
static |
Definition at line 222 of file sm.c.
◆ sm_state()
Definition at line 251 of file sm.c.
◆ sm_timeout_cancel()
static bool sm_timeout_cancel |
( |
struct m0_clink * |
link | ) |
|
|
static |
Cancels a timeout, if necessary.
This is called if a state transition happened before the timeout expired.
- See also
- m0_sm_timeout_arm().
Definition at line 655 of file sm.c.
◆ sm_timer_bottom()
◆ sm_timer_top()
static unsigned long sm_timer_top |
( |
unsigned long |
data | ) |
|
|
static |
◆ sm_unlock()
static void sm_unlock |
( |
struct m0_sm * |
mach | ) |
|
|
static |
Definition at line 227 of file sm.c.
◆ state_get()
Definition at line 244 of file sm.c.
◆ state_is_valid()
static bool state_is_valid |
( |
const struct m0_sm_conf * |
conf, |
|
|
uint32_t |
state |
|
) |
| |
|
static |
Definition at line 237 of file sm.c.
◆ state_set()
static void state_set |
( |
struct m0_sm * |
mach, |
|
|
int |
state, |
|
|
int32_t |
rc |
|
) |
| |
|
static |
Definition at line 416 of file sm.c.
◆ timeout_ast()
◆ timer_done()
Definition at line 535 of file sm.c.
◆ trans_exists()
static bool trans_exists |
( |
const struct m0_sm_conf * |
conf, |
|
|
uint32_t |
src, |
|
|
uint32_t |
tgt |
|
) |
| |
|
static |
Definition at line 718 of file sm.c.
◆ eoq
An end-of-queue marker.
All fork queues end with this pointer. This marker is used instead of NULL to make (ast->sa_next == NULL) equivalent to "the ast is not in a fork queue".
Compare with lib/queue.c:EOQ.
Definition at line 51 of file sm.c.
◆ m0_sm__conf_init
Definition at line 338 of file sm.c.