Motr  M0
uthread.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 #include <stdlib.h> /* getenv */
24 #include <unistd.h> /* getpid */
25 #include <errno.h> /* program_invocation_name */
26 #include <stdio.h> /* snprinf */
27 #include <linux/limits.h>/* PATH_MAX */
28 
29 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_MEMORY
30 #include "lib/trace.h"
31 #include "lib/misc.h" /* M0_SET0 */
32 #include "lib/string.h" /* m0_strdup */
33 #include "lib/memory.h"
34 #include "lib/errno.h"
35 #include "lib/thread.h"
36 #include "lib/arith.h"
37 #include "lib/bitmap.h"
38 #include "lib/assert.h"
39 #include "module/instance.h" /* m0_set */
40 #include "addb2/global.h" /* m0_addb2_global_thread_enter */
41 
63 static pthread_attr_t pthread_attr_default;
64 
65 static __thread struct m0_thread thread = {};
66 static __thread struct m0_thread_tls *tls = NULL;
67 
68 static struct m0_thread main_thread = {
70  .t_tls = {
71  .tls_self = &main_thread
72  },
73  .t_namebuf = "main()"
74 };
75 
76 M0_INTERNAL struct m0_thread_tls *m0_thread_tls(void)
77 {
78  if (tls == NULL) {
79  thread = (struct m0_thread) {
81  .t_tls = {
82  .tls_m0_instance =
84  .tls_self = &thread,
85  },
86  .t_namebuf = "anon"
87  };
88  tls = &thread.t_tls;
89  }
90  return tls;
91 }
92 
93 static void *uthread_trampoline(void *arg)
94 {
95  struct m0_thread *t = arg;
96 
97  tls = &t->t_tls;
99  tls = NULL;
100  return NULL;
101 }
102 
103 M0_INTERNAL int m0_thread_init_impl(struct m0_thread *q, const char *_)
104 {
105  M0_PRE(q->t_state == TS_RUNNING);
106 
107  return -pthread_create(&q->t_h.h_id, &pthread_attr_default,
109 }
110 
112 {
113  int result;
114 
115  M0_PRE(q->t_state == TS_RUNNING);
116  M0_PRE(!pthread_equal(q->t_h.h_id, pthread_self()));
117 
118  result = -pthread_join(q->t_h.h_id, NULL);
119  if (result == 0)
120  q->t_state = TS_PARKED;
121  return result;
122 }
123 
124 M0_INTERNAL int m0_thread_signal(struct m0_thread *q, int sig)
125 {
126  return -pthread_kill(q->t_h.h_id, sig);
127 }
128 
129 M0_INTERNAL int m0_thread_confine(struct m0_thread *q,
130  const struct m0_bitmap *processors)
131 {
132  size_t idx;
133  size_t nr_bits = min64u(processors->b_nr, CPU_SETSIZE);
134  cpu_set_t cpuset;
135 
136  CPU_ZERO(&cpuset);
137 
138  for (idx = 0; idx < nr_bits; ++idx) {
139  if (m0_bitmap_get(processors, idx))
140  CPU_SET(idx, &cpuset);
141  }
142 
143  return -pthread_setaffinity_np(q->t_h.h_id, sizeof cpuset, &cpuset);
144 }
145 
146 M0_INTERNAL char m0_argv0[PATH_MAX] = {};
147 
148 M0_INTERNAL char *m0_debugger_args[4] = {
149  NULL, /* debugger name */
150  NULL, /* our binary name */
151  NULL, /* our process id */
152  NULL
153 };
154 
155 M0_INTERNAL int m0_threads_init(struct m0 *instance)
156 {
157  m0_set(instance);
158  return -pthread_attr_init(&pthread_attr_default) ?:
159  -pthread_attr_setdetachstate(&pthread_attr_default,
160  PTHREAD_CREATE_JOINABLE);
161 }
162 
163 M0_INTERNAL void m0_threads_fini(void)
164 {
165  (void)pthread_attr_destroy(&pthread_attr_default);
166 }
167 
168 M0_INTERNAL int m0_threads_once_init(void)
169 {
170  static char pidbuf[20];
171  char *env_ptr;
172 
173  if (readlink("/proc/self/exe", m0_argv0, sizeof m0_argv0) == -1)
174  return M0_ERR_INFO(errno, "%s", strerror(errno));
175 
176  env_ptr = getenv("M0_DEBUGGER");
177  if (env_ptr != NULL)
178  m0_debugger_args[0] = m0_strdup(env_ptr);
179  /*
180  * Note: program_invocation_name requires _GNU_SOURCE.
181  */
182  m0_debugger_args[1] = program_invocation_name;
183  m0_debugger_args[2] = pidbuf;
184  (void)snprintf(pidbuf, ARRAY_SIZE(pidbuf), "%i", getpid());
185  tls = &main_thread.t_tls;
186  return 0;
187 }
188 
189 M0_INTERNAL void m0_threads_once_fini(void)
190 {
192 }
193 
194 M0_INTERNAL void m0_enter_awkward(void)
195 {
196  struct m0_thread_tls *tls = m0_thread_tls();
197 
198  /*
199  * m0_enter_awkward() can be called at arbitrary moment. It is possible
200  * that TLS is not yet set (or already released) at this time (this
201  * happens, for example, when a timer signal) arrives to a thread
202  * executing glibc code, creating or destroying a thread.
203  */
204  if (tls != NULL)
206 }
207 
208 M0_INTERNAL void m0_exit_awkward(void)
209 {
210  struct m0_thread_tls *tls = m0_thread_tls();
211 
212  if (tls != NULL)
214 }
215 
216 M0_INTERNAL bool m0_is_awkward(void)
217 {
218  return m0_thread_tls()->tls_arch.tat_awkward != 0;
219 }
220 
221 M0_INTERNAL uint64_t m0_pid(void)
222 {
223  return getpid();
224 }
225 
226 M0_INTERNAL uint64_t m0_process(void)
227 {
228  return m0_pid();
229 }
230 
231 M0_INTERNAL int m0_thread_arch_adopt(struct m0_thread *thread,
232  struct m0 *instance, bool full)
233 {
234  M0_PRE(M0_IS0(thread));
235 
237  tls = &thread->t_tls;
238  m0_set(instance);
239  if (full)
241  return 0;
242 }
243 
244 M0_INTERNAL void m0_thread_arch_shun(void)
245 {
247  tls = NULL;
248 }
249 
250 #undef M0_TRACE_SUBSYSTEM
251 
254 /*
255  * Local variables:
256  * c-indentation-style: "K&R"
257  * c-basic-offset: 8
258  * tab-width: 8
259  * fill-column: 80
260  * scroll-step: 1
261  * End:
262  */
M0_INTERNAL void m0_enter_awkward(void)
Definition: kthread.c:249
M0_INTERNAL uint64_t m0_process(void)
Definition: kthread.c:295
M0_INTERNAL char m0_argv0[PATH_MAX]
Definition: uthread.c:146
#define M0_PRE(cond)
M0_INTERNAL int m0_thread_init_impl(struct m0_thread *q, const char *name)
Definition: kthread.c:150
#define m0_strdup(s)
Definition: string.h:43
M0_INTERNAL char * m0_debugger_args[4]
Definition: uthread.c:148
static struct m0_semaphore q
Definition: rwlock.c:55
#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
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
M0_INTERNAL void m0_threads_fini(void)
Definition: kthread.c:85
M0_INTERNAL void m0_set(struct m0 *instance)
Definition: instance.c:48
static void full(void)
Definition: base.c:334
struct m0 * tls_m0_instance
Definition: thread.h:65
struct m0_thread_tls t_tls
Definition: thread.h:118
static pthread_attr_t pthread_attr_default
Definition: uthread.c:63
M0_INTERNAL struct m0_thread_tls * m0_thread_tls(void)
Definition: kthread.c:67
struct m0_thread_arch_tls tls_arch
Definition: thread.h:67
#define M0_ERR_INFO(rc, fmt,...)
Definition: trace.h:215
M0_INTERNAL void m0_addb2_global_thread_leave(void)
Definition: global.c:58
static void * uthread_trampoline(void *arg)
Definition: uthread.c:93
#define m0_free0(pptr)
Definition: memory.h:77
M0_INTERNAL int m0_thread_signal(struct m0_thread *q, int sig)
Definition: kthread.c:192
M0_INTERNAL void * m0_thread_trampoline(void *arg)
Definition: thread.c:101
static struct m0_thread main_thread
Definition: uthread.c:68
static struct m0_thread t[8]
Definition: service_ut.c:1230
M0_INTERNAL void m0_addb2_global_thread_enter(void)
Definition: global.c:43
uint32_t tat_awkward
Definition: thread.h:55
Definition: instance.h:80
M0_INTERNAL void m0_threads_once_fini(void)
Definition: kthread.c:94
M0_INTERNAL bool m0_is_awkward(void)
Definition: kthread.c:269
static __thread struct m0_thread_tls * tls
Definition: uthread.c:66
static uint64_t min64u(uint64_t a, uint64_t b)
Definition: arith.h:66
static __thread struct m0_thread thread
Definition: uthread.c:65
#define M0_CNT_INC(cnt)
Definition: arith.h:226
#define M0_IS0(obj)
Definition: misc.h:70
M0_INTERNAL bool m0_bitmap_get(const struct m0_bitmap *map, size_t idx)
Definition: bitmap.c:105
M0_INTERNAL int m0_threads_once_init(void)
Definition: kthread.c:89
static struct m0 instance
Definition: main.c:78
#define M0_CNT_DEC(cnt)
Definition: arith.h:219
struct m0_thread * tls_self
Definition: thread.h:69
M0_INTERNAL void m0_exit_awkward(void)
Definition: kthread.c:262
M0_INTERNAL uint64_t m0_pid(void)
Definition: kthread.c:290
size_t b_nr
Definition: bitmap.h:44
char t_namebuf[M0_THREAD_NAME_LEN]
Definition: thread.h:119
M0_INTERNAL int m0_threads_init(struct m0 *instance)
Definition: kthread.c:77
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
#define ARRAY_SIZE(a)
Definition: misc.h:45
enum m0_thread_state t_state
Definition: thread.h:111