Motr  M0
chan.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-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/thread.h"
25 #include "lib/mutex.h"
26 #include "lib/chan.h"
27 #include "lib/assert.h"
28 #include "lib/timer.h"
29 
30 enum {
31  NR = 16
32 };
33 
34 static struct m0_thread t[NR];
35 static struct m0_chan cc[NR];
36 static struct m0_mutex m[NR];
37 static struct m0_clink l[NR];
38 
39 static void t0(int self)
40 {
41  int i;
42  int j;
43 
44  for (i = 0; i < NR; ++i) {
45  for (j = 0; j < NR; ++j) {
46  if (j != self)
48  }
49 
50  for (j = 0; j < NR - 1; ++j)
51  m0_chan_wait(&l[self]);
52  }
53 }
54 
55 static int flag;
56 
57 static bool cb1(struct m0_clink *clink)
58 {
59  flag += 1;
60  return false;
61 }
62 
63 static bool cb2(struct m0_clink *clink)
64 {
65  flag += 2;
66  return false;
67 }
68 
69 static bool cb_filter(struct m0_clink *clink)
70 {
71  return flag == 1;
72 }
73 
74 static bool mfilter(struct m0_clink *clink)
75 {
76  M0_UT_ASSERT(flag == 0);
77 
78  flag = 1;
79  return false;
80 }
81 
82 unsigned long signal_the_chan_in_timer(unsigned long data)
83 {
84  struct m0_clink *clink = (struct m0_clink *)data;
86  return 0;
87 }
88 
89 void test_chan(void)
90 {
91  struct m0_mutex mutex = {};
92  struct m0_chan chan = {};
93  struct m0_clink clink1;
94  struct m0_clink clink2;
95  struct m0_clink clink3;
96  struct m0_timer timer;
97  int i;
98  int j;
99  bool got;
100  int rc;
101 
103  m0_chan_init(&chan, &mutex);
104 
105  /* test call-back notification */
106  flag = 0;
107  m0_clink_init(&clink1, &cb1);
108 
110  m0_clink_add(&chan, &clink1);
112  M0_UT_ASSERT(flag == 1);
114  M0_UT_ASSERT(flag == 2);
116 
117  m0_clink_init(&clink2, &cb2);
118  m0_clink_add_lock(&chan, &clink2);
119 
120  flag = 0;
122  M0_UT_ASSERT(flag == 1 || flag == 2);
123  flag = 0;
125  M0_UT_ASSERT(flag == 3);
126 
128  m0_clink_del(&clink1);
130 
131  flag = 0;
133  M0_UT_ASSERT(flag == 2);
134  flag = 0;
136  M0_UT_ASSERT(flag == 2);
137 
138  m0_clink_del_lock(&clink2);
139 
140  m0_clink_fini(&clink1);
141  m0_clink_fini(&clink2);
142 
143  /* test synchronous notification */
144 
145  m0_clink_init(&clink1, NULL);
146  m0_clink_add_lock(&chan, &clink1);
147 
148  got = m0_chan_trywait(&clink1);
149  M0_UT_ASSERT(!got);
150 
152  got = m0_chan_trywait(&clink1);
153  M0_UT_ASSERT(got);
154 
156  m0_chan_wait(&clink1);
157 
158  /* wait will expire after 1/5 second */
159  got = m0_chan_timedwait(&clink1,
161  M0_UT_ASSERT(!got);
162 
163  /* chan is signaled after 1/10 second. so the wait will return true */
164  rc = m0_timer_init(&timer, M0_TIMER_HARD, NULL,
165  &signal_the_chan_in_timer, (unsigned long)&clink1);
166  M0_UT_ASSERT(rc == 0);
168  got = m0_chan_timedwait(&clink1,
170  M0_UT_ASSERT(got);
171  m0_timer_stop(&timer);
172  m0_timer_fini(&timer);
173 
174  /* chan is signaled after 1/3 seconds. so the wait will timeout and
175  return false. Another wait should work.*/
176  rc = m0_timer_init(&timer, M0_TIMER_HARD, NULL,
177  &signal_the_chan_in_timer, (unsigned long)&clink1);
178  M0_UT_ASSERT(rc == 0);
180  got = m0_chan_timedwait(&clink1,
182  M0_UT_ASSERT(!got);
183  m0_chan_wait(&clink1); /* another wait. Timer will signal in 1 second */
184  m0_timer_stop(&timer);
185  m0_timer_fini(&timer);
186 
187  m0_clink_del_lock(&clink1);
188  m0_clink_fini(&clink1);
189 
190  /* test filtered events. */
191  m0_clink_init(&clink3, &cb_filter);
192  m0_clink_add_lock(&chan, &clink3);
193 
194  flag = 1;
196  got = m0_chan_trywait(&clink3);
197  M0_UT_ASSERT(!got);
198 
199  flag = 0;
201  got = m0_chan_trywait(&clink3);
202  M0_UT_ASSERT(got);
203 
204  m0_clink_del_lock(&clink3);
205  m0_clink_fini(&clink3);
206 
209 
210  /* multi-threaded test */
211 
212  for (i = 0; i < ARRAY_SIZE(cc); ++i) {
213  m0_mutex_init(&m[i]);
214  m0_chan_init(&cc[i], &m[i]);
215  m0_clink_init(&l[i], NULL);
216  m0_clink_add_lock(&cc[i], &l[i]);
217  }
218 
219  for (i = 0; i < ARRAY_SIZE(t); ++i) {
220  got = M0_THREAD_INIT(&t[i], int, NULL, &t0, i, "t0");
221  M0_UT_ASSERT(got == 0);
222  }
223 
224  for (i = 0; i < ARRAY_SIZE(t); ++i) {
225  m0_thread_join(&t[i]);
226  m0_thread_fini(&t[i]);
227  }
228 
229  for (i = 0; i < ARRAY_SIZE(cc); ++i) {
230  m0_clink_del_lock(&l[i]);
231  m0_clink_fini(&l[i]);
233  m0_mutex_fini(&m[i]);
234  }
235 
236  /*
237  * multi-channel test
238  *
239  * NR clinks are arranged in a group, with cc[0] as a head. Each clink is
240  * added to the corresponding channel.
241  *
242  * j-th channel is signalled and the signal is awaited for on the (j+1)
243  * (in cyclic order) channel.
244  *
245  * mfilter() attached to j-th channel to check filtering for groups.
246  */
247 
248  for (j = 0; j < ARRAY_SIZE(cc); ++j) {
249  for (i = 0; i < ARRAY_SIZE(cc); ++i) {
250  m0_mutex_init(&m[i]);
251  m0_chan_init(&cc[i], &m[i]);
252  }
253 
254  m0_clink_init(&l[0], j == 0 ? mfilter : NULL);
255  for (i = 1; i < ARRAY_SIZE(cc); ++i)
256  m0_clink_attach(&l[i], &l[0], j == i ? mfilter : NULL);
257 
258  for (i = 0; i < ARRAY_SIZE(cc); ++i)
259  m0_clink_add_lock(&cc[i], &l[i]);
260 
261  flag = 0;
262  rc = m0_timer_init(&timer, M0_TIMER_HARD, NULL,
263  &signal_the_chan_in_timer, (unsigned long)&l[j]);
264  M0_UT_ASSERT(rc == 0);
266 
267  m0_chan_wait(&l[(j + 1) % ARRAY_SIZE(cc)]);
268  M0_UT_ASSERT(flag == 1);
269 
270  m0_timer_stop(&timer);
271  m0_timer_fini(&timer);
272 
273  for (i = ARRAY_SIZE(cc) - 1; i >= 0; --i) {
274  m0_clink_del_lock(&l[i]);
275  m0_clink_fini(&l[i]);
277  m0_mutex_fini(&m[i]);
278  }
279  }
280 
281 }
282 M0_EXPORTED(test_chan);
283 
284 /*
285  * Local variables:
286  * c-indentation-style: "K&R"
287  * c-basic-offset: 8
288  * tab-width: 8
289  * fill-column: 80
290  * scroll-step: 1
291  * End:
292  */
static bool cb1(struct m0_clink *clink)
Definition: chan.c:57
static struct m0_mutex m[NR]
Definition: chan.c:36
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
M0_INTERNAL void m0_chan_broadcast_lock(struct m0_chan *chan)
Definition: chan.c:178
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
M0_INTERNAL void m0_clink_del(struct m0_clink *link)
Definition: chan.c:267
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
static bool mfilter(struct m0_clink *clink)
Definition: chan.c:74
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
struct m0_bufvec data
Definition: di.c:40
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
M0_INTERNAL int m0_timer_init(struct m0_timer *timer, enum m0_timer_type type, struct m0_timer_locality *loc, m0_timer_callback_t callback, unsigned long data)
Definition: timer.c:39
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
Definition: timer.h:39
static bool cb2(struct m0_clink *clink)
Definition: chan.c:63
M0_INTERNAL void m0_timer_fini(struct m0_timer *timer)
Definition: timer.c:65
M0_INTERNAL void m0_chan_signal(struct m0_chan *chan)
Definition: chan.c:159
int i
Definition: dir.c:1033
M0_INTERNAL void m0_clink_attach(struct m0_clink *link, struct m0_clink *group, m0_chan_cb_t cb)
Definition: chan.c:215
static bool cb_filter(struct m0_clink *clink)
Definition: chan.c:69
M0_INTERNAL void m0_timer_stop(struct m0_timer *timer)
Definition: timer.c:86
M0_INTERNAL void m0_chan_init(struct m0_chan *chan, struct m0_mutex *ch_guard)
Definition: chan.c:96
M0_INTERNAL void m0_timer_start(struct m0_timer *timer, m0_time_t expire)
Definition: timer.c:75
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
M0_INTERNAL bool m0_chan_trywait(struct m0_clink *link)
Definition: chan.c:331
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
Definition: chan.h:229
static void t0(int self)
Definition: chan.c:39
static struct m0_clink clink[RDWR_REQUEST_MAX]
static int flag
Definition: chan.c:55
static struct m0_clink l[NR]
Definition: chan.c:37
M0_INTERNAL void m0_chan_signal_lock(struct m0_chan *chan)
Definition: chan.c:165
void m0_clink_add_lock(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:255
void test_chan(void)
Definition: chan.c:89
static struct m0_chan chan[RDWR_REQUEST_MAX]
Definition: chan.c:31
M0_INTERNAL void m0_clink_add(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:228
M0_INTERNAL bool m0_chan_timedwait(struct m0_clink *link, const m0_time_t abs_timeout)
Definition: chan.c:349
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
struct m0_mutex mutex
Definition: format.h:170
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
M0_INTERNAL void m0_chan_fini_lock(struct m0_chan *chan)
Definition: chan.c:112
Definition: mutex.h:47
M0_INTERNAL void m0_chan_broadcast(struct m0_chan *chan)
Definition: chan.c:172
int32_t rc
Definition: trigger_fop.h:47
static struct m0_thread t[NR]
Definition: chan.c:34
#define ARRAY_SIZE(a)
Definition: misc.h:45
#define M0_UT_ASSERT(a)
Definition: ut.h:46
unsigned long signal_the_chan_in_timer(unsigned long data)
Definition: chan.c:82
static struct m0_chan cc[NR]
Definition: chan.c:35