Motr  M0
coroutine.c
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 
29 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_LIB
30 #include "lib/trace.h"
31 #include "lib/coroutine.h"
32 #include "lib/memory.h"
33 #include "fop/fom.h"
34 
35 
37 {
40  alloc->la_frame = 0;
41  return alloc->la_pool == NULL ? -ENOMEM : 0;
42 }
43 
45 {
46  M0_PRE(alloc->la_frame == 0);
49 }
50 
51 static void *locals_alloc(struct m0_co_locals_allocator *alloc, uint64_t frame,
52  uint64_t size)
53 {
54  struct m0_co_la_item *curr;
55  struct m0_co_la_item *prev;
56  uint64_t i;
57  uint64_t aligned_sz = m0_align(size +
60  M0_PRE(alloc->la_frame == frame);
61 
62  curr = &alloc->la_items[alloc->la_frame];
63  if (alloc->la_frame == 0) {
64  curr->lai_addr = alloc->la_pool;
65  curr->lai_size = aligned_sz;
66  alloc->la_total = curr->lai_size;
67  } else {
68  prev = &alloc->la_items[alloc->la_frame - 1];
69  curr->lai_addr = prev->lai_addr + prev->lai_size;
70  M0_ASSERT(m0_is_aligned((uint64_t) curr->lai_addr,
72  curr->lai_size = aligned_sz;
73  alloc->la_total += curr->lai_size;
74  }
75 
77  M0_ASSERT(alloc->la_frame < M0_MCC_STACK_NR);
78 
79  /* test memory's zeroed */
80  for (i = 0; i < curr->lai_size; ++i)
81  M0_ASSERT(((uint8_t*) curr->lai_addr)[i] == 0x00);
82 
83  memset(curr->lai_addr, 0xCC, aligned_sz);
84  alloc->la_frame++;
85 
86  return curr->lai_addr;
87 }
88 
89 static void locals_free(struct m0_co_locals_allocator *alloc, uint64_t frame)
90 {
91  uint64_t i;
92  struct m0_co_la_item *curr;
93 
94  curr = &alloc->la_items[--alloc->la_frame];
95  M0_PRE(alloc->la_frame >= 0);
96  M0_PRE(alloc->la_frame == frame);
97 
98  /* test pad is CC-ed */
99  for (i = curr->lai_size - M0_MCC_LOCALS_ALLOC_PAD_SZ;
100  i < curr->lai_size; ++i)
101  M0_ASSERT(((uint8_t*) curr->lai_addr)[i] == 0xCC);
102 
103  memset(curr->lai_addr, 0x00, curr->lai_size);
104  alloc->la_total -= curr->lai_size;
105  curr->lai_addr = NULL;
106  curr->lai_size = 0;
107 
108  M0_ASSERT(ergo(frame == 0, alloc->la_total == 0));
109 }
110 
111 M0_INTERNAL void m0_co_context_locals_alloc(struct m0_co_context *context,
112  uint64_t size)
113 {
114  context->mc_locals[context->mc_frame] =
115  locals_alloc(&context->mc_alloc, context->mc_frame, size);
116 }
117 
118 M0_INTERNAL void m0_co_context_locals_free(struct m0_co_context *context)
119 {
120  locals_free(&context->mc_alloc, context->mc_frame);
121  context->mc_locals[context->mc_frame] = NULL;
122 }
123 
124 M0_INTERNAL void *m0_co_context_locals(struct m0_co_context *context)
125 {
126  return context->mc_locals[context->mc_yield ? context->mc_yield_frame :
127  context->mc_frame];
128 }
129 
130 M0_INTERNAL int m0_co_context_init(struct m0_co_context *context)
131 {
132  *context = (struct m0_co_context) { .mc_yield = false };
133  return locals_alloc_init(&context->mc_alloc);
134 }
135 
136 M0_INTERNAL void m0_co_context_fini(struct m0_co_context *context)
137 {
138  locals_alloc_fini(&context->mc_alloc);
139 }
140 
146 };
147 
148 static struct m0_sm_state_descr co_states[] = {
149  [COR_INIT] = {
151  .sd_name = "COR_INIT",
152  .sd_allowed = M0_BITS(COR_ACTIVE),
153  },
154  [COR_ACTIVE] = {
155  .sd_flags = 0,
156  .sd_name = "COR_ACTIVE",
157  .sd_allowed = M0_BITS(COR_DONE),
158  },
159  [COR_DONE] = {
160  .sd_flags = M0_SDF_TERMINAL,
161  .sd_name = "COR_DONE",
162  .sd_allowed = 0,
163  },
164 };
165 
166 static struct m0_sm_trans_descr co_trans[] = {
167  { "started", COR_INIT, COR_ACTIVE },
168  { "completed", COR_ACTIVE, COR_DONE },
169 };
170 
171 M0_INTERNAL struct m0_sm_conf co_states_conf = {
172  .scf_name = "m0_co_op::co_sm",
173  .scf_nr_states = ARRAY_SIZE(co_states),
174  .scf_state = co_states,
175  .scf_trans_nr = ARRAY_SIZE(co_trans),
176  .scf_trans = co_trans
177 };
178 
179 M0_INTERNAL void m0_co_op_init(struct m0_co_op *op)
180 {
181  M0_PRE_EX(M0_IS0(op));
182  m0_sm_group_init(&op->co_sm_group);
184  &op->co_sm_group);
185 }
186 M0_EXPORTED(m0_co_op_init);
187 
188 M0_INTERNAL void m0_co_op_fini(struct m0_co_op *op)
189 {
190  m0_sm_group_lock(&op->co_sm_group);
191  M0_PRE(M0_IN(op->co_sm.sm_state, (COR_INIT, COR_DONE)));
192 
193  if (op->co_sm.sm_state == COR_INIT) {
194  m0_sm_state_set(&op->co_sm, COR_ACTIVE);
195  m0_sm_state_set(&op->co_sm, COR_DONE);
196  }
197  m0_sm_fini(&op->co_sm);
198  m0_sm_group_unlock(&op->co_sm_group);
199  M0_SET0(op);
200 }
201 M0_EXPORTED(m0_co_op_fini);
202 
203 M0_INTERNAL void m0_co_op_reset(struct m0_co_op *op)
204 {
205  m0_co_op_fini(op);
206  m0_co_op_init(op);
207 }
208 M0_EXPORTED(m0_co_op_reset);
209 
210 M0_INTERNAL void m0_co_op_active(struct m0_co_op *op)
211 {
212  m0_sm_group_lock(&op->co_sm_group);
213  m0_sm_state_set(&op->co_sm, COR_ACTIVE);
214  m0_sm_group_unlock(&op->co_sm_group);
215 }
216 M0_EXPORTED(m0_co_op_active);
217 
218 M0_INTERNAL void m0_co_op_done(struct m0_co_op *op)
219 {
220  m0_sm_group_lock(&op->co_sm_group);
221  m0_sm_state_set(&op->co_sm, COR_DONE);
222  m0_sm_group_unlock(&op->co_sm_group);
223 }
224 M0_EXPORTED(m0_co_op_done);
225 
226 M0_INTERNAL int m0_co_op_tick_ret(struct m0_co_op *op,
227  struct m0_fom *fom,
228  int next_state)
229 {
231 
232  m0_sm_group_lock(&op->co_sm_group);
233  M0_PRE(M0_IN(op->co_sm.sm_state, (COR_ACTIVE, COR_DONE)));
234 
235  if (op->co_sm.sm_state == COR_ACTIVE) {
236  ret = M0_FSO_WAIT;
237  m0_fom_wait_on(fom, &op->co_sm.sm_chan, &fom->fo_cb);
238  }
239  m0_sm_group_unlock(&op->co_sm_group);
240 
241  m0_fom_phase_set(fom, next_state);
242  return ret;
243 }
244 M0_EXPORTED(m0_co_op_tick_ret);
245 
246 #undef M0_TRACE_SUBSYSTEM
247 
250 /*
251  * Local variables:
252  * c-indentation-style: "K&R"
253  * c-basic-offset: 8
254  * tab-width: 8
255  * fill-column: 80
256  * scroll-step: 1
257  * End:
258  */
259 /*
260  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
261  */
#define M0_PRE(cond)
M0_INTERNAL void m0_co_context_fini(struct m0_co_context *context)
Definition: coroutine.c:136
static struct m0_sm_trans_descr co_trans[]
Definition: coroutine.c:166
#define NULL
Definition: misc.h:38
#define ergo(a, b)
Definition: misc.h:293
Definition: storage.c:103
Definition: sm.h:350
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_free_aligned(void *data, size_t size, unsigned shift)
Definition: memory.c:192
M0_INTERNAL void m0_co_op_init(struct m0_co_op *op)
Definition: coroutine.c:179
M0_INTERNAL void m0_fom_wait_on(struct m0_fom *fom, struct m0_chan *chan, struct m0_fom_callback *cb)
Definition: fom.c:1490
#define M0_BITS(...)
Definition: misc.h:236
#define M0_SET0(obj)
Definition: misc.h:64
m0_co_op_state
Definition: coroutine.c:141
op
Definition: libdemo.c:64
static void locals_free(struct m0_co_locals_allocator *alloc, uint64_t frame)
Definition: coroutine.c:89
M0_INTERNAL void m0_sm_group_unlock(struct m0_sm_group *grp)
Definition: sm.c:96
int i
Definition: dir.c:1033
M0_INTERNAL void m0_co_op_fini(struct m0_co_op *op)
Definition: coroutine.c:188
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
uint64_t mc_yield_frame
Definition: coroutine.h:148
M0_INTERNAL void m0_sm_group_init(struct m0_sm_group *grp)
Definition: sm.c:53
static bool m0_is_aligned(uint64_t val, uint64_t alignment)
Definition: arith.h:179
void m0_sm_state_set(struct m0_sm *mach, int state)
Definition: sm.c:478
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 struct m0_sm_conf co_states_conf
Definition: coroutine.c:171
uint64_t lai_size
Definition: coroutine.h:47
static struct ff2c_term * alloc(void)
Definition: parser.c:37
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
static int locals_alloc_init(struct m0_co_locals_allocator *alloc)
Definition: coroutine.c:36
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
uint32_t sd_flags
Definition: sm.h:378
Definition: fom.h:481
static struct m0_sm_state_descr co_states[]
Definition: coroutine.c:148
m0_fom_phase_outcome
Definition: fom.h:625
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
#define M0_IS0(obj)
Definition: misc.h:70
M0_INTERNAL int m0_co_context_init(struct m0_co_context *context)
Definition: coroutine.c:130
m0_bcount_t size
Definition: di.c:39
M0_INTERNAL void m0_sm_group_lock(struct m0_sm_group *grp)
Definition: sm.c:83
void * mc_locals[M0_MCC_STACK_NR]
Definition: coroutine.h:140
void m0_fom_phase_set(struct m0_fom *fom, int phase)
Definition: fom.c:1688
M0_INTERNAL void * m0_alloc_aligned(size_t size, unsigned shift)
Definition: memory.c:168
#define M0_PRE_EX(cond)
M0_INTERNAL void m0_co_context_locals_free(struct m0_co_context *context)
Definition: coroutine.c:118
#define ARRAY_SIZE(a)
Definition: misc.h:45
static uint64_t m0_align(uint64_t val, uint64_t alignment)
Definition: arith.h:170
M0_INTERNAL void m0_co_op_done(struct m0_co_op *op)
Definition: coroutine.c:218
static void * locals_alloc(struct m0_co_locals_allocator *alloc, uint64_t frame, uint64_t size)
Definition: coroutine.c:51
static void locals_alloc_fini(struct m0_co_locals_allocator *alloc)
Definition: coroutine.c:44
M0_INTERNAL void m0_sm_fini(struct m0_sm *mach)
Definition: sm.c:331