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 moduleocean.sys.CpuAffinity;
21 22 importocean.meta.types.Qualifiers;
23 importocean.meta.types.Typedef;
24 25 importcore.sys.posix.sys.types : pid_t;
26 27 /*******************************************************************************
28 29 Definition of external functions required to set cpu affinity.
30 31 *******************************************************************************/32 33 privateextern ( C )
34 {
35 /* Type for array elements in 'cpu_set_t'. */36 mixin(Typedef!(uint, "__cpu_mask"));
37 38 /* Size definition for CPU sets. */39 staticimmutable__CPU_SETSIZE = 1024;
40 staticimmutable__NCPUBITS = (8 * __cpu_mask.sizeof);
41 42 /* Data structure to describe CPU mask. */43 structcpu_set_t44 {
45 __cpu_mask[__CPU_SETSIZE / __NCPUBITS] __bits;
46 }
47 48 intsched_setaffinity(pid_tpid, size_tcpusetsize, cpu_set_t *mask);
49 }
50 51 52 53 /*******************************************************************************
54 55 Struct containing static functions for cpu affinity.
56 57 *******************************************************************************/58 59 publicstructCpuAffinity60 {
61 importocean.sys.ErrnoException;
62 importcore.stdc.errno: EINVAL;
63 64 static:
65 66 /***************************************************************************
67 68 Sets the CPU affinity of the calling process.
69 70 Params:
71 cpu = index of cpu to run process on
72 73 Throws:
74 ErrnoException on failure. Possible errors:
75 - EINVAL: The processor is not currently physically on the system
76 and permitted to the process according to any restrictions that
77 may be imposed by the "cpuset" mechanism described in cpuset(7).
78 - EPERM: The calling process does not have appropriate privileges.
79 80 ***************************************************************************/81 82 publicvoidset ( uintcpu )
83 {
84 try85 {
86 cpu_set_tcpu_set;
87 CPU_SET(cast(__cpu_mask)cpu, cpu_set);
88 89 enumpid_tpid = 0; // 0 := calling process90 if (sched_setaffinity(pid, cpu_set_t.sizeof, &cpu_set))
91 {
92 throw (newErrnoException).useGlobalErrno("sched_setaffinity");
93 }
94 }
95 catch (ErrnoExceptione)
96 {
97 /*
98 * Add a sensible error message for EINVAL because this error can be
99 * caused by a bad parameter value in the config.ini, and the
100 * standard message "sched_setaffinity: Invalid argument" may appear
101 * cryptic to the user.
102 */103 104 if (e.errorNumber == EINVAL)
105 {
106 e.append(" - probably attempted to set the CPU affinity to a " ~
107 "CPU that doesn't exist in this system.");
108 }
109 110 throwe;
111 }
112 }
113 114 115 // TODO: multiple CPU affinity setter (if needed)116 117 118 /***************************************************************************
119 120 CPU index bit mask array index. Converted from the __CPUELT macro
121 defined in bits/sched.h:
122 123 ---
124 125 # define __CPUELT(cpu) ((cpu) / __NCPUBITS)
126 127 ---
128 129 Params:
130 cpu = cpu index
131 132 Returns:
133 index of bit mask array element which the indexed cpu is within
134 135 ***************************************************************************/136 137 privatesize_tCPUELT ( uintcpu )
138 {
139 return (cpu / __NCPUBITS);
140 }
141 142 143 /***************************************************************************
144 145 CPU index bit mask. Converted from the __CPUMASK macro defined in
146 bits/sched.h:
147 148 ---
149 150 # define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
151 152 ---
153 154 Params:
155 cpu = cpu index
156 157 Returns:
158 bit mask with the indexed cpu set to 1
159 160 ***************************************************************************/161 162 private__cpu_maskCPUMASK ( uintcpu )
163 {
164 returncast(__cpu_mask)(1 << (cpu % __NCPUBITS));
165 }
166 167 168 /***************************************************************************
169 170 Sets the bit mask of the provided cpu_set_t to the indexed cpu.
171 Converted from the __CPU_SET macro defined in bits/sched.h:
172 173 ---
174 175 # define __CPU_SET(cpu, cpusetp) \
176 ((cpusetp)->__bits[__CPUELT (cpu)] |= __CPUMASK (cpu))
177 178 ---
179 180 Params:
181 cpu = cpu index
182 set = cpu set
183 184 Throws:
185 ErrnoException (EINVAL) if cpu is too high to fit in set.
186 187 ***************************************************************************/188 189 privatevoidCPU_SET ( uintcpu, refcpu_set_tset )
190 {
191 autoi = CPUELT(cpu);
192 193 if (i < set.__bits.length)
194 {
195 set.__bits[i] |= CPUMASK(cpu);
196 }
197 else198 {
199 throw (newErrnoException).set(EINVAL, "CPU_SET")
200 .append(" - CPU index too high");
201 }
202 }
203 }