Motr  M0
coroutine2.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2021 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 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_UT
23 #include "lib/trace.h"
24 #include "lib/coroutine.h"
25 #include "lib/string.h"
26 #include "ut/ut.h"
27 #include "be/op.h"
28 #include "reqh/reqh.h" /* m0_reqh_fop_handle */
29 #include "fop/fom.h" /* m0_fom_phase_set */
30 #include "fop/fom_generic.h" /* M0_FOPH_FINISH */
31 #include "fop/fom_simple.h"
32 #include "fop/fom_long_lock.h"
33 
34 
35 extern struct m0_reqh *m0_ut__reqh_init(void);
36 extern void m0_ut__reqh_fini(void);
37 
42 };
43 
45 #define _S(name, flags, allowed) \
46  [name] = { \
47  .sd_flags = flags, \
48  .sd_name = #name, \
49  .sd_allowed = allowed \
50  }
51 
54 #undef _S
55 };
56 
57 static struct m0_sm_conf coroutine2_conf = {
58  .scf_name = "coroutine2_states",
59  .scf_nr_states = ARRAY_SIZE(coroutine2_states),
60  .scf_state = coroutine2_states,
61 };
62 
63 struct test_tree {
64  int insert;
65  int delete;
66 };
67 
68 static void crud(struct m0_fom *fom, struct test_tree *tree, int k, int v);
69 static void insert(struct m0_fom *fom, struct test_tree *tree, int k, int v);
70 static void delete(struct m0_fom *fom, struct test_tree *tree, int k);
71 
72 static struct m0_semaphore ready;
73 static struct m0_semaphore insert1;
74 static struct m0_semaphore insert2;
75 static struct m0_semaphore delete1;
76 static struct m0_semaphore delete2;
77 
78 static struct m0_fom_simple fom_simple;
79 static struct m0_co_context fom_context = {};
80 static struct m0_co_op fom_op = {};
81 
82 /* Simple FOM data */
83 static struct test_tree fom_tree = {};
84 static struct m0_long_lock fom_lock = {};
85 
86 /* handy getters, can be a part of coroutine lib */
87 #define F M0_CO_FRAME_DATA
88 #define LR M0_FOM_LONG_LOCK_RETURN
89 
90 static struct m0_co_context *CO(struct m0_fom *fom)
91 {
92  /* Take the context from the specific_fom structure in real scenarios */
93  return &fom_context;
94 }
95 
96 static struct m0_co_op *OP(struct m0_fom *fom)
97 {
98  /* Take the op from the specific_fom structure in real scenarios */
99  return &fom_op;
100 }
101 
102 static void wait_for_coroutine_fom(void)
103 {
106 
109 
112 
115 
117 }
118 
119 static int coroutine_fom_tick(struct m0_fom *fom, int *x, int *__unused)
120 {
121  int key = 1;
122  int val = 2;
123  int rc;
124 
126 
127  M0_CO_START(CO(fom));
128  crud(fom, &fom_tree, key, val);
129  rc = M0_CO_END(CO(fom));
130 
131  if (rc == -EAGAIN) /* m0_co_op case */
133  else if (M0_IN(rc, (M0_FSO_WAIT, M0_FSO_AGAIN))) /* long_lock case */
134  return rc;
135 
137  return -1;
138 }
139 
140 static void crud(struct m0_fom *fom, struct test_tree *tree, int k, int v)
141 {
143  struct m0_long_lock_link llink;
144  );
145 
146  M0_LOG(M0_DEBUG, "tree=%p tree.delete=%d, tree.insert=%d k=%d",
147  tree, tree->delete, tree->insert, k);
148 
149  /*
150  * This part pretends to take a long lock. In the reality it takes it
151  * only once, no concurrency expected. Use the following code as an
152  * example to implement your own.
153  */
154  m0_long_lock_link_init(&F(llink), fom, NULL);
157  &F(llink),
158  m0_fom_phase(fom))));
159 
160  m0_long_write_unlock(&fom_lock, &F(llink));
161  m0_long_lock_link_fini(&F(llink));
162 
163  /*
164  * Updates pretended tree object asuming two blocking points to simulate
165  * paged inside insert() and delete().
166  */
167  M0_CO_FUN(CO(fom), insert(fom, tree, k, v));
168  M0_CO_FUN(CO(fom), delete(fom, tree, k));
169  M0_UT_ASSERT(tree->delete + tree->insert == 22);
170 }
171 
172 static void insert(struct m0_fom *fom, struct test_tree *tree, int k, int v)
173 {
174  M0_CO_REENTER(CO(fom));
175 
176  M0_LOG(M0_DEBUG, "tree=%p tree.delete=%d, tree.insert=%d k=%d v=%d",
177  tree, tree->delete, tree->insert, k, v);
178 
179  M0_LOG(M0_DEBUG, "yield");
180  tree->insert++;
183  M0_CO_YIELD(CO(fom));
184 
185  M0_LOG(M0_DEBUG, "yield");
186  tree->insert++;
189  M0_CO_YIELD(CO(fom));
190 }
191 
192 static void delete(struct m0_fom *fom, struct test_tree *tree, int k)
193 {
194  M0_CO_REENTER(CO(fom));
195 
196  M0_LOG(M0_DEBUG, "tree=%p tree.delete=%d, tree.insert=%d",
197  tree, tree->delete, tree->insert);
198 
199  M0_LOG(M0_DEBUG, "yield");
200  tree->delete += 10;
203  M0_CO_YIELD(CO(fom));
204 
205  M0_LOG(M0_DEBUG, "yield");
206  tree->delete += 10;
209  M0_CO_YIELD(CO(fom));
210 }
211 
212 static void test_run(void)
213 {
214  struct m0_reqh *reqh = m0_ut__reqh_init();
215  (void) reqh;
216 
222 }
223 
225 {
226  int rc;
227 
228  M0_SET0(&fom_tree);
235 
238  M0_UT_ASSERT(rc == 0);
239 
240  test_run();
241 
244 
251 }
252 
253 #undef F
254 #undef LR
255 
256 /*
257  * Local variables:
258  * c-indentation-style: "K&R"
259  * c-basic-offset: 8
260  * tab-width: 8
261  * fill-column: 80
262  * scroll-step: 1
263  * End:
264  */
265 /*
266  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
267  */
static struct m0_semaphore insert2
Definition: coroutine2.c:74
M0_INTERNAL void m0_long_lock_fini(struct m0_long_lock *lock)
int delete
Definition: coroutine2.c:65
struct m0_reqh * m0_ut__reqh_init(void)
Definition: locality.c:67
M0_INTERNAL void m0_long_lock_link_init(struct m0_long_lock_link *link, struct m0_fom *fom, struct m0_long_lock_addb2 *addb2)
Definition: fom_long_lock.c:66
static struct m0_co_context * CO(struct m0_fom *fom)
Definition: coroutine2.c:90
static struct m0_semaphore ready
Definition: coroutine2.c:72
static struct m0_semaphore delete2
Definition: coroutine2.c:76
M0_INTERNAL void m0_co_context_fini(struct m0_co_context *context)
Definition: coroutine.c:136
#define NULL
Definition: misc.h:38
static struct m0_semaphore delete1
Definition: coroutine2.c:75
Definition: idx_mock.c:52
void m0_test_coroutine2(void)
Definition: coroutine2.c:224
static bool x
Definition: sm.c:168
Definition: sm.h:350
#define M0_LOG(level,...)
Definition: trace.h:167
M0_INTERNAL void m0_co_op_reset(struct m0_co_op *op)
Definition: coroutine.c:203
static struct m0_semaphore insert1
Definition: coroutine2.c:73
#define LR
Definition: coroutine2.c:88
#define F
Definition: coroutine2.c:87
static void insert(struct m0_fom *fom, struct test_tree *tree, int k, int v)
Definition: coroutine2.c:172
M0_INTERNAL void m0_co_op_init(struct m0_co_op *op)
Definition: coroutine.c:179
#define M0_BITS(...)
Definition: misc.h:236
M0_INTERNAL void m0_long_write_unlock(struct m0_long_lock *lock, struct m0_long_lock_link *link)
#define M0_CO_START(context)
Definition: coroutine.h:157
#define M0_SET0(obj)
Definition: misc.h:64
#define M0_CO_END(context)
Definition: coroutine.h:167
m0_fom_phase
Definition: fom.h:372
static struct m0_fom_simple fom_simple
Definition: coroutine2.c:78
M0_INTERNAL bool m0_long_write_lock(struct m0_long_lock *lk, struct m0_long_lock_link *link, int next_phase)
#define M0_CO_YIELD_RC(context, rc)
Definition: coroutine.h:248
M0_INTERNAL void m0_co_op_fini(struct m0_co_op *op)
Definition: coroutine.c:188
static struct m0_co_context fom_context
Definition: coroutine2.c:79
const char * scf_name
Definition: sm.h:352
M0_INTERNAL void m0_long_lock_link_fini(struct m0_long_lock_link *link)
Definition: fom_long_lock.c:76
M0_INTERNAL int m0_co_op_tick_ret(struct m0_co_op *op, struct m0_fom *fom, int next_state)
Definition: coroutine.c:226
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
static struct m0_sm_conf coroutine2_conf
Definition: coroutine2.c:57
int insert
Definition: coroutine2.c:64
Definition: reqh.h:94
Definition: dump.c:103
#define M0_CO_YIELD(context)
Definition: coroutine.h:266
#define _S(name, flags, allowed)
void m0_ut__reqh_fini(void)
Definition: locality.c:84
static void crud(struct m0_fom *fom, struct test_tree *tree, int k, int v)
Definition: coroutine2.c:140
M0_INTERNAL void m0_co_op_active(struct m0_co_op *op)
Definition: coroutine.c:210
#define M0_CO_FUN(context, function)
Definition: coroutine.h:183
M0_INTERNAL void m0_long_lock_init(struct m0_long_lock *lock)
Definition: fom.h:481
static struct m0_long_lock fom_lock
Definition: coroutine2.c:84
struct m0_reqh reqh
Definition: rm_foms.c:48
static struct m0_sm_state_descr coroutine2_states[C2_NR]
Definition: coroutine2.c:44
static void wait_for_coroutine_fom(void)
Definition: coroutine2.c:102
M0_INTERNAL int m0_co_context_init(struct m0_co_context *context)
Definition: coroutine.c:130
static struct m0_co_op fom_op
Definition: coroutine2.c:80
static struct test_tree fom_tree
Definition: coroutine2.c:83
#define M0_CO_REENTER(context,...)
Definition: coroutine.h:205
M0_INTERNAL void m0_semaphore_down(struct m0_semaphore *semaphore)
Definition: semaphore.c:49
static void test_run(void)
Definition: coroutine2.c:212
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
static int coroutine_fom_tick(struct m0_fom *fom, int *x, int *__unused)
Definition: coroutine2.c:119
#define M0_FOM_SIMPLE_POST(s, r, c, t, f, d, l)
Definition: fom_simple.h:165
coroutine2_state
Definition: coroutine2.c:38
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
#define M0_UT_ASSERT(a)
Definition: ut.h:46
M0_INTERNAL void m0_co_op_done(struct m0_co_op *op)
Definition: coroutine.c:218
Definition: idx_mock.c:47
static struct m0_co_op * OP(struct m0_fom *fom)
Definition: coroutine2.c:96