14#include "kmp_affinity.h"
21#include "kmp_wait_release.h"
22#include "kmp_wrapper_getpid.h"
24#if !KMP_OS_DRAGONFLY && !KMP_OS_FREEBSD && !KMP_OS_NETBSD && !KMP_OS_OPENBSD
31#include <sys/resource.h>
32#include <sys/syscall.h>
38#include <sys/sysinfo.h>
54#include <sys/sysctl.h>
55#elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD
57#include <sys/sysctl.h>
59#include <pthread_np.h>
60#elif KMP_OS_NETBSD || KMP_OS_OPENBSD
62#include <sys/sysctl.h>
70 struct timespec start;
74#define TS2NS(timespec) \
75 (((timespec).tv_sec * (long int)1e9) + (timespec).tv_nsec)
77static struct kmp_sys_timer __kmp_sys_timer_data;
80typedef void (*sig_func_t)(int);
81STATIC_EFI2_WORKAROUND
struct sigaction __kmp_sighldrs[NSIG];
82static sigset_t __kmp_sigset;
85static int __kmp_init_runtime = FALSE;
87static int __kmp_fork_count = 0;
89static pthread_condattr_t __kmp_suspend_cond_attr;
90static pthread_mutexattr_t __kmp_suspend_mutex_attr;
92static kmp_cond_align_t __kmp_wait_cv;
93static kmp_mutex_align_t __kmp_wait_mx;
95kmp_uint64 __kmp_ticks_per_msec = 1000000;
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);
105#if ((KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED)
109void __kmp_affinity_bind_thread(
int which) {
110 KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
111 "Illegal set affinity operation when not capable");
113 kmp_affin_mask_t *mask;
114 KMP_CPU_ALLOC_ON_STACK(mask);
116 KMP_CPU_SET(which, mask);
117 __kmp_set_system_affinity(mask, TRUE);
118 KMP_CPU_FREE_FROM_STACK(mask);
124void __kmp_affinity_determine_capable(
const char *env_var) {
128#define KMP_CPU_SET_SIZE_LIMIT (1024 * 1024)
129#define KMP_CPU_SET_TRY_SIZE CACHE_LINE
131#define KMP_CPU_SET_SIZE_LIMIT (sizeof(cpuset_t))
137 buf = (
unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT);
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",
146 if (gCode < 0 && errno != EINVAL) {
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))) {
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);
160 KMP_AFFINITY_DISABLE();
161 KMP_INTERNAL_FREE(buf);
163 }
else if (gCode > 0) {
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);
175 KA_TRACE(30, (
"__kmp_affinity_determine_capable: "
176 "searching for proper set size\n"));
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));
185 if (errno == ENOSYS) {
187 KA_TRACE(30, (
"__kmp_affinity_determine_capable: "
188 "inconsistent OS call behavior: errno == ENOSYS for mask "
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))) {
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);
204 KMP_AFFINITY_DISABLE();
205 KMP_INTERNAL_FREE(buf);
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);
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",
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);
236 KMP_INTERNAL_FREE(buf);
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);
254int __kmp_futex_determine_capable() {
256 long rc = syscall(__NR_futex, &loc, FUTEX_WAKE, 1, NULL, NULL, 0);
257 int retval = (rc == 0) || (errno != ENOSYS);
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"));
269#if (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (!KMP_ASM_INTRINS)
273kmp_int8 __kmp_test_then_or8(
volatile kmp_int8 *p, kmp_int8 d) {
274 kmp_int8 old_value, new_value;
276 old_value = TCR_1(*p);
277 new_value = old_value | d;
279 while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
281 old_value = TCR_1(*p);
282 new_value = old_value | d;
287kmp_int8 __kmp_test_then_and8(
volatile kmp_int8 *p, kmp_int8 d) {
288 kmp_int8 old_value, new_value;
290 old_value = TCR_1(*p);
291 new_value = old_value & d;
293 while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
295 old_value = TCR_1(*p);
296 new_value = old_value & d;
301kmp_uint32 __kmp_test_then_or32(
volatile kmp_uint32 *p, kmp_uint32 d) {
302 kmp_uint32 old_value, new_value;
304 old_value = TCR_4(*p);
305 new_value = old_value | d;
307 while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
309 old_value = TCR_4(*p);
310 new_value = old_value | d;
315kmp_uint32 __kmp_test_then_and32(
volatile kmp_uint32 *p, kmp_uint32 d) {
316 kmp_uint32 old_value, new_value;
318 old_value = TCR_4(*p);
319 new_value = old_value & d;
321 while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
323 old_value = TCR_4(*p);
324 new_value = old_value & d;
330kmp_int8 __kmp_test_then_add8(
volatile kmp_int8 *p, kmp_int8 d) {
331 kmp_int8 old_value, new_value;
333 old_value = TCR_1(*p);
334 new_value = old_value + d;
336 while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
338 old_value = TCR_1(*p);
339 new_value = old_value + d;
344kmp_int64 __kmp_test_then_add64(
volatile kmp_int64 *p, kmp_int64 d) {
345 kmp_int64 old_value, new_value;
347 old_value = TCR_8(*p);
348 new_value = old_value + d;
350 while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
352 old_value = TCR_8(*p);
353 new_value = old_value + d;
359kmp_uint64 __kmp_test_then_or64(
volatile kmp_uint64 *p, kmp_uint64 d) {
360 kmp_uint64 old_value, new_value;
362 old_value = TCR_8(*p);
363 new_value = old_value | d;
364 while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
366 old_value = TCR_8(*p);
367 new_value = old_value | d;
372kmp_uint64 __kmp_test_then_and64(
volatile kmp_uint64 *p, kmp_uint64 d) {
373 kmp_uint64 old_value, new_value;
375 old_value = TCR_8(*p);
376 new_value = old_value & d;
377 while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
379 old_value = TCR_8(*p);
380 new_value = old_value & d;
387void __kmp_terminate_thread(
int gtid) {
389 kmp_info_t *th = __kmp_threads[gtid];
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),
409static kmp_int32 __kmp_set_stack_info(
int gtid, kmp_info_t *th) {
411#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
421 if (!KMP_UBER_GTID(gtid)) {
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);
430 status = pthread_getattr_np(pthread_self(), &attr);
431 KMP_CHECK_SYSFAIL(
"pthread_getattr_np", status);
433 status = pthread_attr_getstack(&attr, &addr, &size);
434 KMP_CHECK_SYSFAIL(
"pthread_attr_getstack", status);
436 (
"__kmp_set_stack_info: T#%d pthread_attr_getstack returned size:"
437 " %lu, low addr: %p\n",
439 status = pthread_attr_destroy(&attr);
440 KMP_CHECK_SYSFAIL(
"pthread_attr_destroy", status);
443 if (size != 0 && addr != 0) {
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);
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);