Motr  M0
sm.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2011-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include "ut/ut.h"
24 #include "lib/ub.h"
25 #include "lib/time.h"
26 #include "lib/errno.h"
27 #include "lib/arith.h" /* m0_rnd */
28 #include "lib/misc.h" /* M0_IN */
29 #include "lib/thread.h"
30 
31 #include "sm/sm.h"
32 
33 static struct m0_sm_group G;
34 static struct m0_sm m;
35 static struct m0_sm_ast ast;
36 static bool more;
37 static struct m0_thread ath;
38 
40  C_NR };
41 
42 static int heads;
43 static int tails;
44 
45 
46 static void ast_thread(int __d)
47 {
48  while (more) {
51  m0_sm_asts_run(&G);
53  }
54 }
55 
56 static int init(void) {
58  M0_SET0(&m);
59  M0_SET0(&ast);
60  more = true;
61  M0_SET0(&ath);
62  heads = 0;
63  tails = 0;
64 
65  return 0;
66 }
67 
68 static int fini(void) {
69  more = false;
73  return 0;
74 }
75 
88 static void transition(void)
89 {
90  enum { S_INITIAL, S_TERMINAL, S_FAILURE, S_NR };
91  struct m0_sm_state_descr states[S_NR] = {
92  [S_INITIAL] = {
94  .sd_name = "initial",
95  .sd_in = NULL,
96  .sd_ex = NULL,
97  .sd_invariant = NULL,
98  .sd_allowed = M0_BITS(S_TERMINAL, S_FAILURE)
99  },
100  [S_FAILURE] = {
101  .sd_flags = M0_SDF_FAILURE,
102  .sd_name = "initial",
103  .sd_in = NULL,
104  .sd_ex = NULL,
105  .sd_invariant = NULL,
106  .sd_allowed = M0_BITS(S_TERMINAL)
107  },
108  [S_TERMINAL] = {
109  .sd_flags = M0_SDF_TERMINAL,
110  .sd_name = "terminal",
111  .sd_in = NULL,
112  .sd_ex = NULL,
113  .sd_invariant = NULL,
114  .sd_allowed = 0
115  }
116  };
117  struct m0_sm_trans_descr trans[] = {
118  { "Step", S_INITIAL, S_TERMINAL },
119  { "Fail", S_INITIAL, S_FAILURE },
120  { "Fini", S_FAILURE, S_TERMINAL },
121  };
122  struct m0_sm_conf conf = {
123  .scf_name = "test drive: transition",
124  .scf_nr_states = S_NR,
125  .scf_state = states,
126  .scf_trans_nr = ARRAY_SIZE(trans),
127  .scf_trans = trans
128  };
129 
131  M0_UT_ASSERT(states[S_INITIAL].sd_trans[S_INITIAL] == ~0);
132  M0_UT_ASSERT(states[S_INITIAL].sd_trans[S_TERMINAL] == 0);
133  M0_UT_ASSERT(states[S_INITIAL].sd_trans[S_FAILURE] == 1);
134  M0_UT_ASSERT(states[S_FAILURE].sd_trans[S_INITIAL] == ~0);
135  M0_UT_ASSERT(states[S_FAILURE].sd_trans[S_FAILURE] == ~0);
136  M0_UT_ASSERT(states[S_FAILURE].sd_trans[S_TERMINAL] == 2);
137  M0_UT_ASSERT(states[S_TERMINAL].sd_trans[S_INITIAL] == ~0);
138  M0_UT_ASSERT(states[S_TERMINAL].sd_trans[S_FAILURE] == ~0);
139  M0_UT_ASSERT(states[S_TERMINAL].sd_trans[S_TERMINAL] == ~0);
140 
142  M0_SET0(&m);
143  m0_sm_init(&m, &conf, S_INITIAL, &G);
147  m0_sm_fini(&m);
148 
149  M0_SET0(&m);
150  m0_sm_init(&m, &conf, S_INITIAL, &G);
152  m0_sm_move(&m, 0, S_TERMINAL);
154  m0_sm_fini(&m);
155 
156  M0_SET0(&m);
157  m0_sm_init(&m, &conf, S_INITIAL, &G);
159  m0_sm_move(&m, -EINVAL, S_FAILURE);
161  M0_UT_ASSERT(m.sm_rc == -EINVAL);
163  m0_sm_fini(&m);
164 
166 }
167 
168 static bool x;
169 
170 static void ast_cb(struct m0_sm_group *g, struct m0_sm_ast *a)
171 {
172  M0_UT_ASSERT(g == &G);
173  M0_UT_ASSERT(a == &ast);
174  M0_UT_ASSERT(a->sa_datum == &ast_cb);
175  x = true;
176 }
177 
181 static void ast_test(void)
182 {
183 
184  x = false;
185  ast.sa_cb = &ast_cb;
186  ast.sa_datum = &ast_cb;
187  m0_sm_ast_post(&G, &ast);
188  M0_UT_ASSERT(!x);
190  M0_UT_ASSERT(x);
192 
193  /* test ast cancellation. */
194  /* cancel before execution. */
195  x = false;
197  m0_sm_ast_post(&G, &ast);
198  M0_UT_ASSERT(!x);
200  m0_sm_ast_cancel(&G, &ast);
203  M0_UT_ASSERT(!x);
204 
205  /* cancel after execution. */
206  x = false;
207  m0_sm_ast_post(&G, &ast);
208  M0_UT_ASSERT(!x);
211  M0_UT_ASSERT(x);
213  m0_sm_ast_cancel(&G, &ast);
216  x = false;
218  M0_UT_ASSERT(!x);
220 }
221 
236 
238  [S_TMO_INITIAL] = {
240  .sd_name = "initial",
241  .sd_in = NULL,
242  .sd_ex = NULL,
243  .sd_invariant = NULL,
244  .sd_allowed = M0_BITS(S_TMO_0)
245  },
246  [S_TMO_0] = {
247  .sd_flags = 0,
248  .sd_name = "0",
249  .sd_in = NULL,
250  .sd_ex = NULL,
251  .sd_invariant = NULL,
252  .sd_allowed = M0_BITS(S_TMO_1, S_TMO_2)
253  },
254  [S_TMO_1] = {
255  .sd_flags = 0,
256  .sd_name = "0",
257  .sd_in = NULL,
258  .sd_ex = NULL,
259  .sd_invariant = NULL,
260  .sd_allowed = M0_BITS(S_TMO_2, S_TMO_TERMINAL)
261  },
262  [S_TMO_2] = {
263  .sd_flags = 0,
264  .sd_name = "0",
265  .sd_in = NULL,
266  .sd_ex = NULL,
267  .sd_invariant = NULL,
268  .sd_allowed = M0_BITS(S_TMO_0, S_TMO_TERMINAL)
269  },
270  [S_TMO_TERMINAL] = {
271  .sd_flags = M0_SDF_TERMINAL,
272  .sd_name = "terminal",
273  .sd_in = NULL,
274  .sd_ex = NULL,
275  .sd_invariant = NULL,
276  .sd_allowed = 0
277  }
278 };
279 
280 static const struct m0_sm_conf tmo_sm_conf = {
281  .scf_name = "test drive: timeout",
282  .scf_nr_states = S_TMO_NR,
283  .scf_state = tmo_states
284 };
285 
286 static void timeout(void)
287 {
288  struct m0_sm_timeout t0;
289  struct m0_sm_timeout t1;
290  const long delta = M0_TIME_ONE_SECOND/100;
291  int result;
292 
293  result = M0_THREAD_INIT(&ath, int, NULL, &ast_thread, 0, "ast_thread");
294  M0_UT_ASSERT(result == 0);
295 
297  M0_SET0(&m);
299 
300  /* check that timeout initialisation and finalisation work. */
303 
305 
306  /* check that timeout works */
307  result = m0_sm_timeout_arm(&m, &t0, m0_time_from_now(0, delta),
308  S_TMO_0, 0);
309  M0_UT_ASSERT(result == 0);
310 
312  M0_UT_ASSERT(result == 0);
314 
317 
318  /* check that state transition cancels the timeout */
319  result = m0_sm_timeout_arm(&m, &t1, m0_time_from_now(0, delta),
320  S_TMO_1, 0);
321  M0_UT_ASSERT(result == 0);
322 
325 
327  2 * delta));
328  M0_UT_ASSERT(result == -ETIMEDOUT);
330 
333 
334  /* check that timeout with a bitmask is not cancelled by a state
335  transition */
337  result = m0_sm_timeout_arm(&m, &t1, m0_time_from_now(0, delta), S_TMO_2,
338  M0_BITS(S_TMO_1));
339  M0_UT_ASSERT(result == 0);
340 
343 
345  M0_UT_ASSERT(result == 0);
347 
349 
352 
353  m0_sm_fini(&m);
355 }
356 
357 struct story {
358  struct m0_sm cain;
359  struct m0_sm abel;
360 };
361 
363 
364 static int genesis_4_8(struct m0_sm *mach)
365 {
366  struct story *s;
367 
368  s = container_of(mach, struct story, cain);
369  m0_sm_fail(&s->abel, S_TERMINAL, -EINTR);
370  return M0_SM_BREAK;
371 }
372 
386 static void group(void)
387 {
388  struct m0_sm_state_descr states[S_NR] = {
389  [S_INITIAL] = {
391  .sd_name = "initial",
392  .sd_in = NULL,
393  .sd_ex = NULL,
394  .sd_invariant = NULL,
395  .sd_allowed = M0_BITS(S_ITERATE, S_FRATRICIDE)
396  },
397  [S_ITERATE] = {
398  .sd_flags = 0,
399  .sd_name = "loop here",
400  .sd_in = NULL,
401  .sd_ex = NULL,
402  .sd_invariant = NULL,
403  .sd_allowed = M0_BITS(S_ITERATE, S_TERMINAL)
404  },
405  [S_FRATRICIDE] = {
406  .sd_flags = 0,
407  .sd_name = "Let's go out to the field",
408  .sd_in = &genesis_4_8,
409  .sd_ex = NULL,
410  .sd_invariant = NULL,
411  .sd_allowed = M0_BITS(S_TERMINAL)
412  },
413  [S_TERMINAL] = {
414  .sd_flags = M0_SDF_TERMINAL|M0_SDF_FAILURE,
415  .sd_name = "terminal",
416  .sd_in = NULL,
417  .sd_ex = NULL,
418  .sd_invariant = NULL,
419  .sd_allowed = 0
420  }
421  };
422  const struct m0_sm_conf conf = {
423  .scf_name = "test drive: group",
424  .scf_nr_states = S_NR,
425  .scf_state = states
426  };
427 
428  struct story s = {};
429  struct m0_sm_timeout to;
430  int result;
431 
433  m0_sm_init(&s.cain, &conf, S_INITIAL, &G);
434  m0_sm_init(&s.abel, &conf, S_INITIAL, &G);
435 
436  /* check that timeout works */
437  m0_sm_timeout_init(&to);
438  result = m0_sm_timeout_arm(&s.cain, &to,
440  S_FRATRICIDE, 0);
441  M0_UT_ASSERT(result == 0);
442 
443  while (s.abel.sm_rc == 0) {
444  /* live, while you can */
445  m0_sm_state_set(&s.abel, S_ITERATE);
446  /* give providence a chance to run */
447  m0_sm_asts_run(&G);
448  }
449  M0_UT_ASSERT(s.abel.sm_state == S_TERMINAL);
450  M0_UT_ASSERT(s.cain.sm_state == S_FRATRICIDE);
451 
452  m0_sm_fail(&s.cain, S_TERMINAL, -1);
453 
454  m0_sm_timeout_fini(&to);
455 
456  m0_sm_fini(&s.abel);
457  m0_sm_fini(&s.cain);
459 }
460 
461 static int flip(struct m0_sm *mach)
462 {
463  uint64_t cookie = ~heads + 11 * tails + 42;
464 
465  return m0_rnd(10, &cookie) >= 5 ? C_HEAD : C_TAIL;
466 }
467 
468 static int head(struct m0_sm *mach)
469 {
470  ++heads;
471  return C_DONE;
472 }
473 
474 static int tail(struct m0_sm *mach)
475 {
476  ++tails;
477  return C_DONE;
478 }
479 
480 static int over(struct m0_sm *mach)
481 {
482  if (tails > heads) {
483  return C_WIN;
484  } else if (tails == heads) {
485  return C_TIE;
486  } else {
487  /* transit to a failure state */
488  mach->sm_rc = heads - tails;
489  return C_LOSE;
490  }
491 }
492 
512 static struct m0_sm_state_descr states[C_NR] = {
513  [C_INIT] = {
515  .sd_name = "initial",
516  .sd_in = NULL,
517  .sd_ex = NULL,
518  .sd_invariant = NULL,
519  .sd_allowed = M0_BITS(C_FLIP)
520  },
521  [C_FLIP] = {
522  .sd_flags = 0,
523  .sd_name = "flip a coin",
524  .sd_in = flip,
525  .sd_ex = NULL,
526  .sd_invariant = NULL,
527  .sd_allowed = M0_BITS(C_HEAD, C_TAIL)
528  },
529  [C_HEAD] = {
530  .sd_flags = 0,
531  .sd_name = "Head, I win!",
532  .sd_in = head,
533  .sd_ex = NULL,
534  .sd_invariant = NULL,
535  .sd_allowed = M0_BITS(C_DONE)
536  },
537  [C_TAIL] = {
538  .sd_flags = 0,
539  .sd_name = "Tail, you lose!",
540  .sd_in = tail,
541  .sd_ex = NULL,
542  .sd_invariant = NULL,
543  .sd_allowed = M0_BITS(C_DONE)
544  },
545  [C_DONE] = {
546  .sd_flags = 0,
547  .sd_name = "round done",
548  .sd_in = NULL,
549  .sd_ex = NULL,
550  .sd_invariant = NULL,
551  .sd_allowed = M0_BITS(C_OVER, C_FLIP)
552  },
553  [C_OVER] = {
554  .sd_flags = 0,
555  .sd_name = "game over",
556  .sd_in = over,
557  .sd_ex = NULL,
558  .sd_invariant = NULL,
559  .sd_allowed = M0_BITS(C_WIN, C_LOSE, C_TIE)
560  },
561  [C_WIN] = {
562  .sd_flags = M0_SDF_TERMINAL,
563  .sd_name = "tails win",
564  .sd_in = NULL,
565  .sd_ex = NULL,
566  .sd_invariant = NULL,
567  .sd_allowed = 0
568  },
569  [C_LOSE] = {
570  .sd_flags = M0_SDF_TERMINAL|M0_SDF_FAILURE,
571  .sd_name = "tails lose",
572  .sd_in = NULL,
573  .sd_ex = NULL,
574  .sd_invariant = NULL,
575  .sd_allowed = 0
576  },
577  [C_TIE] = {
578  .sd_flags = M0_SDF_TERMINAL,
579  .sd_name = "tie",
580  .sd_in = NULL,
581  .sd_ex = NULL,
582  .sd_invariant = NULL,
583  .sd_allowed = 0
584  },
585 };
586 
587 enum { NR_RUNS = 20 };
588 
589 static const struct m0_sm_conf conf = {
590  .scf_name = "test drive: chain",
591  .scf_nr_states = C_NR,
592  .scf_state = states
593 };
594 
595 static void chain(void)
596 {
597  int i;
598 
600  M0_SET0(&m);
601  m0_sm_init(&m, &conf, C_INIT, &G);
603 
604  for (i = 0; i < NR_RUNS; ++i) {
607  }
610  M0_UT_ASSERT(M0_IN(m.sm_state, (C_WIN, C_LOSE, C_TIE)));
611 
612  m0_sm_fini(&m);
614 }
615 
616 static struct m0_sm_ast_wait wait;
617 static struct m0_mutex wait_guard;
618 
619 static void ast_wait_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
620 {
621  x = true;
625 }
626 
627 static void ast_wait(void)
628 {
631  x = false;
632  ast.sa_cb = &ast_wait_cb;
636  M0_UT_ASSERT(x);
637 
641 }
642 
643 struct m0_ut_suite sm_ut = {
644  .ts_name = "sm-ut",
645  .ts_init = init,
646  .ts_fini = fini,
647  .ts_tests = {
648  { "transition", transition },
649  { "ast", ast_test },
650  { "timeout", timeout },
651  { "group", group },
652  { "chain", chain },
653  { "wait", ast_wait },
654  { NULL, NULL }
655  }
656 };
657 M0_EXPORTED(sm_ut);
658 
659 /*
660  * Local variables:
661  * c-indentation-style: "K&R"
662  * c-basic-offset: 8
663  * tab-width: 8
664  * fill-column: 80
665  * scroll-step: 1
666  * End:
667  */
Definition: sm.c:235
static void transition(void)
Definition: sm.c:88
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
Definition: sm.c:39
Definition: sm.c:39
M0_INTERNAL void m0_sm_conf_init(struct m0_sm_conf *conf)
Definition: sm.c:340
M0_INTERNAL void m0_sm_fail(struct m0_sm *mach, int fail_state, int32_t rc)
Definition: sm.c:468
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
#define NULL
Definition: misc.h:38
static struct m0_mutex wait_guard
Definition: sm.c:617
static bool more
Definition: sm.c:36
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
void(* sa_cb)(struct m0_sm_group *grp, struct m0_sm_ast *)
Definition: sm.h:506
static bool x
Definition: sm.c:168
Definition: sm.h:350
Definition: sm.c:39
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
Definition: sm.c:39
static struct m0_sm_group * grp
Definition: bytecount.c:38
M0_INTERNAL void m0_sm_timeout_init(struct m0_sm_timeout *to)
Definition: sm.c:667
static void timeout(void)
Definition: sm.c:286
static int over(struct m0_sm *mach)
Definition: sm.c:480
M0_INTERNAL void m0_sm_ast_wait(struct m0_sm_ast_wait *wait)
Definition: sm.c:950
M0_INTERNAL void m0_sm_ast_post(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:135
Definition: sm.c:39
static struct m0_sm_ast ast
Definition: sm.c:35
struct m0_clink s_clink
Definition: sm.h:516
static int flip(struct m0_sm *mach)
Definition: sm.c:461
M0_INTERNAL void m0_sm_ast_wait_init(struct m0_sm_ast_wait *wait, struct m0_mutex *ch_guard)
Definition: sm.c:903
Definition: conf.py:1
static struct m0_addb2_mach * mach
Definition: storage.c:42
#define M0_BITS(...)
Definition: misc.h:236
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
Definition: sm.h:504
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
Definition: ut.h:77
M0_INTERNAL void m0_sm_group_fini(struct m0_sm_group *grp)
Definition: sm.c:65
M0_INTERNAL int m0_sm_timedwait(struct m0_sm *mach, uint64_t states, m0_time_t deadline)
Definition: sm.c:387
static int head(struct m0_sm *mach)
Definition: sm.c:468
static struct m0_sm_state_descr tmo_states[S_TMO_NR]
Definition: sm.c:237
Definition: sm.c:362
M0_INTERNAL void m0_sm_group_unlock(struct m0_sm_group *grp)
Definition: sm.c:96
Definition: sm.c:357
int i
Definition: dir.c:1033
static void ast_thread(int __d)
Definition: sm.c:46
static void ast_wait_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:619
void * sa_datum
Definition: sm.h:508
M0_INTERNAL uint64_t m0_rnd(uint64_t max, uint64_t *seed)
Definition: misc.c:115
static void ast_cb(struct m0_sm_group *g, struct m0_sm_ast *a)
Definition: sm.c:170
static void ast_test(void)
Definition: sm.c:181
static struct m0_thread ath
Definition: sm.c:37
struct m0_sm cain
Definition: sm.c:358
static struct m0_sm m
Definition: sm.c:34
const char * scf_name
Definition: sm.h:352
Definition: sm.c:587
M0_INTERNAL void m0_sm_group_init(struct m0_sm_group *grp)
Definition: sm.c:53
void m0_sm_state_set(struct m0_sm *mach, int state)
Definition: sm.c:478
static struct m0_sm_ast_wait wait
Definition: sm.c:616
Definition: sm.c:40
M0_INTERNAL void m0_clink_signal(struct m0_clink *clink)
Definition: chan.c:326
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
static int init(void)
Definition: sm.c:56
int32_t sm_rc
Definition: sm.h:336
static void group(void)
Definition: sm.c:386
static void t0(int self)
Definition: chan.c:39
struct m0_sm_ast * sa_next
Definition: sm.h:509
Definition: sm.c:362
Definition: sm.c:235
static void ast_wait(void)
Definition: sm.c:627
uint32_t sd_flags
Definition: sm.h:378
struct m0_ut_suite sm_ut
Definition: sm.c:643
const char * ts_name
Definition: ut.h:99
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)
Definition: sm.c:674
static int genesis_4_8(struct m0_sm *mach)
Definition: sm.c:364
M0_INTERNAL void m0_sm_ast_wait_post(struct m0_sm_ast_wait *wait, struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:961
M0_INTERNAL void m0_sm_timeout_fini(struct m0_sm_timeout *to)
Definition: sm.c:705
struct m0_sm abel
Definition: sm.c:359
Definition: sm.c:362
M0_INTERNAL void m0_sm_init(struct m0_sm *mach, const struct m0_sm_conf *conf, uint32_t state, struct m0_sm_group *grp)
Definition: sm.c:313
Definition: sm.c:39
static struct m0_sm_trans_descr trans[]
Definition: stats_fom.c:47
Definition: sm.c:235
Definition: sm.c:235
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
Definition: sm.h:301
M0_INTERNAL void m0_sm_ast_wait_fini(struct m0_sm_ast_wait *wait)
Definition: sm.c:910
M0_INTERNAL void m0_sm_move(struct m0_sm *mach, int32_t rc, int state)
Definition: sm.c:485
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
Definition: sm.c:362
static struct m0_sm_group G
Definition: sm.c:33
M0_INTERNAL void m0_sm_group_lock(struct m0_sm_group *grp)
Definition: sm.c:83
Definition: sm.c:39
static int tails
Definition: sm.c:43
static void t1(int n)
Definition: mutex.c:48
M0_INTERNAL void m0_sm_ast_cancel(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:183
static void chain(void)
Definition: sm.c:595
static int heads
Definition: sm.c:42
M0_INTERNAL void m0_sm_asts_run(struct m0_sm_group *grp)
Definition: sm.c:150
static int fini(void)
Definition: sm.c:68
static struct gen g[MAX_GEN]
Definition: beck.c:521
Definition: mutex.h:47
static struct m0_addb2_source * s
Definition: consumer.c:39
Definition: sm.c:39
uint32_t sm_state
Definition: sm.h:307
M0_INTERNAL void m0_sm_ast_wait_signal(struct m0_sm_ast_wait *wait)
Definition: sm.c:985
#define ARRAY_SIZE(a)
Definition: misc.h:45
static struct m0_sm_state_descr states[C_NR]
Definition: sm.c:512
#define M0_UT_ASSERT(a)
Definition: ut.h:46
Definition: sm.c:39
static int tail(struct m0_sm *mach)
Definition: sm.c:474
static const struct m0_sm_conf tmo_sm_conf
Definition: sm.c:280
M0_INTERNAL void m0_sm_fini(struct m0_sm *mach)
Definition: sm.c:331