]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - ubuntu/vbox/include/iprt/cpuset.h
UBUNTU: ubuntu: vbox -- update to 5.1.28-dfsg-1
[mirror_ubuntu-bionic-kernel.git] / ubuntu / vbox / include / iprt / cpuset.h
1 /** @file
2 * IPRT - CPU Set.
3 */
4
5 /*
6 * Copyright (C) 2008-2016 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26 #ifndef ___iprt_cpuset_h
27 #define ___iprt_cpuset_h
28
29 #include <iprt/types.h>
30 #include <iprt/mp.h> /* RTMpCpuIdToSetIndex */
31 #include <iprt/asm.h>
32
33
34 RT_C_DECLS_BEGIN
35
36 /** @defgroup grp_rt_cpuset RTCpuSet - CPU Set
37 * @ingroup grp_rt
38 * @{
39 */
40
41
42 /**
43 * Clear all CPUs.
44 *
45 * @returns pSet.
46 * @param pSet Pointer to the set.
47 */
48 DECLINLINE(PRTCPUSET) RTCpuSetEmpty(PRTCPUSET pSet)
49 {
50 size_t i;
51 for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
52 pSet->bmSet[i] = 0;
53 return pSet;
54 }
55
56
57 /**
58 * Set all CPUs.
59 *
60 * @returns pSet.
61 * @param pSet Pointer to the set.
62 */
63 DECLINLINE(PRTCPUSET) RTCpuSetFill(PRTCPUSET pSet)
64 {
65 size_t i;
66 for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
67 pSet->bmSet[i] = UINT64_MAX;
68 return pSet;
69 }
70
71
72 /**
73 * Copies one set to another.
74 *
75 * @param pDst Pointer to the destination set.
76 * @param pSrc Pointer to the source set.
77 */
78 DECLINLINE(void) RTCpuSetCopy(PRTCPUSET pDst, PRTCPUSET pSrc)
79 {
80 size_t i;
81 for (i = 0; i < RT_ELEMENTS(pDst->bmSet); i++)
82 pDst->bmSet[i] = pSrc->bmSet[i];
83 }
84
85
86 /**
87 * ANDs the given CPU set with another.
88 *
89 * @returns pSet.
90 * @param pSet Pointer to the set.
91 * @param pAndMaskSet Pointer to the AND-mask set.
92 */
93 DECLINLINE(PRTCPUSET) RTCpuSetAnd(PRTCPUSET pSet, PRTCPUSET pAndMaskSet)
94 {
95 size_t i;
96 for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
97 ASMAtomicAndU64((volatile uint64_t *)&pSet->bmSet[i], pAndMaskSet->bmSet[i]);
98 return pSet;
99 }
100
101
102 /**
103 * Adds a CPU given by its identifier to the set.
104 *
105 * @returns 0 on success, -1 if idCpu isn't valid.
106 * @param pSet Pointer to the set.
107 * @param idCpu The identifier of the CPU to add.
108 * @remarks The modification is atomic.
109 */
110 DECLINLINE(int) RTCpuSetAdd(PRTCPUSET pSet, RTCPUID idCpu)
111 {
112 int iCpu = RTMpCpuIdToSetIndex(idCpu);
113 if (RT_LIKELY(iCpu >= 0))
114 {
115 ASMAtomicBitSet(pSet, iCpu);
116 return 0;
117 }
118 return -1;
119 }
120
121
122 /**
123 * Adds a CPU given by its identifier to the set.
124 *
125 * @returns 0 on success, -1 if iCpu isn't valid.
126 * @param pSet Pointer to the set.
127 * @param iCpu The index of the CPU to add.
128 * @remarks The modification is atomic.
129 */
130 DECLINLINE(int) RTCpuSetAddByIndex(PRTCPUSET pSet, int iCpu)
131 {
132 if (RT_LIKELY((unsigned)iCpu < RTCPUSET_MAX_CPUS))
133 {
134 ASMAtomicBitSet(pSet, iCpu);
135 return 0;
136 }
137 return -1;
138 }
139
140
141 /**
142 * Removes a CPU given by its identifier from the set.
143 *
144 * @returns 0 on success, -1 if idCpu isn't valid.
145 * @param pSet Pointer to the set.
146 * @param idCpu The identifier of the CPU to delete.
147 * @remarks The modification is atomic.
148 */
149 DECLINLINE(int) RTCpuSetDel(PRTCPUSET pSet, RTCPUID idCpu)
150 {
151 int iCpu = RTMpCpuIdToSetIndex(idCpu);
152 if (RT_LIKELY(iCpu >= 0))
153 {
154 ASMAtomicBitClear(pSet, iCpu);
155 return 0;
156 }
157 return -1;
158 }
159
160
161 /**
162 * Removes a CPU given by its index from the set.
163 *
164 * @returns 0 on success, -1 if iCpu isn't valid.
165 * @param pSet Pointer to the set.
166 * @param iCpu The index of the CPU to delete.
167 * @remarks The modification is atomic.
168 */
169 DECLINLINE(int) RTCpuSetDelByIndex(PRTCPUSET pSet, int iCpu)
170 {
171 if (RT_LIKELY((unsigned)iCpu < RTCPUSET_MAX_CPUS))
172 {
173 ASMAtomicBitClear(pSet, iCpu);
174 return 0;
175 }
176 return -1;
177 }
178
179
180 /**
181 * Checks if a CPU given by its identifier is a member of the set.
182 *
183 * @returns true / false accordingly.
184 * @param pSet Pointer to the set.
185 * @param idCpu The identifier of the CPU to look for.
186 * @remarks The test is atomic.
187 */
188 DECLINLINE(bool) RTCpuSetIsMember(PCRTCPUSET pSet, RTCPUID idCpu)
189 {
190 int iCpu = RTMpCpuIdToSetIndex(idCpu);
191 if (RT_LIKELY(iCpu >= 0))
192 return ASMBitTest((volatile void *)pSet, iCpu);
193 return false;
194 }
195
196
197 /**
198 * Checks if a CPU given by its index is a member of the set.
199 *
200 * @returns true / false accordingly.
201 * @param pSet Pointer to the set.
202 * @param iCpu The index of the CPU in the set.
203 * @remarks The test is atomic.
204 */
205 DECLINLINE(bool) RTCpuSetIsMemberByIndex(PCRTCPUSET pSet, int iCpu)
206 {
207 if (RT_LIKELY((unsigned)iCpu < RTCPUSET_MAX_CPUS))
208 return ASMBitTest((volatile void *)pSet, iCpu);
209 return false;
210 }
211
212
213 /**
214 * Checks if the two sets match or not.
215 *
216 * @returns true / false accordingly.
217 * @param pSet1 The first set.
218 * @param pSet2 The second set.
219 */
220 DECLINLINE(bool) RTCpuSetIsEqual(PCRTCPUSET pSet1, PCRTCPUSET pSet2)
221 {
222 size_t i;
223 for (i = 0; i < RT_ELEMENTS(pSet1->bmSet); i++)
224 if (pSet1->bmSet[i] != pSet2->bmSet[i])
225 return false;
226 return true;
227 }
228
229
230 /**
231 * Checks if the CPU set is empty or not.
232 *
233 * @returns true / false accordingly.
234 * @param pSet Pointer to the set.
235 */
236 DECLINLINE(bool) RTCpuSetIsEmpty(PRTCPUSET pSet)
237 {
238 size_t i;
239 for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
240 if (pSet->bmSet[i])
241 return false;
242 return true;
243 }
244
245
246 /**
247 * Converts the CPU set to a 64-bit mask.
248 *
249 * @returns The mask.
250 * @param pSet Pointer to the set.
251 * @remarks Use with extreme care as it may lose information!
252 */
253 DECLINLINE(uint64_t) RTCpuSetToU64(PCRTCPUSET pSet)
254 {
255 return pSet->bmSet[0];
256 }
257
258
259 /**
260 * Initializes the CPU set from a 64-bit mask.
261 *
262 * @param pSet Pointer to the set.
263 * @param fMask The mask.
264 */
265 DECLINLINE(PRTCPUSET) RTCpuSetFromU64(PRTCPUSET pSet, uint64_t fMask)
266 {
267 size_t i;
268
269 pSet->bmSet[0] = fMask;
270 for (i = 1; i < RT_ELEMENTS(pSet->bmSet); i++)
271 pSet->bmSet[i] = 0;
272
273 return pSet;
274 }
275
276
277 /**
278 * Count the CPUs in the set.
279 *
280 * @returns CPU count.
281 * @param pSet Pointer to the set.
282 */
283 DECLINLINE(int) RTCpuSetCount(PCRTCPUSET pSet)
284 {
285 int cCpus = 0;
286 size_t i;
287
288 for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++)
289 {
290 uint64_t u64 = pSet->bmSet[i];
291 if (u64 != 0)
292 {
293 unsigned iCpu = 64;
294 while (iCpu-- > 0)
295 {
296 if (u64 & 1)
297 cCpus++;
298 u64 >>= 1;
299 }
300 }
301 }
302 return cCpus;
303 }
304
305
306 /**
307 * Get the highest set index.
308 *
309 * @returns The higest set index, -1 if all bits are clear.
310 * @param pSet Pointer to the set.
311 */
312 DECLINLINE(int) RTCpuLastIndex(PCRTCPUSET pSet)
313 {
314 size_t i = RT_ELEMENTS(pSet->bmSet);
315 while (i-- > 0)
316 {
317 uint64_t u64 = pSet->bmSet[i];
318 if (u64)
319 {
320 /* There are more efficient ways to do this in asm.h... */
321 unsigned iBit;
322 for (iBit = 63; iBit > 0; iBit--)
323 {
324 if (u64 & RT_BIT_64(63))
325 break;
326 u64 <<= 1;
327 }
328 return (int)i * 64 + iBit;
329 }
330 }
331 return 0;
332 }
333
334
335 /** @} */
336
337 RT_C_DECLS_END
338
339 #endif
340