1 /******************************************************************************* 2 3 Functions to set a process' CPU affinity. 4 5 This module uses the GNU API and contains declarations and functionality 6 found in <sched.h> on GNU/Linux. See 7 http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html 8 9 Copyright: 10 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 11 All rights reserved. 12 13 License: 14 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 15 Alternatively, this file may be distributed under the terms of the Tango 16 3-Clause BSD License (see LICENSE_BSD.txt for details). 17 18 *******************************************************************************/ 19 20 module ocean.sys.CpuAffinity; 21 22 23 24 25 import ocean.transition; 26 27 import ocean.stdc.posix.sys.types : pid_t; 28 29 30 31 /******************************************************************************* 32 33 Definition of external functions required to set cpu affinity. 34 35 *******************************************************************************/ 36 37 private extern ( C ) 38 { 39 /* Type for array elements in 'cpu_set_t'. */ 40 mixin(Typedef!(uint, "__cpu_mask")); 41 42 /* Size definition for CPU sets. */ 43 static immutable __CPU_SETSIZE = 1024; 44 static immutable __NCPUBITS = (8 * __cpu_mask.sizeof); 45 46 /* Data structure to describe CPU mask. */ 47 struct cpu_set_t 48 { 49 __cpu_mask[__CPU_SETSIZE / __NCPUBITS] __bits; 50 } 51 52 int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); 53 } 54 55 56 57 /******************************************************************************* 58 59 Struct containing static functions for cpu affinity. 60 61 *******************************************************************************/ 62 63 public struct CpuAffinity 64 { 65 import ocean.sys.ErrnoException; 66 import core.stdc.errno: EINVAL; 67 68 static: 69 70 /*************************************************************************** 71 72 Sets the CPU affinity of the calling process. 73 74 Params: 75 cpu = index of cpu to run process on 76 77 Throws: 78 ErrnoException on failure. Possible errors: 79 - EINVAL: The processor is not currently physically on the system 80 and permitted to the process according to any restrictions that 81 may be imposed by the "cpuset" mechanism described in cpuset(7). 82 - EPERM: The calling process does not have appropriate privileges. 83 84 ***************************************************************************/ 85 86 public void set ( uint cpu ) 87 { 88 try 89 { 90 cpu_set_t cpu_set; 91 CPU_SET(cast(__cpu_mask)cpu, cpu_set); 92 93 enum pid_t pid = 0; // 0 := calling process 94 if (sched_setaffinity(pid, cpu_set_t.sizeof, &cpu_set)) 95 { 96 throw (new ErrnoException).useGlobalErrno("sched_setaffinity"); 97 } 98 } 99 catch (ErrnoException e) 100 { 101 /* 102 * Add a sensible error message for EINVAL because this error can be 103 * caused by a bad parameter value in the config.ini, and the 104 * standard message "sched_setaffinity: Invalid argument" may appear 105 * cryptic to the user. 106 */ 107 108 if (e.errorNumber == EINVAL) 109 { 110 e.append(" - probably attempted to set the CPU affinity to a " ~ 111 "CPU that doesn't exist in this system."); 112 } 113 114 throw e; 115 } 116 } 117 118 119 // TODO: multiple CPU affinity setter (if needed) 120 121 122 /*************************************************************************** 123 124 CPU index bit mask array index. Converted from the __CPUELT macro 125 defined in bits/sched.h: 126 127 --- 128 129 # define __CPUELT(cpu) ((cpu) / __NCPUBITS) 130 131 --- 132 133 Params: 134 cpu = cpu index 135 136 Returns: 137 index of bit mask array element which the indexed cpu is within 138 139 ***************************************************************************/ 140 141 private size_t CPUELT ( uint cpu ) 142 { 143 return (cpu / __NCPUBITS); 144 } 145 146 147 /*************************************************************************** 148 149 CPU index bit mask. Converted from the __CPUMASK macro defined in 150 bits/sched.h: 151 152 --- 153 154 # define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS)) 155 156 --- 157 158 Params: 159 cpu = cpu index 160 161 Returns: 162 bit mask with the indexed cpu set to 1 163 164 ***************************************************************************/ 165 166 private __cpu_mask CPUMASK ( uint cpu ) 167 { 168 return cast(__cpu_mask)(1 << (cpu % __NCPUBITS)); 169 } 170 171 172 /*************************************************************************** 173 174 Sets the bit mask of the provided cpu_set_t to the indexed cpu. 175 Converted from the __CPU_SET macro defined in bits/sched.h: 176 177 --- 178 179 # define __CPU_SET(cpu, cpusetp) \ 180 ((cpusetp)->__bits[__CPUELT (cpu)] |= __CPUMASK (cpu)) 181 182 --- 183 184 Params: 185 cpu = cpu index 186 set = cpu set 187 188 Throws: 189 ErrnoException (EINVAL) if cpu is too high to fit in set. 190 191 ***************************************************************************/ 192 193 private void CPU_SET ( uint cpu, ref cpu_set_t set ) 194 { 195 auto i = CPUELT(cpu); 196 197 if (i < set.__bits.length) 198 { 199 set.__bits[i] |= CPUMASK(cpu); 200 } 201 else 202 { 203 throw (new ErrnoException).set(EINVAL, "CPU_SET") 204 .append(" - CPU index too high"); 205 } 206 } 207 } 208