VirtualBox

source: vbox/trunk/include/iprt/cpuset.h@ 104212

Last change on this file since 104212 was 103005, checked in by vboxsync, 10 months ago

iprt/asm.h,*: Split out the ASMMem* and related stuff into a separate header, asm-mem.h, so that we can get the RT_ASM_PAGE_SIZE stuff out of the way.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette