1 /* $NetBSD: thread.c,v 1.1 2024/02/18 20:57:56 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #if defined(HAVE_SCHED_H) 19 #include <sched.h> 20 #endif /* if defined(HAVE_SCHED_H) */ 21 22 #if defined(HAVE_CPUSET_H) 23 #include <sys/cpuset.h> 24 #include <sys/param.h> 25 #endif /* if defined(HAVE_CPUSET_H) */ 26 27 #if defined(HAVE_SYS_PROCSET_H) 28 #include <sys/processor.h> 29 #include <sys/procset.h> 30 #include <sys/types.h> 31 #endif /* if defined(HAVE_SYS_PROCSET_H) */ 32 33 #include <isc/strerr.h> 34 #include <isc/thread.h> 35 #include <isc/util.h> 36 37 #include "trampoline_p.h" 38 39 #ifndef THREAD_MINSTACKSIZE 40 #define THREAD_MINSTACKSIZE (1024U * 1024) 41 #endif /* ifndef THREAD_MINSTACKSIZE */ 42 43 #define _FATAL(r, f) \ 44 { \ 45 char strbuf[ISC_STRERRORSIZE]; \ 46 strerror_r(r, strbuf, sizeof(strbuf)); \ 47 isc_error_fatal(__FILE__, __LINE__, f " failed: %s", strbuf); \ 48 } 49 50 void 51 isc_thread_create(isc_threadfunc_t func, isc_threadarg_t arg, 52 isc_thread_t *thread) { 53 pthread_attr_t attr; 54 isc__trampoline_t *trampoline_arg; 55 56 trampoline_arg = isc__trampoline_get(func, arg); 57 58 #if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \ 59 defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) 60 size_t stacksize; 61 #endif /* if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \ 62 * defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) */ 63 int ret; 64 65 pthread_attr_init(&attr); 66 67 #if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \ 68 defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) 69 ret = pthread_attr_getstacksize(&attr, &stacksize); 70 if (ret != 0) { 71 _FATAL(ret, "pthread_attr_getstacksize()"); 72 } 73 74 if (stacksize < THREAD_MINSTACKSIZE) { 75 ret = pthread_attr_setstacksize(&attr, THREAD_MINSTACKSIZE); 76 if (ret != 0) { 77 _FATAL(ret, "pthread_attr_setstacksize()"); 78 } 79 } 80 #endif /* if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \ 81 * defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) */ 82 83 ret = pthread_create(thread, &attr, isc__trampoline_run, 84 trampoline_arg); 85 if (ret != 0) { 86 _FATAL(ret, "pthread_create()"); 87 } 88 89 pthread_attr_destroy(&attr); 90 91 return; 92 } 93 94 void 95 isc_thread_join(isc_thread_t thread, isc_threadresult_t *result) { 96 int ret = pthread_join(thread, result); 97 if (ret != 0) { 98 _FATAL(ret, "pthread_join()"); 99 } 100 } 101 102 void 103 isc_thread_setname(isc_thread_t thread, const char *name) { 104 #if defined(HAVE_PTHREAD_SETNAME_NP) && !defined(__APPLE__) 105 /* 106 * macOS has pthread_setname_np but only works on the 107 * current thread so it's not used here 108 */ 109 #if defined(__NetBSD__) 110 (void)pthread_setname_np(thread, name, NULL); 111 #else /* if defined(__NetBSD__) */ 112 (void)pthread_setname_np(thread, name); 113 #endif /* if defined(__NetBSD__) */ 114 #elif defined(HAVE_PTHREAD_SET_NAME_NP) 115 (void)pthread_set_name_np(thread, name); 116 #else /* if defined(HAVE_PTHREAD_SETNAME_NP) && !defined(__APPLE__) */ 117 UNUSED(thread); 118 UNUSED(name); 119 #endif /* if defined(HAVE_PTHREAD_SETNAME_NP) && !defined(__APPLE__) */ 120 } 121 122 void 123 isc_thread_yield(void) { 124 #if defined(HAVE_SCHED_YIELD) 125 sched_yield(); 126 #elif defined(HAVE_PTHREAD_YIELD) 127 pthread_yield(); 128 #elif defined(HAVE_PTHREAD_YIELD_NP) 129 pthread_yield_np(); 130 #endif /* if defined(HAVE_SCHED_YIELD) */ 131 } 132