Motr  M0
thread.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-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 #ifndef __KERNEL__
24 # include <stdarg.h>
25 # include <stdio.h> /* vsnprintf */
26 #endif
27 
28 #include "lib/thread.h"
29 #include "lib/misc.h" /* M0_SET0 */
30 #include "module/instance.h" /* m0_get */
31 #include "addb2/global.h"
32 
41 int m0_thread_init(struct m0_thread *q, int (*init)(void *),
42  void (*func)(void *), void *arg, const char *namefmt, ...)
43 {
44  int result;
45  va_list varargs;
46 
47  M0_PRE(M0_IS0(q));
48  M0_PRE(q->t_func == NULL);
49  M0_PRE(q->t_state == TS_PARKED);
50 
51  va_start(varargs, namefmt);
52  result = vsnprintf(q->t_namebuf, sizeof q->t_namebuf, namefmt, varargs);
53  va_end(varargs);
54  M0_ASSERT_INFO(result < sizeof q->t_namebuf,
55  "namebuf truncated to \"%s\"", q->t_namebuf);
56 
57  q->t_state = TS_RUNNING;
58  q->t_init = init;
59  q->t_func = func;
60  q->t_arg = arg;
61 
62  result = m0_semaphore_init(&q->t_wait, 0);
63  if (result != 0)
64  return result;
65 
66  /* Let `q' inherit the pointer from current thread's TLS.
67  * m0_set() is of no use here, since it has no impact on the TLS
68  * of `q'. */
69  q->t_tls.tls_m0_instance = m0_get();
70  q->t_tls.tls_self = q;
71 
72  result = m0_thread_init_impl(q, q->t_namebuf);
73  if (result != 0)
74  goto err;
75 
76  if (q->t_init != NULL) {
77  m0_semaphore_down(&q->t_wait);
78  result = q->t_initrc;
79  if (result != 0)
81  }
82 
83  if (result == 0)
84  return 0;
85 err:
86  m0_semaphore_fini(&q->t_wait);
87  q->t_state = TS_PARKED;
88  return result;
89 }
90 M0_EXPORTED(m0_thread_init);
91 
92 void m0_thread_fini(struct m0_thread *q)
93 {
94  M0_PRE(q->t_state == TS_PARKED);
95 
96  m0_semaphore_fini(&q->t_wait);
97  M0_SET0(q);
98 }
99 M0_EXPORTED(m0_thread_fini);
100 
101 M0_INTERNAL void *m0_thread_trampoline(void *arg)
102 {
103  struct m0_thread *t = arg;
104 
105  M0_PRE(t->t_state == TS_RUNNING);
106  M0_PRE(t->t_initrc == 0);
108  M0_PRE(t->t_tls.tls_self == t);
109 
112  if (t->t_init != NULL) {
113  t->t_initrc = t->t_init(t->t_arg);
115  }
116  if (t->t_initrc == 0)
117  t->t_func(t->t_arg);
119  return NULL;
120 }
121 
122 M0_INTERNAL struct m0_thread *m0_thread_self(void)
123 {
124  return m0_thread_tls()->tls_self;
125 }
126 
127 M0_INTERNAL int m0_thread_adopt(struct m0_thread *thread, struct m0 *instance)
128 {
129  M0_PRE(M0_IS0(thread));
130 
131  return m0_thread_arch_adopt(thread, instance, true);
132 }
133 
134 M0_INTERNAL void m0_thread_shun(void)
135 {
137 }
138 
141 /*
142  * Local variables:
143  * c-indentation-style: "K&R"
144  * c-basic-offset: 8
145  * tab-width: 8
146  * fill-column: 80
147  * scroll-step: 1
148  * End:
149  */
#define M0_PRE(cond)
M0_INTERNAL int m0_thread_init_impl(struct m0_thread *q, const char *name)
Definition: kthread.c:150
static struct m0_semaphore q
Definition: rwlock.c:55
#define NULL
Definition: misc.h:38
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
M0_INTERNAL void m0_set(struct m0 *instance)
Definition: instance.c:48
struct m0 * tls_m0_instance
Definition: thread.h:65
struct m0_thread_tls t_tls
Definition: thread.h:118
struct m0_semaphore t_wait
Definition: thread.h:116
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
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL struct m0_thread_tls * m0_thread_tls(void)
Definition: kthread.c:67
static struct m0_thread t[NR]
Definition: thread.c:45
M0_INTERNAL void m0_addb2_global_thread_leave(void)
Definition: global.c:58
M0_INTERNAL void * m0_thread_trampoline(void *arg)
Definition: thread.c:101
struct m0_thread thread
Definition: note.c:104
int m0_thread_init(struct m0_thread *q, int(*init)(void *), void(*func)(void *), void *arg, const char *namefmt,...)
Definition: thread.c:41
M0_INTERNAL void m0_addb2_global_thread_enter(void)
Definition: global.c:43
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
Definition: instance.h:80
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
M0_INTERNAL void m0_thread_shun(void)
Definition: thread.c:134
int(* t_init)(void *)
Definition: thread.h:113
int init(struct workload *w)
#define M0_IS0(obj)
Definition: misc.h:70
void(* t_func)(void *)
Definition: thread.h:114
M0_INTERNAL void m0_semaphore_fini(struct m0_semaphore *semaphore)
Definition: semaphore.c:45
M0_INTERNAL struct m0_thread * m0_thread_self(void)
Definition: thread.c:122
int t_initrc
Definition: thread.h:117
static struct m0 instance
Definition: main.c:78
void * t_arg
Definition: thread.h:115
#define M0_ASSERT_INFO(cond, fmt,...)
struct m0_thread * tls_self
Definition: thread.h:69
M0_INTERNAL void m0_semaphore_down(struct m0_semaphore *semaphore)
Definition: semaphore.c:49
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
M0_INTERNAL int m0_thread_arch_adopt(struct m0_thread *thread, struct m0 *instance, bool full)
Definition: kthread.c:300
M0_INTERNAL void m0_thread_arch_shun(void)
Definition: kthread.c:320
enum m0_thread_state t_state
Definition: thread.h:111