1 1.6 christos /* $NetBSD: os.c,v 1.6 2026/04/08 00:16:15 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.1 christos * SPDX-License-Identifier: MPL-2.0 7 1.1 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.6 christos #include <ctype.h> 17 1.1 christos #include <inttypes.h> 18 1.1 christos #include <sys/stat.h> 19 1.6 christos #include <sys/utsname.h> 20 1.1 christos 21 1.1 christos #include <isc/os.h> 22 1.6 christos #include <isc/string.h> 23 1.1 christos #include <isc/types.h> 24 1.1 christos #include <isc/util.h> 25 1.1 christos 26 1.1 christos #include "os_p.h" 27 1.1 christos 28 1.1 christos static unsigned int isc__os_ncpus = 0; 29 1.1 christos static unsigned long isc__os_cacheline = ISC_OS_CACHELINE_SIZE; 30 1.1 christos static mode_t isc__os_umask = 0; 31 1.6 christos static int kernel_major = -1, kernel_minor = -1, kernel_patch = -1; 32 1.6 christos static char kernel_name[64]; 33 1.1 christos 34 1.1 christos #ifdef HAVE_SYSCONF 35 1.1 christos 36 1.1 christos #include <unistd.h> 37 1.1 christos 38 1.1 christos static long 39 1.1 christos sysconf_ncpus(void) { 40 1.1 christos #if defined(_SC_NPROCESSORS_ONLN) 41 1.4 christos return sysconf(_SC_NPROCESSORS_ONLN); 42 1.1 christos #elif defined(_SC_NPROC_ONLN) 43 1.4 christos return sysconf(_SC_NPROC_ONLN); 44 1.1 christos #else /* if defined(_SC_NPROCESSORS_ONLN) */ 45 1.4 christos return 0; 46 1.1 christos #endif /* if defined(_SC_NPROCESSORS_ONLN) */ 47 1.1 christos } 48 1.1 christos #endif /* HAVE_SYSCONF */ 49 1.1 christos 50 1.1 christos #if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME) 51 1.1 christos #include <sys/param.h> /* for NetBSD */ 52 1.1 christos #include <sys/sysctl.h> 53 1.1 christos #include <sys/types.h> /* for FreeBSD */ 54 1.1 christos 55 1.1 christos static int 56 1.1 christos sysctl_ncpus(void) { 57 1.1 christos int ncpu, result; 58 1.1 christos size_t len; 59 1.1 christos 60 1.1 christos len = sizeof(ncpu); 61 1.1 christos result = sysctlbyname("hw.ncpu", &ncpu, &len, 0, 0); 62 1.1 christos if (result != -1) { 63 1.4 christos return ncpu; 64 1.1 christos } 65 1.4 christos return 0; 66 1.1 christos } 67 1.1 christos #endif /* if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME) */ 68 1.1 christos 69 1.3 christos #if defined(HAVE_SCHED_GETAFFINITY) 70 1.3 christos 71 1.3 christos #if defined(HAVE_SCHED_H) 72 1.3 christos #include <sched.h> 73 1.3 christos #endif 74 1.3 christos 75 1.3 christos /* 76 1.3 christos * Administrators may wish to constrain the set of cores that BIND runs 77 1.3 christos * on via the 'taskset' or 'numactl' programs (or equivalent on other 78 1.3 christos * O/S), for example to achieve higher (or more stable) performance by 79 1.3 christos * more closely associating threads with individual NIC rx queues. If 80 1.3 christos * the admin has used taskset, it follows that BIND ought to 81 1.3 christos * automatically use the given number of CPUs rather than the system 82 1.3 christos * wide count. 83 1.3 christos */ 84 1.3 christos static int 85 1.3 christos sched_affinity_ncpus(void) { 86 1.3 christos cpu_set_t cpus; 87 1.3 christos int result; 88 1.3 christos 89 1.3 christos result = sched_getaffinity(0, sizeof(cpus), &cpus); 90 1.3 christos if (result != -1) { 91 1.3 christos #ifdef CPU_COUNT 92 1.4 christos return CPU_COUNT(&cpus); 93 1.3 christos #else 94 1.3 christos int i, n = 0; 95 1.3 christos 96 1.3 christos for (i = 0; i < CPU_SETSIZE; ++i) { 97 1.5 christos if (CPU_ISSET(i, &cpus)) { 98 1.3 christos ++n; 99 1.5 christos } 100 1.3 christos } 101 1.4 christos return n; 102 1.3 christos #endif 103 1.3 christos } 104 1.4 christos return 0; 105 1.3 christos } 106 1.3 christos #endif 107 1.3 christos 108 1.3 christos /* 109 1.3 christos * Affinity detecting variant of sched_affinity_cpus() for FreeBSD 110 1.3 christos */ 111 1.3 christos 112 1.3 christos #if defined(HAVE_SYS_CPUSET_H) && defined(HAVE_CPUSET_GETAFFINITY) 113 1.3 christos #include <sys/cpuset.h> 114 1.3 christos #include <sys/param.h> 115 1.3 christos 116 1.3 christos static int 117 1.3 christos cpuset_affinity_ncpus(void) { 118 1.3 christos cpuset_t cpus; 119 1.3 christos int result; 120 1.3 christos 121 1.3 christos result = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, 122 1.3 christos sizeof(cpus), &cpus); 123 1.3 christos if (result != -1) { 124 1.3 christos int i, n = 0; 125 1.3 christos for (i = 0; i < CPU_SETSIZE; ++i) { 126 1.5 christos if (CPU_ISSET(i, &cpus)) { 127 1.3 christos ++n; 128 1.5 christos } 129 1.3 christos } 130 1.4 christos return n; 131 1.3 christos } 132 1.4 christos return 0; 133 1.3 christos } 134 1.3 christos #endif 135 1.3 christos 136 1.1 christos static void 137 1.1 christos ncpus_initialize(void) { 138 1.3 christos #if defined(HAVE_SYS_CPUSET_H) && defined(HAVE_CPUSET_GETAFFINITY) 139 1.3 christos if (isc__os_ncpus <= 0) { 140 1.3 christos isc__os_ncpus = cpuset_affinity_ncpus(); 141 1.3 christos } 142 1.3 christos #endif 143 1.3 christos #if defined(HAVE_SCHED_GETAFFINITY) 144 1.3 christos if (isc__os_ncpus <= 0) { 145 1.3 christos isc__os_ncpus = sched_affinity_ncpus(); 146 1.3 christos } 147 1.3 christos #endif 148 1.1 christos #if defined(HAVE_SYSCONF) 149 1.3 christos if (isc__os_ncpus <= 0) { 150 1.3 christos isc__os_ncpus = sysconf_ncpus(); 151 1.3 christos } 152 1.1 christos #endif /* if defined(HAVE_SYSCONF) */ 153 1.1 christos #if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME) 154 1.1 christos if (isc__os_ncpus <= 0) { 155 1.1 christos isc__os_ncpus = sysctl_ncpus(); 156 1.1 christos } 157 1.1 christos #endif /* if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME) */ 158 1.3 christos if (isc__os_ncpus <= 0) { 159 1.1 christos isc__os_ncpus = 1; 160 1.1 christos } 161 1.1 christos } 162 1.1 christos 163 1.1 christos static void 164 1.1 christos umask_initialize(void) { 165 1.1 christos isc__os_umask = umask(0); 166 1.1 christos (void)umask(isc__os_umask); 167 1.1 christos } 168 1.1 christos 169 1.6 christos static void 170 1.6 christos kernel_initialize(void) { 171 1.6 christos struct utsname buffer; 172 1.6 christos 173 1.6 christos if (uname(&buffer) == -1) { 174 1.6 christos return; 175 1.6 christos } 176 1.6 christos 177 1.6 christos (void)sscanf(buffer.release, "%d.%d.%d", &kernel_major, &kernel_minor, 178 1.6 christos &kernel_patch); 179 1.6 christos (void)strlcpy(kernel_name, buffer.sysname, sizeof(kernel_name)); 180 1.6 christos } 181 1.6 christos 182 1.1 christos unsigned int 183 1.1 christos isc_os_ncpus(void) { 184 1.4 christos return isc__os_ncpus; 185 1.1 christos } 186 1.1 christos 187 1.1 christos unsigned long 188 1.1 christos isc_os_cacheline(void) { 189 1.4 christos return isc__os_cacheline; 190 1.1 christos } 191 1.1 christos 192 1.1 christos mode_t 193 1.1 christos isc_os_umask(void) { 194 1.4 christos return isc__os_umask; 195 1.1 christos } 196 1.1 christos 197 1.1 christos void 198 1.6 christos isc_os_kernel(char **name, int *major, int *minor, int *patch) { 199 1.6 christos SET_IF_NOT_NULL(name, kernel_name) 200 1.6 christos SET_IF_NOT_NULL(major, kernel_major); 201 1.6 christos SET_IF_NOT_NULL(minor, kernel_minor); 202 1.6 christos SET_IF_NOT_NULL(patch, kernel_patch); 203 1.6 christos } 204 1.6 christos 205 1.6 christos void 206 1.1 christos isc__os_initialize(void) { 207 1.1 christos umask_initialize(); 208 1.1 christos ncpus_initialize(); 209 1.6 christos kernel_initialize(); 210 1.1 christos #if defined(HAVE_SYSCONF) && defined(_SC_LEVEL1_DCACHE_LINESIZE) 211 1.1 christos long s = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); 212 1.1 christos if (s > 0 && (unsigned long)s > isc__os_cacheline) { 213 1.1 christos isc__os_cacheline = s; 214 1.1 christos } 215 1.1 christos #endif 216 1.1 christos } 217 1.1 christos 218 1.1 christos void 219 1.1 christos isc__os_shutdown(void) { 220 1.1 christos /* empty, but defined for completeness */; 221 1.1 christos } 222