LLVM OpenMP* Runtime Library
z_Linux_util.cpp
1/*
2 * z_Linux_util.cpp -- platform specific routines.
3 */
4
5//===----------------------------------------------------------------------===//
6//
7// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8// See https://llvm.org/LICENSE.txt for license information.
9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10//
11//===----------------------------------------------------------------------===//
12
13#include "kmp.h"
14#include "kmp_affinity.h"
15#include "kmp_i18n.h"
16#include "kmp_io.h"
17#include "kmp_itt.h"
18#include "kmp_lock.h"
19#include "kmp_stats.h"
20#include "kmp_str.h"
21#include "kmp_wait_release.h"
22#include "kmp_wrapper_getpid.h"
23
24#if !KMP_OS_DRAGONFLY && !KMP_OS_FREEBSD && !KMP_OS_NETBSD && !KMP_OS_OPENBSD
25#include <alloca.h>
26#endif
27#include <math.h> // HUGE_VAL.
28#if KMP_OS_LINUX
29#include <semaphore.h>
30#endif // KMP_OS_LINUX
31#include <sys/resource.h>
32#include <sys/syscall.h>
33#include <sys/time.h>
34#include <sys/times.h>
35#include <unistd.h>
36
37#if KMP_OS_LINUX
38#include <sys/sysinfo.h>
39#if KMP_USE_FUTEX
40// We should really include <futex.h>, but that causes compatibility problems on
41// different Linux* OS distributions that either require that you include (or
42// break when you try to include) <pci/types.h>. Since all we need is the two
43// macros below (which are part of the kernel ABI, so can't change) we just
44// define the constants here and don't include <futex.h>
45#ifndef FUTEX_WAIT
46#define FUTEX_WAIT 0
47#endif
48#ifndef FUTEX_WAKE
49#define FUTEX_WAKE 1
50#endif
51#endif
52#elif KMP_OS_DARWIN
53#include <mach/mach.h>
54#include <sys/sysctl.h>
55#elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD
56#include <sys/types.h>
57#include <sys/sysctl.h>
58#include <sys/user.h>
59#include <pthread_np.h>
60#elif KMP_OS_NETBSD || KMP_OS_OPENBSD
61#include <sys/types.h>
62#include <sys/sysctl.h>
63#endif
64
65#include <ctype.h>
66#include <dirent.h>
67#include <fcntl.h>
68
69struct kmp_sys_timer {
70 struct timespec start;
71};
72
73// Convert timespec to nanoseconds.
74#define TS2NS(timespec) \
75 (((timespec).tv_sec * (long int)1e9) + (timespec).tv_nsec)
76
77static struct kmp_sys_timer __kmp_sys_timer_data;
78
79#if KMP_HANDLE_SIGNALS
80typedef void (*sig_func_t)(int);
81STATIC_EFI2_WORKAROUND struct sigaction __kmp_sighldrs[NSIG];
82static sigset_t __kmp_sigset;
83#endif
84
85static int __kmp_init_runtime = FALSE;
86
87static int __kmp_fork_count = 0;
88
89static pthread_condattr_t __kmp_suspend_cond_attr;
90static pthread_mutexattr_t __kmp_suspend_mutex_attr;
91
92static kmp_cond_align_t __kmp_wait_cv;
93static kmp_mutex_align_t __kmp_wait_mx;
94
95kmp_uint64 __kmp_ticks_per_msec = 1000000;
96
97#ifdef DEBUG_SUSPEND
98static void __kmp_print_cond(char *buffer, kmp_cond_align_t *cond) {
99 KMP_SNPRINTF(buffer, 128, "(cond (lock (%ld, %d)), (descr (%p)))",
100 cond->c_cond.__c_lock.__status, cond->c_cond.__c_lock.__spinlock,
101 cond->c_cond.__c_waiting);
102}
103#endif
104
105#if ((KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED)
106
107/* Affinity support */
108
109void __kmp_affinity_bind_thread(int which) {
110 KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
111 "Illegal set affinity operation when not capable");
112
113 kmp_affin_mask_t *mask;
114 KMP_CPU_ALLOC_ON_STACK(mask);
115 KMP_CPU_ZERO(mask);
116 KMP_CPU_SET(which, mask);
117 __kmp_set_system_affinity(mask, TRUE);
118 KMP_CPU_FREE_FROM_STACK(mask);
119}
120
121/* Determine if we can access affinity functionality on this version of
122 * Linux* OS by checking __NR_sched_{get,set}affinity system calls, and set
123 * __kmp_affin_mask_size to the appropriate value (0 means not capable). */
124void __kmp_affinity_determine_capable(const char *env_var) {
125 // Check and see if the OS supports thread affinity.
126
127#if KMP_OS_LINUX
128#define KMP_CPU_SET_SIZE_LIMIT (1024 * 1024)
129#define KMP_CPU_SET_TRY_SIZE CACHE_LINE
130#elif KMP_OS_FREEBSD
131#define KMP_CPU_SET_SIZE_LIMIT (sizeof(cpuset_t))
132#endif
133
134#if KMP_OS_LINUX
135 long gCode;
136 unsigned char *buf;
137 buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT);
138
139 // If the syscall returns a suggestion for the size,
140 // then we don't have to search for an appropriate size.
141 gCode = syscall(__NR_sched_getaffinity, 0, KMP_CPU_SET_TRY_SIZE, buf);
142 KA_TRACE(30, ("__kmp_affinity_determine_capable: "
143 "initial getaffinity call returned %ld errno = %d\n",
144 gCode, errno));
145
146 if (gCode < 0 && errno != EINVAL) {
147 // System call not supported
148 if (__kmp_affinity_verbose ||
149 (__kmp_affinity_warnings && (__kmp_affinity_type != affinity_none) &&
150 (__kmp_affinity_type != affinity_default) &&
151 (__kmp_affinity_type != affinity_disabled))) {
152 int error = errno;
153 kmp_msg_t err_code = KMP_ERR(error);
154 __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var),
155 err_code, __kmp_msg_null);
156 if (__kmp_generate_warnings == kmp_warnings_off) {
157 __kmp_str_free(&err_code.str);
158 }
159 }
160 KMP_AFFINITY_DISABLE();
161 KMP_INTERNAL_FREE(buf);
162 return;
163 } else if (gCode > 0) {
164 // The optimal situation: the OS returns the size of the buffer it expects.
165 KMP_AFFINITY_ENABLE(gCode);
166 KA_TRACE(10, ("__kmp_affinity_determine_capable: "
167 "affinity supported (mask size %d)\n",
168 (int)__kmp_affin_mask_size));
169 KMP_INTERNAL_FREE(buf);
170 return;
171 }
172
173 // Call the getaffinity system call repeatedly with increasing set sizes
174 // until we succeed, or reach an upper bound on the search.
175 KA_TRACE(30, ("__kmp_affinity_determine_capable: "
176 "searching for proper set size\n"));
177 int size;
178 for (size = 1; size <= KMP_CPU_SET_SIZE_LIMIT; size *= 2) {
179 gCode = syscall(__NR_sched_getaffinity, 0, size, buf);
180 KA_TRACE(30, ("__kmp_affinity_determine_capable: "
181 "getaffinity for mask size %ld returned %ld errno = %d\n",
182 size, gCode, errno));
183
184 if (gCode < 0) {
185 if (errno == ENOSYS) {
186 // We shouldn't get here
187 KA_TRACE(30, ("__kmp_affinity_determine_capable: "
188 "inconsistent OS call behavior: errno == ENOSYS for mask "
189 "size %d\n",
190 size));
191 if (__kmp_affinity_verbose ||
192 (__kmp_affinity_warnings &&
193 (__kmp_affinity_type != affinity_none) &&
194 (__kmp_affinity_type != affinity_default) &&
195 (__kmp_affinity_type != affinity_disabled))) {
196 int error = errno;
197 kmp_msg_t err_code = KMP_ERR(error);
198 __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var),
199 err_code, __kmp_msg_null);
200 if (__kmp_generate_warnings == kmp_warnings_off) {
201 __kmp_str_free(&err_code.str);
202 }
203 }
204 KMP_AFFINITY_DISABLE();
205 KMP_INTERNAL_FREE(buf);
206 return;
207 }
208 continue;
209 }
210
211 KMP_AFFINITY_ENABLE(gCode);
212 KA_TRACE(10, ("__kmp_affinity_determine_capable: "
213 "affinity supported (mask size %d)\n",
214 (int)__kmp_affin_mask_size));
215 KMP_INTERNAL_FREE(buf);
216 return;
217 }
218#elif KMP_OS_FREEBSD
219 long gCode;
220 unsigned char *buf;
221 buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT);
222 gCode = pthread_getaffinity_np(pthread_self(), KMP_CPU_SET_SIZE_LIMIT,
223 reinterpret_cast<cpuset_t *>(buf));
224 KA_TRACE(30, ("__kmp_affinity_determine_capable: "
225 "initial getaffinity call returned %d errno = %d\n",
226 gCode, errno));
227 if (gCode == 0) {
228 KMP_AFFINITY_ENABLE(KMP_CPU_SET_SIZE_LIMIT);
229 KA_TRACE(10, ("__kmp_affinity_determine_capable: "
230 "affinity supported (mask size %d)\n",
231 (int)__kmp_affin_mask_size));
232 KMP_INTERNAL_FREE(buf);
233 return;
234 }
235#endif
236 KMP_INTERNAL_FREE(buf);
237
238 // Affinity is not supported
239 KMP_AFFINITY_DISABLE();
240 KA_TRACE(10, ("__kmp_affinity_determine_capable: "
241 "cannot determine mask size - affinity not supported\n"));
242 if (__kmp_affinity_verbose ||
243 (__kmp_affinity_warnings && (__kmp_affinity_type != affinity_none) &&
244 (__kmp_affinity_type != affinity_default) &&
245 (__kmp_affinity_type != affinity_disabled))) {
246 KMP_WARNING(AffCantGetMaskSize, env_var);
247 }
248}
249
250#endif // KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED
251
252#if KMP_USE_FUTEX
253
254int __kmp_futex_determine_capable() {
255 int loc = 0;
256 long rc = syscall(__NR_futex, &loc, FUTEX_WAKE, 1, NULL, NULL, 0);
257 int retval = (rc == 0) || (errno != ENOSYS);
258
259 KA_TRACE(10,
260 ("__kmp_futex_determine_capable: rc = %d errno = %d\n", rc, errno));
261 KA_TRACE(10, ("__kmp_futex_determine_capable: futex syscall%s supported\n",
262 retval ? "" : " not"));
263
264 return retval;
265}
266
267#endif // KMP_USE_FUTEX
268
269#if (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (!KMP_ASM_INTRINS)
270/* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to
271 use compare_and_store for these routines */
272
273kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 d) {
274 kmp_int8 old_value, new_value;
275
276 old_value = TCR_1(*p);
277 new_value = old_value | d;
278
279 while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
280 KMP_CPU_PAUSE();
281 old_value = TCR_1(*p);
282 new_value = old_value | d;
283 }
284 return old_value;
285}
286
287kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 d) {
288 kmp_int8 old_value, new_value;
289
290 old_value = TCR_1(*p);
291 new_value = old_value & d;
292
293 while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
294 KMP_CPU_PAUSE();
295 old_value = TCR_1(*p);
296 new_value = old_value & d;
297 }
298 return old_value;
299}
300
301kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 d) {
302 kmp_uint32 old_value, new_value;
303
304 old_value = TCR_4(*p);
305 new_value = old_value | d;
306
307 while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
308 KMP_CPU_PAUSE();
309 old_value = TCR_4(*p);
310 new_value = old_value | d;
311 }
312 return old_value;
313}
314
315kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) {
316 kmp_uint32 old_value, new_value;
317
318 old_value = TCR_4(*p);
319 new_value = old_value & d;
320
321 while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
322 KMP_CPU_PAUSE();
323 old_value = TCR_4(*p);
324 new_value = old_value & d;
325 }
326 return old_value;
327}
328
329#if KMP_ARCH_X86
330kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) {
331 kmp_int8 old_value, new_value;
332
333 old_value = TCR_1(*p);
334 new_value = old_value + d;
335
336 while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
337 KMP_CPU_PAUSE();
338 old_value = TCR_1(*p);
339 new_value = old_value + d;
340 }
341 return old_value;
342}
343
344kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 d) {
345 kmp_int64 old_value, new_value;
346
347 old_value = TCR_8(*p);
348 new_value = old_value + d;
349
350 while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
351 KMP_CPU_PAUSE();
352 old_value = TCR_8(*p);
353 new_value = old_value + d;
354 }
355 return old_value;
356}
357#endif /* KMP_ARCH_X86 */
358
359kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 d) {
360 kmp_uint64 old_value, new_value;
361
362 old_value = TCR_8(*p);
363 new_value = old_value | d;
364 while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
365 KMP_CPU_PAUSE();
366 old_value = TCR_8(*p);
367 new_value = old_value | d;
368 }
369 return old_value;
370}
371
372kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) {
373 kmp_uint64 old_value, new_value;
374
375 old_value = TCR_8(*p);
376 new_value = old_value & d;
377 while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
378 KMP_CPU_PAUSE();
379 old_value = TCR_8(*p);
380 new_value = old_value & d;
381 }
382 return old_value;
383}
384
385#endif /* (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (! KMP_ASM_INTRINS) */
386
387void __kmp_terminate_thread(int gtid) {
388 int status;
389 kmp_info_t *th = __kmp_threads[gtid];
390
391 if (!th)
392 return;
393
394#ifdef KMP_CANCEL_THREADS
395 KA_TRACE(10, ("__kmp_terminate_thread: kill (%d)\n", gtid));
396 status = pthread_cancel(th->th.th_info.ds.ds_thread);
397 if (status != 0 && status != ESRCH) {
398 __kmp_fatal(KMP_MSG(CantTerminateWorkerThread), KMP_ERR(status),
399 __kmp_msg_null);
400 }
401#endif
402 KMP_YIELD(TRUE);
403} //
404
405/* Set thread stack info according to values returned by pthread_getattr_np().
406 If values are unreasonable, assume call failed and use incremental stack
407 refinement method instead. Returns TRUE if the stack parameters could be
408 determined exactly, FALSE if incremental refinement is necessary. */
409static kmp_int32 __kmp_set_stack_info(int gtid, kmp_info_t *th) {
410 int stack_data;
411#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
412 KMP_OS_HURD
413 pthread_attr_t attr;
414 int status;
415 size_t size = 0;
416 void *addr = 0;
417
418 /* Always do incremental stack refinement for ubermaster threads since the
419 initial thread stack range can be reduced by sibling thread creation so
420 pthread_attr_getstack may cause thread gtid aliasing */
421 if (!KMP_UBER_GTID(gtid)) {
422
423 /* Fetch the real thread attributes */
424 status = pthread_attr_init(&attr);
425 KMP_CHECK_SYSFAIL("pthread_attr_init", status);
426#if KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD
427 status = pthread_attr_get_np(pthread_self(), &attr);
428 KMP_CHECK_SYSFAIL("pthread_attr_get_np", status);
429#else
430 status = pthread_getattr_np(pthread_self(), &attr);
431 KMP_CHECK_SYSFAIL("pthread_getattr_np", status);
432#endif
433 status = pthread_attr_getstack(&attr, &addr, &size);
434 KMP_CHECK_SYSFAIL("pthread_attr_getstack", status);
435 KA_TRACE(60,
436 ("__kmp_set_stack_info: T#%d pthread_attr_getstack returned size:"
437 " %lu, low addr: %p\n",
438 gtid, size, addr));
439 status = pthread_attr_destroy(&attr);
440 KMP_CHECK_SYSFAIL("pthread_attr_destroy", status);
441 }
442
443 if (size != 0 && addr != 0) { // was stack parameter determination successful?
444 /* Store the correct base and size */
445 TCW_PTR(th->th.th_info.ds.ds_stackbase, (((char *)addr) + size));
446 TCW_PTR(th->th.th_info.ds.ds_stacksize, size);
447 TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
448 return TRUE;
449 }
450#endif /* KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD \
451 || KMP_OS_HURD */
452 /* Use incremental refinement starting from initial conservative estimate */
453 TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
454 TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data);
455 TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
456 return FALSE;
457}
458