Motr  M0
thread.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2011-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 "lib/misc.h" /* M0_SET_ARR0 */
24 #include "ut/ut.h"
25 #include "lib/ub.h"
26 #include "lib/thread.h"
27 #include "lib/bitmap.h"
28 #include "lib/assert.h"
29 #include "lib/memory.h"
30 #include "lib/semaphore.h"
31 #include "module/instance.h"
32 
33 enum { NR = 255 };
34 
35 void test_is_awkward(void);
36 static void test_adopt(void);
37 
38 static int t0place;
39 
40 static void t0(int x)
41 {
42  t0place = x;
43 }
44 
45 static struct m0_thread t[NR];
46 static int r[NR];
47 
48 static void t2(int n)
49 {
50  int result;
51 
52  if (n > 0) {
53  result = M0_THREAD_INIT(&t[n - 1], int, NULL, &t2, n - 1, "t2");
54  M0_UT_ASSERT(result == 0);
55  }
56  r[n] = n;
57 }
58 
59 static void t3(int n)
60 {
61  int result;
62  struct m0_bitmap t3bm;
63 
64  /* set affinity (confine) to CPU 0 */
65  M0_UT_ASSERT(m0_bitmap_init(&t3bm, 3) == 0);
66  m0_bitmap_set(&t3bm, 0, true);
67 
68  result = m0_thread_confine(&t[n], &t3bm);
69  M0_UT_ASSERT(result == 0);
70 
71  m0_bitmap_fini(&t3bm);
72 
74 }
75 
76 static char t1place[100];
77 
78 static void forty_two_func(const char *s)
79 {
80  strcpy(t1place, s);
81 }
82 
83 static int lambda42_init(int x)
84 {
85  return 0;
86 }
87 
88 static void lambda42_func(int x)
89 {
90 }
91 
92 static int lambda_42_init(int x)
93 {
94  return -42;
95 }
96 
97 static void lambda_42_func(int x)
98 {
99 }
100 
101 void test_thread(void)
102 {
103  int i;
104  int result;
105 
107 
108  M0_SET_ARR0(r);
109  t0place = 0;
110  result = M0_THREAD_INIT(&t[0], int, NULL, &t0, 42, "t0");
111  M0_UT_ASSERT(result == 0);
112 
113  M0_UT_ASSERT(m0_thread_self() != &t[0]);
114  M0_UT_ASSERT(m0_thread_join(&t[0]) == 0);
115  m0_thread_fini(&t[0]);
116  M0_UT_ASSERT(t0place == 42);
117 
118  result = M0_THREAD_INIT(&t[0], const char *, NULL, &forty_two_func,
119  (const char *)"forty-two", "fourty-two");
120  M0_UT_ASSERT(result == 0);
121  m0_thread_join(&t[0]);
122  m0_thread_fini(&t[0]);
123  M0_UT_ASSERT(!strcmp(t1place, "forty-two"));
124 
125  t2(NR - 1);
126  for (i = NR - 2; i >= 0; --i) {
127  /* this loop is safe, because t[n] fills t[n - 1] before
128  exiting. */
129  m0_thread_join(&t[i]);
130  m0_thread_fini(&t[i]);
131  M0_UT_ASSERT(r[i] == i);
132  }
133 
134  /* test init functions */
135  result = M0_THREAD_INIT(&t[0], int, &lambda42_init, &lambda42_func,
136  42, "lambda42");
137  M0_UT_ASSERT(result == 0);
138  m0_thread_join(&t[0]);
139  m0_thread_fini(&t[0]);
140 
141  result = M0_THREAD_INIT(&t[0], int, &lambda_42_init, &lambda_42_func,
142  42, "lambda-42");
143  M0_UT_ASSERT(result == -42);
144  m0_thread_fini(&t[0]);
145 
146  /* test confine */
147  result = M0_THREAD_INIT(&t[0], int, NULL, &t3, 0, "t3");
148  M0_UT_ASSERT(result == 0);
149  m0_thread_join(&t[0]);
150  m0_thread_fini(&t[0]);
151 
152  /* test m0_is_awkward() */
153 #ifndef __KERNEL__
154  test_is_awkward();
155 #endif
156  test_adopt();
157 }
158 M0_EXPORTED(test_thread);
159 
160 enum {
161  UB_ITER = 10000
162 };
163 
164 static struct m0_thread ubt[UB_ITER];
165 
166 static void threads_set0(void)
167 {
168  M0_SET_ARR0(ubt);
169 }
170 
171 static int ub_init(const char *opts M0_UNUSED)
172 {
173  threads_set0();
174  return 0;
175 }
176 
177 static void ub_fini(void)
178 {
179  int i;
180 
181  for (i = 0; i < ARRAY_SIZE(ubt); ++i)
182  m0_thread_fini(&ubt[i]);
183 }
184 
185 static void ub0(int x)
186 {
187 }
188 
189 static void ub_spawn(int i)
190 {
191  int result;
192  result = M0_THREAD_INIT(&ubt[i], int, NULL, &ub0, 0, "ub0");
193  M0_ASSERT(result == 0);
194 }
195 
196 static void ub_join(int i)
197 {
198  m0_thread_join(&ubt[i]);
199 }
200 
201 static int ub_spawn_initcall(int x)
202 {
203  return 0;
204 }
205 
206 static void ub_spawn_init(int i)
207 {
208  int result;
209  result = M0_THREAD_INIT(&ubt[i], int, &ub_spawn_initcall, &ub0, 0,
210  "ub0");
211  M0_ASSERT(result == 0);
212 }
213 
214 static void ub_join_all(void)
215 {
216  int i;
217 
218  for (i = 0; i < ARRAY_SIZE(ubt); ++i)
219  m0_thread_join(&ubt[i]);
220  threads_set0();
221 }
222 
224  .us_name = "thread-ub",
225  .us_init = ub_init,
226  .us_fini = ub_fini,
227  .us_run = {
228  { .ub_name = "spawn",
229  .ub_iter = UB_ITER,
230  .ub_round = ub_spawn },
231 
232  { .ub_name = "join",
233  .ub_iter = UB_ITER,
234  .ub_round = ub_join,
235  .ub_fini = threads_set0 },
236 
237  { .ub_name = "spawn-init",
238  .ub_iter = UB_ITER,
239  .ub_round = ub_spawn_init,
240  .ub_fini = ub_join_all },
241 
242  { .ub_name = NULL }
243  }
244 };
245 
246 static void set_and_check_is_awkward(void)
247 {
249  M0_UT_ASSERT(m0_is_awkward() == true);
250 
251  m0_exit_awkward();
252  M0_UT_ASSERT(m0_is_awkward() == false);
253 
254  /* Recurrsive check */
256  M0_UT_ASSERT(m0_is_awkward() == true);
257 
259  M0_UT_ASSERT(m0_is_awkward() == true);
260 
261  m0_exit_awkward();
262  M0_UT_ASSERT(m0_is_awkward() == true);
263 
264  m0_exit_awkward();
265  M0_UT_ASSERT(m0_is_awkward() == false);
266 }
267 
268 static void ut_t0_handler1(int arg)
269 {
270  /* check default */
271  M0_UT_ASSERT(m0_is_awkward() == false);
272 
273  /* set and check is_awkward() */
275 }
276 
277 void test_is_awkward(void)
278 {
279  int result;
280 
281  result = M0_THREAD_INIT(&t[0], int, NULL, &ut_t0_handler1,
282  0, "ut_t0_handler1");
283  M0_UT_ASSERT(result == 0);
284 
285  m0_thread_join(&t[0]);
286  m0_thread_fini(&t[0]);
287 }
288 
289 #ifndef __KERNEL__
290 #include <pthread.h>
291 
292 static struct m0_semaphore synch;
293 
294 static void *adopted(void *arg)
295 {
296  struct m0 *instance = arg;
297  struct m0_thread thread = {};
298  void *area;
299 
301  M0_UT_ASSERT(m0_thread_tls() != 0);
303 
304  /* Check that Motr calls work in this thread. */
305  area = m0_alloc(3215);
306  M0_UT_ASSERT(area != NULL);
308  m0_free(area);
309  m0_thread_shun();
310  return NULL;
311 }
312 
313 static void test_adopt(void)
314 {
315  int result;
316  pthread_t rawthread;
317 
319  result = pthread_create(&rawthread, NULL, &adopted, m0_get());
320  M0_UT_ASSERT(result == 0);
322  pthread_join(rawthread, NULL);
323 }
324 
325 #else /* __KERNEL__ */
326 static void test_adopt(void)
327 {;}
328 #endif /* __KERNEL__ */
329 
330 /*
331  * Local variables:
332  * c-indentation-style: "K&R"
333  * c-basic-offset: 8
334  * tab-width: 8
335  * fill-column: 80
336  * scroll-step: 1
337  * End:
338  */
M0_INTERNAL void m0_enter_awkward(void)
Definition: kthread.c:249
static void forty_two_func(const char *s)
Definition: thread.c:78
static void ut_t0_handler1(int arg)
Definition: thread.c:268
static void t0(int x)
Definition: thread.c:40
M0_INTERNAL int m0_bitmap_init(struct m0_bitmap *map, size_t nr)
Definition: bitmap.c:86
struct m0_ub_set m0_thread_ub
Definition: thread.c:223
Definition: thread.c:33
#define NULL
Definition: misc.h:38
M0_INTERNAL int m0_thread_confine(struct m0_thread *q, const struct m0_bitmap *processors)
Definition: kthread.c:197
M0_INTERNAL void m0_bitmap_fini(struct m0_bitmap *map)
Definition: bitmap.c:97
static struct m0_thread ubt[UB_ITER]
Definition: thread.c:164
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
static void set_and_check_is_awkward(void)
Definition: thread.c:246
static bool x
Definition: sm.c:168
static void ub_join(int i)
Definition: thread.c:196
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
M0_INTERNAL struct m0 * m0_get(void)
Definition: instance.c:41
M0_INTERNAL int m0_thread_adopt(struct m0_thread *thread, struct m0 *instance)
Definition: thread.c:127
static void ub_spawn(int i)
Definition: thread.c:189
static void * adopted(void *arg)
Definition: thread.c:294
M0_INTERNAL struct m0_thread_tls * m0_thread_tls(void)
Definition: kthread.c:67
static void t2(int n)
Definition: thread.c:48
int i
Definition: dir.c:1033
#define M0_SET_ARR0(arr)
Definition: misc.h:72
static struct m0_thread t[NR]
Definition: thread.c:45
static char t1place[100]
Definition: thread.c:76
void test_thread(void)
Definition: thread.c:101
static void test_adopt(void)
Definition: thread.c:313
#define M0_ASSERT(cond)
const char * us_name
Definition: ub.h:76
void test_is_awkward(void)
Definition: thread.c:277
struct m0_thread thread
Definition: note.c:104
static void lambda_42_func(int x)
Definition: thread.c:97
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
Definition: instance.h:80
static void ub_spawn_init(int i)
Definition: thread.c:206
static int ub_spawn_initcall(int x)
Definition: thread.c:201
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
void * m0_alloc(size_t size)
Definition: memory.c:126
M0_INTERNAL bool m0_is_awkward(void)
Definition: kthread.c:269
M0_INTERNAL void m0_bitmap_set(struct m0_bitmap *map, size_t idx, bool val)
Definition: bitmap.c:139
static int t0place
Definition: thread.c:38
static void ub_fini(void)
Definition: thread.c:177
M0_INTERNAL void m0_thread_shun(void)
Definition: thread.c:134
static int ub_init(const char *opts M0_UNUSED)
Definition: thread.c:171
static void ub_join_all(void)
Definition: thread.c:214
uint64_t n
Definition: fops.h:107
static void ub0(int x)
Definition: thread.c:185
static void threads_set0(void)
Definition: thread.c:166
static int lambda_42_init(int x)
Definition: thread.c:92
static int r[NR]
Definition: thread.c:46
M0_INTERNAL struct m0_thread * m0_thread_self(void)
Definition: thread.c:122
static void lambda42_func(int x)
Definition: thread.c:88
static struct m0 instance
Definition: main.c:78
M0_INTERNAL void m0_exit_awkward(void)
Definition: kthread.c:262
M0_INTERNAL void m0_semaphore_down(struct m0_semaphore *semaphore)
Definition: semaphore.c:49
static struct m0_semaphore synch
Definition: thread.c:292
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
static int lambda42_init(int x)
Definition: thread.c:83
static void t3(int n)
Definition: thread.c:59
void m0_free(void *data)
Definition: memory.c:146
static struct m0_addb2_source * s
Definition: consumer.c:39
#define ARRAY_SIZE(a)
Definition: misc.h:45
Definition: ub.h:74
#define M0_UT_ASSERT(a)
Definition: ut.h:46
#define M0_UNUSED
Definition: misc.h:380