VirtualBox

source: vbox/trunk/include/iprt/mp.h

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.0 KB
RevLine 
[7251]1/** @file
[8245]2 * IPRT - Multiprocessor.
[7251]3 */
4
5/*
[98103]6 * Copyright (C) 2008-2023 Oracle and/or its affiliates.
[7251]7 *
[96407]8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
[7251]10 *
[96407]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 *
[7251]24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
[96407]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
[7251]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.
[96407]32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
[7251]34 */
35
[76557]36#ifndef IPRT_INCLUDED_mp_h
37#define IPRT_INCLUDED_mp_h
[76507]38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
[7251]41
42#include <iprt/cdefs.h>
43#include <iprt/types.h>
44
45
[20374]46RT_C_DECLS_BEGIN
[7251]47
48/** @defgroup grp_rt_mp RTMp - Multiprocessor
49 * @ingroup grp_rt
50 * @{
51 */
52
53/**
54 * Gets the identifier of the CPU executing the call.
[7325]55 *
[7251]56 * When called from a system mode where scheduling is active, like ring-3 or
57 * kernel mode with interrupts enabled on some systems, no assumptions should
58 * be made about the current CPU when the call returns.
[7325]59 *
[7251]60 * @returns CPU Id.
61 */
62RTDECL(RTCPUID) RTMpCpuId(void);
63
[7325]64/**
[54415]65 * Get the CPU set index of the CPU executing the call.
66 *
67 * Same scheduling warnings as for RTMpCpuId().
68 *
69 * @returns CPU set index.
70 */
71RTDECL(int) RTMpCurSetIndex(void);
72
73/**
74 * Get the CPU set index and identifier of the CPU executing the call.
75 *
76 * Same scheduling warnings as for RTMpCpuId().
77 *
78 * @returns CPU set index.
79 * @param pidCpu Where to return the CPU identifier. (not optional)
80 */
81RTDECL(int) RTMpCurSetIndexAndId(PRTCPUID pidCpu);
82
83/**
[7326]84 * Converts a CPU identifier to a CPU set index.
85 *
[10418]86 * This may or may not validate the presence of the CPU.
[7330]87 *
[7326]88 * @returns The CPU set index on success, -1 on failure.
89 * @param idCpu The identifier of the CPU.
90 */
91RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu);
[7325]92
[7328]93/**
[7330]94 * Converts a CPU set index to a a CPU identifier.
95 *
[10418]96 * This may or may not validate the presence of the CPU, so, use
[9429]97 * RTMpIsCpuPossible for that.
[7330]98 *
99 * @returns The corresponding CPU identifier, NIL_RTCPUID on failure.
100 * @param iCpu The CPU set index.
101 */
102RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu);
103
104/**
[64281]105 * Translates an NT process group member to a CPU set index.
106 *
107 * @returns CPU set index, -1 if not valid.
108 * @param idxGroup The CPU group.
109 * @param idxMember The CPU group member number.
110 *
111 * @remarks Only available on Windows.
112 */
113RTDECL(int) RTMpSetIndexFromCpuGroupMember(uint32_t idxGroup, uint32_t idxMember);
114
115/**
116 * Gets the member numbers for a CPU group.
117 *
118 * @returns Maximum number of group members.
119 * @param idxGroup The CPU group.
120 * @param pcActive Where to return the number of active members.
121 *
122 * @remarks Only available on Windows.
123 */
124RTDECL(uint32_t) RTMpGetCpuGroupCounts(uint32_t idxGroup, uint32_t *pcActive);
125
126/**
127 * Get the maximum number of CPU groups.
128 *
129 * @returns Maximum number of CPU groups.
130 *
131 * @remarks Only available on Windows.
132 */
133RTDECL(uint32_t) RTMpGetMaxCpuGroupCount(void);
134
135/**
[7330]136 * Gets the max CPU identifier (inclusive).
137 *
[32572]138 * Intended for brute force enumerations, but use with
[7330]139 * care as it may be expensive.
140 *
141 * @returns The current higest CPU identifier value.
142 */
143RTDECL(RTCPUID) RTMpGetMaxCpuId(void);
144
[32572]145/**
146 * Gets the size of a CPU array that is indexed by CPU set index.
147 *
148 * This takes both online, offline and hot-plugged cpus into account.
149 *
150 * @returns Number of elements.
151 *
152 * @remarks Use RTMpCpuIdToSetIndex to convert a RTCPUID into an array index.
153 */
154RTDECL(uint32_t) RTMpGetArraySize(void);
[12104]155
[7330]156/**
[9429]157 * Checks if a CPU exists in the system or may possibly be hotplugged later.
[7354]158 *
159 * @returns true/false accordingly.
160 * @param idCpu The identifier of the CPU.
161 */
[9429]162RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu);
[7354]163
164/**
[33540]165 * Gets set of the CPUs present in the system plus any that may
[9429]166 * possibly be hotplugged later.
[7354]167 *
[7328]168 * @returns pSet.
169 * @param pSet Where to put the set.
170 */
171RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet);
[7325]172
[7328]173/**
[9429]174 * Get the count of CPUs present in the system plus any that may
175 * possibly be hotplugged later.
[7328]176 *
[32572]177 * @returns The count.
178 * @remarks Don't use this for CPU array sizing, use RTMpGetArraySize instead.
[7328]179 */
180RTDECL(RTCPUID) RTMpGetCount(void);
[7326]181
[46144]182/**
[46636]183 * Get the count of physical CPU cores present in the system plus any that may
184 * possibly be hotplugged later.
185 *
186 * @returns The number of cores.
[46144]187 */
188RTDECL(RTCPUID) RTMpGetCoreCount(void);
[12104]189
[7328]190/**
191 * Gets set of the CPUs present that are currently online.
192 *
193 * @returns pSet.
194 * @param pSet Where to put the set.
195 */
[7329]196RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet);
[7328]197
198/**
199 * Get the count of CPUs that are currently online.
200 *
201 * @return The count.
202 */
203RTDECL(RTCPUID) RTMpGetOnlineCount(void);
204
[9429]205/**
[46639]206 * Get the count of physical CPU cores in the system with one or more online
207 * threads.
208 *
209 * @returns The number of online cores.
210 */
[48765]211RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void);
[46639]212
213/**
[9429]214 * Checks if a CPU is online or not.
215 *
216 * @returns true/false accordingly.
217 * @param idCpu The identifier of the CPU.
218 */
219RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu);
[7328]220
[12104]221
[10418]222/**
[12104]223 * Gets set of the CPUs present in the system.
224 *
225 * @returns pSet.
226 * @param pSet Where to put the set.
227 */
228RTDECL(PRTCPUSET) RTMpGetPresentSet(PRTCPUSET pSet);
229
230/**
231 * Get the count of CPUs that are present in the system.
232 *
233 * @return The count.
234 */
235RTDECL(RTCPUID) RTMpGetPresentCount(void);
236
237/**
[46639]238 * Get the count of physical CPU cores present in the system.
239 *
240 * @returns The number of cores.
241 */
242RTDECL(RTCPUID) RTMpGetPresentCoreCount(void);
243
244/**
[12104]245 * Checks if a CPU is present in the system.
246 *
247 * @returns true/false accordingly.
248 * @param idCpu The identifier of the CPU.
249 */
250RTDECL(bool) RTMpIsCpuPresent(RTCPUID idCpu);
251
252
253/**
[10422]254 * Get the current frequency of a CPU.
[10418]255 *
[10422]256 * The CPU must be online.
257 *
258 * @returns The frequency as MHz. 0 if the CPU is offline
259 * or the information is not available.
260 * @param idCpu The identifier of the CPU.
[10418]261 */
262RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu);
[9429]263
[10418]264/**
[10422]265 * Get the maximum frequency of a CPU.
[10418]266 *
[10422]267 * The CPU must be online.
268 *
269 * @returns The frequency as MHz. 0 if the CPU is offline
270 * or the information is not available.
271 * @param idCpu The identifier of the CPU.
[10418]272 */
273RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu);
274
[21725]275/**
276 * Get the CPU description string.
277 *
278 * The CPU must be online.
279 *
280 * @returns IPRT status code.
[50641]281 * @param idCpu The identifier of the CPU. NIL_RTCPUID can be used to
282 * indicate the current CPU.
[21725]283 * @param pszBuf The output buffer.
284 * @param cbBuf The size of the output buffer.
285 */
286RTDECL(int) RTMpGetDescription(RTCPUID idCpu, char *pszBuf, size_t cbBuf);
[10418]287
[21725]288
[7251]289#ifdef IN_RING0
290
291/**
[15843]292 * Check if there's work (DPCs on Windows) pending on the current CPU.
293 *
294 * @return true if there's pending work on the current CPU, false otherwise.
295 */
296RTDECL(bool) RTMpIsCpuWorkPending(void);
297
298
299/**
[7251]300 * Worker function passed to RTMpOnAll, RTMpOnOthers and RTMpOnSpecific that
301 * is to be called on the target cpus.
[7325]302 *
[7251]303 * @param idCpu The identifier for the CPU the function is called on.
304 * @param pvUser1 The 1st user argument.
305 * @param pvUser2 The 2nd user argument.
306 */
[85121]307typedef DECLCALLBACKTYPE(void, FNRTMPWORKER,(RTCPUID idCpu, void *pvUser1, void *pvUser2));
[7252]308/** Pointer to a FNRTMPWORKER. */
309typedef FNRTMPWORKER *PFNRTMPWORKER;
[7251]310
[54408]311/** @name RTMPON_F_XXX - RTMpOn flags.
312 * @{ */
313/** Caller doesn't care if pfnWorker is executed at the same time on the
314 * specified CPUs or not, as long as it gets executed. */
315#define RTMPON_F_WHATEVER_EXEC 0
316/** The caller insists on pfnWorker being executed more or less concurrently
317 * on the specified CPUs. */
318#define RTMPON_F_CONCURRENT_EXEC RT_BIT_32(1)
319/** Mask of valid bits. */
320#define RTMPON_F_VALID_MASK UINT32_C(0x00000001)
321/** @}*/
322
[7251]323/**
[52618]324 * Checks if the RTMpOnAll() is safe with regards to all threads executing
325 * concurrently.
326 *
327 * If for instance, the RTMpOnAll() is implemented in a way where the threads
328 * might cause a classic deadlock, it is considered -not- concurrent safe.
329 * Windows currently is one such platform where it isn't safe.
330 *
331 * @returns true if RTMpOnAll() is concurrent safe, false otherwise.
332 */
333RTDECL(bool) RTMpOnAllIsConcurrentSafe(void);
334
335/**
[7251]336 * Executes a function on each (online) CPU in the system.
[7325]337 *
[7251]338 * @returns IPRT status code.
339 * @retval VINF_SUCCESS on success.
340 * @retval VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system.
[7325]341 *
[7251]342 * @param pfnWorker The worker function.
[7325]343 * @param pvUser1 The first user argument for the worker.
344 * @param pvUser2 The second user argument for the worker.
[7251]345 *
346 * @remarks The execution isn't in any way guaranteed to be simultaneous,
347 * it might even be serial (cpu by cpu).
348 */
[7252]349RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);
[7251]350
351/**
[75230]352 * Executes a function on all other (online) CPUs in the system.
[7325]353 *
[19390]354 * The caller must disable preemption prior to calling this API if the outcome
355 * is to make any sense. But do *not* disable interrupts.
356 *
[7251]357 * @returns IPRT status code.
358 * @retval VINF_SUCCESS on success.
359 * @retval VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system.
[7325]360 *
[7251]361 * @param pfnWorker The worker function.
[7325]362 * @param pvUser1 The first user argument for the worker.
363 * @param pvUser2 The second user argument for the worker.
364 *
[7251]365 * @remarks The execution isn't in any way guaranteed to be simultaneous,
366 * it might even be serial (cpu by cpu).
367 */
[7252]368RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);
[7251]369
370/**
371 * Executes a function on a specific CPU in the system.
[7325]372 *
[7251]373 * @returns IPRT status code.
374 * @retval VINF_SUCCESS on success.
375 * @retval VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system.
376 * @retval VERR_CPU_OFFLINE if the CPU is offline.
377 * @retval VERR_CPU_NOT_FOUND if the CPU wasn't found.
[7325]378 *
[7251]379 * @param idCpu The id of the CPU.
380 * @param pfnWorker The worker function.
[7325]381 * @param pvUser1 The first user argument for the worker.
382 * @param pvUser2 The second user argument for the worker.
[7251]383 */
[7252]384RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);
[7251]385
[19386]386/**
[54408]387 * Executes a function on two specific CPUs in the system.
388 *
389 * @returns IPRT status code.
390 * @retval VINF_SUCCESS on success.
391 * @retval VERR_NOT_SUPPORTED if this kind of operation isn't supported by the
392 * system or if the specified modifier flag isn't supported.
393 * @retval VERR_CPU_OFFLINE if one or more of the CPUs are offline (see
394 * remarks).
395 * @retval VERR_CPU_NOT_FOUND if on or both of the CPUs weren't found.
396 * @retval VERR_NOT_ALL_CPUS_SHOWED if one of the CPUs didn't show.
397 *
398 * @param idCpu1 The id of the first CPU.
399 * @param idCpu2 The id of the second CPU.
400 * @param fFlags Combination of RTMPON_F_XXX flags.
401 * @param pfnWorker The worker function.
402 * @param pvUser1 The first user argument for the worker.
403 * @param pvUser2 The second user argument for the worker.
404 *
405 * @remarks There is a possible race between one (or both) of the CPUs going
406 * offline while setting up the call. The worker function must take
407 * this into account.
408 */
409RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);
410
411/**
412 * Indicates whether RTMpOnPair supports running the pfnWorker concurrently on
413 * both CPUs using RTMPON_F_CONCURRENT_EXEC.
414 *
415 * @returns true if supported, false if not.
416 */
417RTDECL(bool) RTMpOnPairIsConcurrentExecSupported(void);
418
419
420/**
[19386]421 * Pokes the specified CPU.
422 *
423 * This should cause the execution on the CPU to be interrupted and forcing it
424 * to enter kernel context. It is optimized version of a RTMpOnSpecific call
425 * with a worker which returns immediately.
426 *
427 * @returns IPRT status code.
428 * @retval VERR_NOT_SUPPORTED if this kind of operation isn't supported by the
429 * system. The caller must not automatically assume that this API works
430 * when any of the RTMpOn* APIs works. This is because not all systems
431 * supports unicast MP events and this API will not be implemented as a
432 * broadcast.
433 * @retval VERR_CPU_OFFLINE if the CPU is offline.
434 * @retval VERR_CPU_NOT_FOUND if the CPU wasn't found.
435 *
436 * @param idCpu The id of the CPU to poke.
437 */
438RTDECL(int) RTMpPokeCpu(RTCPUID idCpu);
[9309]439
[19386]440
[9309]441/**
442 * MP event, see FNRTMPNOTIFICATION.
443 */
444typedef enum RTMPEVENT
445{
446 /** The CPU goes online. */
447 RTMPEVENT_ONLINE = 1,
448 /** The CPU goes offline. */
449 RTMPEVENT_OFFLINE
450} RTMPEVENT;
451
452/**
453 * Notification callback.
454 *
[54293]455 * The context this is called in differs a bit from platform to platform, so be
456 * careful while in here.
[9309]457 *
[54382]458 * On Windows we're running with IRQL=PASSIVE_LEVEL (reschedulable) according to
459 * the KeRegisterProcessorChangeCallback documentation - unrestricted API
460 * access. Probably not being called on the onlined/offlined CPU...
[54293]461 *
[54294]462 * On Solaris we're holding the cpu_lock, IPL/SPL/PIL is not yet known, however
463 * we will most likely -not- be firing on the CPU going offline/online.
[54293]464 *
[54382]465 * On Linux it looks like we're called with preemption enabled on any CPU and
466 * not necessarily on the CPU going offline/online.
[54293]467 *
468 * There is no callbacks for darwin at the moment, due to lack of suitable KPI.
469 *
[9309]470 * @param idCpu The CPU this applies to.
471 * @param enmEvent The event.
472 * @param pvUser The user argument.
473 */
[85121]474typedef DECLCALLBACKTYPE(void, FNRTMPNOTIFICATION,(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser));
[9309]475/** Pointer to a FNRTMPNOTIFICATION(). */
476typedef FNRTMPNOTIFICATION *PFNRTMPNOTIFICATION;
477
478/**
479 * Registers a notification callback for cpu events.
480 *
481 * On platforms which doesn't do cpu offline/online events this API
482 * will just be a no-op that pretends to work.
483 *
[9611]484 * @todo We'll be adding a flag to this soon to indicate whether the callback should be called on all
485 * CPUs that are currently online while it's being registered. This is to help avoid some race
486 * conditions (we'll hopefully be able to implement this on linux, solaris/win is no issue).
487 *
[9309]488 * @returns IPRT status code.
489 * @retval VINF_SUCCESS on success.
490 * @retval VERR_NO_MEMORY if a registration record cannot be allocated.
491 * @retval VERR_ALREADY_EXISTS if the pfnCallback and pvUser already exist
492 * in the callback list.
493 *
494 * @param pfnCallback The callback.
495 * @param pvUser The user argument to the callback function.
496 */
497RTDECL(int) RTMpNotificationRegister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser);
498
499/**
500 * This deregisters a notification callback registered via RTMpNotificationRegister().
501 *
502 * The pfnCallback and pvUser arguments must be identical to the registration call
503 * of we won't find the right entry.
504 *
505 * @returns IPRT status code.
506 * @retval VINF_SUCCESS on success.
507 * @retval VERR_NOT_FOUND if no matching entry was found.
508 *
509 * @param pfnCallback The callback.
510 * @param pvUser The user argument to the callback function.
511 */
512RTDECL(int) RTMpNotificationDeregister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser);
513
[7251]514#endif /* IN_RING0 */
515
516/** @} */
517
[20374]518RT_C_DECLS_END
[7251]519
[76585]520#endif /* !IPRT_INCLUDED_mp_h */
[7251]521
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use