VirtualBox

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

Last change on this file since 86649 was 85121, checked in by vboxsync, 4 years ago

iprt/cdefs.h: Refactored the typedef use of DECLCALLBACK as well as DECLCALLBACKMEMBER to wrap the whole expression, similar to the DECLR?CALLBACKMEMBER macros. This allows adding a throw() at the end when compiling with the VC++ compiler to indicate that the callbacks won't throw anything, so we can stop supressing the C5039 warning about passing functions that can potential throw C++ exceptions to extern C code that can't necessarily cope with such (unwind,++). Introduced a few _EX variations that allows specifying different/no calling convention too, as that's handy when dynamically resolving host APIs. Fixed numerous places missing DECLCALLBACK and such. Left two angry @todos regarding use of CreateThread. bugref:9794

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