Motr  M0
pool.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2015-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 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_BE
24 #include "lib/trace.h"
25 
26 #include "be/pool.h"
27 
28 #include "lib/errno.h" /* ENOMEM */
29 #include "lib/memory.h" /* M0_ALLOC_ARR */
30 #include "be/op.h" /* m0_be_op_active */
31 
40  void **bplq_obj;
41  struct m0_be_op *bplq_op;
43  uint64_t bplq_magic;
44 };
45 
46 static const uint64_t BE_POOL_MAGIC_POISON = 0xCCCCCCCCCCCC;
47 
48 M0_TL_DESCR_DEFINE(be_pool, "list of be_pool_items", static,
49  struct m0_be_pool_item, bpli_link, bpli_magic,
51 M0_TL_DEFINE(be_pool, static, struct m0_be_pool_item);
52 
53 M0_TL_DESCR_DEFINE(be_pool_q, "list of be_pool_queue_items", static,
54  struct be_pool_queue_item, bplq_link, bplq_magic,
56 M0_TL_DEFINE(be_pool_q, static, struct be_pool_queue_item);
57 
58 M0_INTERNAL int m0_be_pool_init(struct m0_be_pool *pool,
59  struct m0_be_pool_cfg *cfg)
60 {
61  pool->bpl_cfg = *cfg;
62  M0_ALLOC_ARR(pool->bpl_q_items, cfg->bplc_q_size);
63  if (pool->bpl_q_items == NULL)
64  return M0_ERR(-ENOMEM);
65 
66  m0_mutex_init(&pool->bpl_lock);
67  be_pool_tlist_init(&pool->bpl_free);
68  be_pool_tlist_init(&pool->bpl_used);
69  be_pool_q_tlist_init(&pool->bpl_q_free);
70  be_pool_q_tlist_init(&pool->bpl_q_pending);
71 
72  m0_forall(i, cfg->bplc_q_size,
73  be_pool_q_tlink_init_at(&pool->bpl_q_items[i],
74  &pool->bpl_q_free), true);
75  return 0;
76 }
77 
78 M0_INTERNAL void m0_be_pool_fini(struct m0_be_pool *pool)
79 {
80  M0_PRE(be_pool_q_tlist_length(&pool->bpl_q_free) ==
81  pool->bpl_cfg.bplc_q_size);
82 
83  m0_forall(i, pool->bpl_cfg.bplc_q_size,
84  be_pool_q_tlink_del_fini(&pool->bpl_q_items[i]), true);
85  be_pool_q_tlist_fini(&pool->bpl_q_pending);
86  be_pool_q_tlist_fini(&pool->bpl_q_free);
87  be_pool_tlist_fini(&pool->bpl_used);
88  be_pool_tlist_fini(&pool->bpl_free);
89  m0_mutex_fini(&pool->bpl_lock);
90  m0_free(pool->bpl_q_items);
91 }
92 
93 static void be_pool_lock(struct m0_be_pool *pool)
94 {
95  m0_mutex_lock(&pool->bpl_lock);
96 }
97 
98 static void be_pool_unlock(struct m0_be_pool *pool)
99 {
100  m0_mutex_unlock(&pool->bpl_lock);
101 }
102 
103 static bool be_pool_is_locked(struct m0_be_pool *pool)
104 {
105  return m0_mutex_is_locked(&pool->bpl_lock);
106 }
107 
108 static void *be_pool_amb(const struct m0_be_pool_descr *d,
109  struct m0_be_pool_item *item)
110 {
111  M0_PRE((unsigned long)item >= (unsigned long)d->bpld_item_offset);
112 
113  return (void *)item - d->bpld_item_offset;
114 }
115 
116 static struct m0_be_pool_item *be_pool_item(const struct m0_be_pool_descr *d,
117  void *obj)
118 {
119  return (struct m0_be_pool_item *)(obj + d->bpld_item_offset);
120 }
121 
122 static uint64_t be_pool_magic(const struct m0_be_pool_descr *d,
123  void *obj)
124 {
125  return *(uint64_t *)(obj + d->bpld_magic_offset);
126 }
127 
128 static void be_pool_magic_set(const struct m0_be_pool_descr *d,
129  void *obj,
130  uint64_t magic)
131 {
132  struct m0_be_pool_item *item = be_pool_item(d, obj);
133 
134  item->bpli_pool_magic = magic;
135  *(uint64_t *)(obj + d->bpld_magic_offset) = magic;
136 }
137 
138 static bool be_pool_obj__invariant(const struct m0_be_pool_descr *d,
139  void *obj)
140 {
141  struct m0_be_pool_item *item = be_pool_item(d, obj);
142 
143  return _0C(item->bpli_pool_magic == d->bpld_magic) &&
144  _0C(be_pool_magic(d, obj) == d->bpld_magic);
145 }
146 
147 static void be_pool_get(const struct m0_be_pool_descr *d,
148  struct m0_be_pool *pool,
149  void **obj)
150 {
151  struct m0_be_pool_item *item;
152 
154  M0_PRE(!be_pool_tlist_is_empty(&pool->bpl_free));
155 
156  item = be_pool_tlist_head(&pool->bpl_free);
157  be_pool_tlist_del(item);
158  be_pool_tlist_add_tail(&pool->bpl_used, item);
159 
160  *obj = be_pool_amb(d, item);
162 }
163 
164 
165 static void be_pool_got_free_item(const struct m0_be_pool_descr *d,
166  struct m0_be_pool *pool)
167 {
168  struct be_pool_queue_item *qi;
169  struct m0_be_op *op;
170 
172 
173  if (!be_pool_q_tlist_is_empty(&pool->bpl_q_pending)) {
174  qi = be_pool_q_tlist_head(&pool->bpl_q_pending);
175  be_pool_q_tlist_del(qi);
176  be_pool_q_tlist_add(&pool->bpl_q_free, qi);
177  be_pool_get(d, pool, qi->bplq_obj);
178  op = qi->bplq_op;
179  /*
180  * be_op can have a callback that calls be_pool functions.
181  * Therefore unlock pool here to prevent a deadlock.
182  * This function should be the last step of logically atomic
183  * operation with the pool lists.
184  */
186  m0_be_op_done(op);
188  }
189 }
190 
191 M0_INTERNAL void m0_be_pool_add(const struct m0_be_pool_descr *d,
192  struct m0_be_pool *pool,
193  void *obj)
194 {
195  struct m0_be_pool_item *item = be_pool_item(d, obj);
196 
198 
200  be_pool_tlink_init_at(item, &pool->bpl_free);
203 
205 }
206 
207 M0_INTERNAL void *m0_be_pool_del(const struct m0_be_pool_descr *d,
208  struct m0_be_pool *pool)
209 {
210  struct m0_be_pool_item *item;
211  void *obj = NULL;
212 
214  item = be_pool_tlist_head(&pool->bpl_free);
215  if (item != NULL) {
216  obj = be_pool_amb(d, item);
219  be_pool_tlink_del_fini(item);
220  }
222 
223  return obj;
224 }
225 
226 M0_INTERNAL void m0_be_pool_get(const struct m0_be_pool_descr *d,
227  struct m0_be_pool *pool,
228  void **obj,
229  struct m0_be_op *op)
230 {
231  struct be_pool_queue_item *qi;
232  bool got = false;
233 
236  if (!be_pool_tlist_is_empty(&pool->bpl_free)) {
237  be_pool_get(d, pool, obj);
238  got = true;
239  } else {
240  qi = be_pool_q_tlist_head(&pool->bpl_q_free);
241  M0_ASSERT_INFO(qi != NULL, "pool=%p op=%p bplc_q_size=%u",
242  pool, op, pool->bpl_cfg.bplc_q_size);
243  be_pool_q_tlist_del(qi);
244  be_pool_q_tlist_add_tail(&pool->bpl_q_pending, qi);
245  qi->bplq_obj = obj;
246  qi->bplq_op = op;
247  }
249  if (got)
250  m0_be_op_done(op);
251 }
252 
253 M0_INTERNAL void m0_be_pool_put(const struct m0_be_pool_descr *d,
254  struct m0_be_pool *pool,
255  void *obj)
256 {
257  struct m0_be_pool_item *item = be_pool_item(d, obj);
258 
260 
262  M0_PRE_EX(be_pool_tlist_contains(&pool->bpl_used, item));
263  be_pool_tlist_del(item);
264  be_pool_tlist_add(&pool->bpl_free, item);
267 }
268 
269 #undef M0_TRACE_SUBSYSTEM
270 
273 /*
274  * Local variables:
275  * c-indentation-style: "K&R"
276  * c-basic-offset: 8
277  * tab-width: 8
278  * fill-column: 80
279  * scroll-step: 1
280  * End:
281  */
282 /*
283  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
284  */
static void be_pool_magic_set(const struct m0_be_pool_descr *d, void *obj, uint64_t magic)
Definition: pool.c:128
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
#define NULL
Definition: misc.h:38
M0_INTERNAL int m0_be_pool_init(struct m0_be_pool *pool, struct m0_be_pool_cfg *cfg)
Definition: pool.c:58
struct m0_be_op * bplq_op
Definition: pool.c:41
static uint64_t magic(const struct m0_tl_descr *d, const void *obj)
Definition: tlist.c:286
struct m0_tlink bplq_link
Definition: pool.c:42
int bpld_magic_offset
Definition: pool.h:92
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_INTERNAL void m0_be_pool_get(const struct m0_be_pool_descr *d, struct m0_be_pool *pool, void **obj, struct m0_be_op *op)
Definition: pool.c:226
static struct m0_rpc_item * item
Definition: item.c:56
static struct foo * obj
Definition: tlist.c:302
static void be_pool_got_free_item(const struct m0_be_pool_descr *d, struct m0_be_pool *pool)
Definition: pool.c:165
M0_TL_DESCR_DEFINE(be_pool, "list of be_pool_items", static, struct m0_be_pool_item, bpli_link, bpli_magic, M0_BE_POOL_MAGIC, M0_BE_POOL_HEAD_MAGIC)
op
Definition: libdemo.c:64
static void be_pool_lock(struct m0_be_pool *pool)
Definition: pool.c:93
int i
Definition: dir.c:1033
static bool be_pool_is_locked(struct m0_be_pool *pool)
Definition: pool.c:103
static void * be_pool_amb(const struct m0_be_pool_descr *d, struct m0_be_pool_item *item)
Definition: pool.c:108
void ** bplq_obj
Definition: pool.c:40
return M0_ERR(-EOPNOTSUPP)
#define M0_ASSERT(cond)
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
static const uint64_t BE_POOL_MAGIC_POISON
Definition: pool.c:46
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
#define M0_POST(cond)
M0_INTERNAL void m0_be_op_done(struct m0_be_op *op)
Definition: stubs.c:104
M0_INTERNAL void m0_be_pool_add(const struct m0_be_pool_descr *d, struct m0_be_pool *pool, void *obj)
Definition: pool.c:191
static void be_pool_unlock(struct m0_be_pool *pool)
Definition: pool.c:98
int bpld_item_offset
Definition: pool.h:90
unsigned bplc_q_size
Definition: pool.h:45
static struct m0_pool pool
Definition: iter_ut.c:58
#define m0_forall(var, nr,...)
Definition: misc.h:112
M0_INTERNAL void m0_be_op_active(struct m0_be_op *op)
Definition: stubs.c:100
uint64_t bplq_magic
Definition: pool.c:43
uint64_t bpld_magic
Definition: pool.h:94
#define _0C(exp)
Definition: assert.h:311
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void * m0_be_pool_del(const struct m0_be_pool_descr *d, struct m0_be_pool *pool)
Definition: pool.c:207
M0_INTERNAL void m0_be_pool_fini(struct m0_be_pool *pool)
Definition: pool.c:78
M0_INTERNAL void m0_be_pool_put(const struct m0_be_pool_descr *d, struct m0_be_pool *pool, void *obj)
Definition: pool.c:253
#define M0_ASSERT_INFO(cond, fmt,...)
static uint64_t be_pool_magic(const struct m0_be_pool_descr *d, void *obj)
Definition: pool.c:122
M0_TL_DEFINE(be_pool, static, struct m0_be_pool_item)
Definition: op.h:74
#define M0_PRE_EX(cond)
void m0_free(void *data)
Definition: memory.c:146
static void be_pool_get(const struct m0_be_pool_descr *d, struct m0_be_pool *pool, void **obj)
Definition: pool.c:147
static struct m0_be_pool_item * be_pool_item(const struct m0_be_pool_descr *d, void *obj)
Definition: pool.c:116
static bool be_pool_obj__invariant(const struct m0_be_pool_descr *d, void *obj)
Definition: pool.c:138