Motr  M0
coroutine.h
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2017-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 #pragma once
24 
25 #ifndef __MOTR_LIB_COROUTINE_H__
26 #define __MOTR_LIB_COROUTINE_H__
27 
34 #include "lib/types.h"
35 #include "lib/errno.h"
36 
37 enum {
43 };
44 
45 struct m0_co_la_item {
46  void *lai_addr;
47  uint64_t lai_size;
48 };
49 
57 
59  uint64_t la_frame;
60 
65  void *la_pool;
67  uint64_t la_total;
68 };
69 
142  uint64_t mc_frame;
144  bool mc_yield;
148  uint64_t mc_yield_frame;
151 };
152 
157 #define M0_CO_START(context) \
158 ({ \
159  M0_ASSERT((context)->mc_yield_frame == 0); \
160 })
161 
167 #define M0_CO_END(context) \
168 ({ \
169  int rc = ((context)->mc_yield ? (context)->mc_co_end_ret : 0); \
170  if (rc == 0) { \
171  M0_ASSERT((context)->mc_frame == 0); \
172  M0_ASSERT((context)->mc_yield_frame == 0); \
173  m0_co_context_locals_free((context)); \
174  } \
175  rc; \
176 })
177 
183 #define M0_CO_FUN(context, function) \
184 ({ \
185  __label__ save; \
186  M0_LOG(M0_DEBUG, "M0_CO_FUN: context=%p yeild=%d", \
187  context, !!context->mc_yield); \
188  M0_ASSERT(context->mc_frame < M0_MCC_STACK_NR); \
189  context->mc_stack[context->mc_frame++] = &&save; \
190 save: (function); \
191  if (context->mc_yield) { \
192  return; \
193  } else { \
194  m0_co_context_locals_free(context); \
195  context->mc_frame--; \
196  } \
197 })
198 
199 #define M0_CO_FRAME_DATA(field) (__frame_data__->field)
200 
205 #define M0_CO_REENTER(context, ...) \
206  struct foo_context { \
207  __VA_ARGS__ \
208  }; \
209  struct foo_context *__frame_data__; \
210  M0_CO__REENTER((context), __frame_data__);
211 
223 #define M0_CO__REENTER(context, frame_data) \
224 ({ \
225  uint64_t size = sizeof(*frame_data); \
226  M0_LOG(M0_DEBUG, "M0_CO_REENTER: context=%p yeild=%d", \
227  context, !!context->mc_yield); \
228  if (!context->mc_yield) { \
229  m0_co_context_locals_alloc(context, (size)); \
230  frame_data = m0_co_context_locals(context); \
231  } else { \
232  M0_ASSERT(context->mc_yield_frame < M0_MCC_STACK_NR); \
233  frame_data = m0_co_context_locals(context); \
234  goto *context->mc_stack[context->mc_yield_frame++]; \
235  } \
236 })
237 
248 #define M0_CO_YIELD_RC(context, rc) \
249 ({ \
250  __label__ save; \
251  M0_LOG(M0_DEBUG, "M0_CO_YIELD: context=%p yeild=%d", \
252  context, !!context->mc_yield); \
253  context->mc_yield = true; \
254  context->mc_co_end_ret = (rc); \
255  M0_ASSERT(context->mc_frame < M0_MCC_STACK_NR); \
256  context->mc_stack[context->mc_frame++] = &&save; \
257  return; \
258 save: \
259  M0_ASSERT(context->mc_yield); \
260  M0_ASSERT(context->mc_frame == context->mc_yield_frame); \
261  context->mc_yield = false; \
262  context->mc_yield_frame = 0; \
263  context->mc_frame--; \
264 })
265 
266 #define M0_CO_YIELD(context) M0_CO_YIELD_RC(context, -EAGAIN)
267 
268 
269 M0_INTERNAL int m0_co_context_init(struct m0_co_context *context);
270 M0_INTERNAL void m0_co_context_fini(struct m0_co_context *context);
271 
272 /* internal */
273 M0_INTERNAL void *m0_co_context_locals(struct m0_co_context *context);
274 M0_INTERNAL void m0_co_context_locals_alloc(struct m0_co_context *context,
275  uint64_t size);
276 M0_INTERNAL void m0_co_context_locals_free(struct m0_co_context *context);
277 
278 #include "sm/sm.h" /* m0_sm_group */
279 
280 struct m0_fom;
281 
282 struct m0_co_op {
283  struct m0_sm co_sm;
284  /* MOTR-787: get rid of explicit locking here, use locality lock! */
286 };
287 
288 M0_INTERNAL void m0_co_op_init(struct m0_co_op *op);
289 M0_INTERNAL void m0_co_op_fini(struct m0_co_op *op);
290 
291 M0_INTERNAL void m0_co_op_reset(struct m0_co_op *op);
292 M0_INTERNAL void m0_co_op_active(struct m0_co_op *op);
293 M0_INTERNAL void m0_co_op_done(struct m0_co_op *op);
294 
295 /* Don't introduce co_op_wait()! co_op intended to be used inside foms. */
296 M0_INTERNAL int m0_co_op_tick_ret(struct m0_co_op *op,
297  struct m0_fom *fom,
298  int next_state);
299 
301 #endif /* __MOTR_LIB_COROUTINE_H__ */
302 
303 /*
304  * Local variables:
305  * c-indentation-style: "K&R"
306  * c-basic-offset: 8
307  * tab-width: 8
308  * fill-column: 80
309  * scroll-step: 1
310  * End:
311  */
312 /*
313  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
314  */
M0_INTERNAL void m0_co_context_fini(struct m0_co_context *context)
Definition: coroutine.c:136
uint64_t mc_frame
Definition: coroutine.h:142
M0_INTERNAL void m0_co_op_reset(struct m0_co_op *op)
Definition: coroutine.c:203
M0_INTERNAL void m0_co_op_init(struct m0_co_op *op)
Definition: coroutine.c:179
op
Definition: libdemo.c:64
struct m0_sm_group co_sm_group
Definition: coroutine.h:285
M0_INTERNAL void m0_co_op_fini(struct m0_co_op *op)
Definition: coroutine.c:188
uint64_t mc_yield_frame
Definition: coroutine.h:148
M0_INTERNAL int m0_co_op_tick_ret(struct m0_co_op *op, struct m0_fom *fom, int next_state)
Definition: coroutine.c:226
uint64_t lai_size
Definition: coroutine.h:47
M0_INTERNAL void m0_co_context_locals_alloc(struct m0_co_context *context, uint64_t size)
Definition: coroutine.c:111
void * lai_addr
Definition: coroutine.h:46
Definition: dump.c:103
M0_INTERNAL void * m0_co_context_locals(struct m0_co_context *context)
Definition: coroutine.c:124
struct m0_co_locals_allocator mc_alloc
Definition: coroutine.h:150
M0_INTERNAL void m0_co_op_active(struct m0_co_op *op)
Definition: coroutine.c:210
int mc_co_end_ret
Definition: coroutine.h:146
Definition: fom.h:481
M0_INTERNAL int m0_co_context_init(struct m0_co_context *context)
Definition: coroutine.c:130
void * mc_stack[M0_MCC_STACK_NR]
Definition: coroutine.h:138
Definition: sm.h:301
m0_bcount_t size
Definition: di.c:39
struct m0_sm co_sm
Definition: coroutine.h:283
struct m0_co_la_item la_items[M0_MCC_STACK_NR]
Definition: coroutine.h:56
void * mc_locals[M0_MCC_STACK_NR]
Definition: coroutine.h:140
M0_INTERNAL void m0_co_context_locals_free(struct m0_co_context *context)
Definition: coroutine.c:118
M0_INTERNAL void m0_co_op_done(struct m0_co_op *op)
Definition: coroutine.c:218