VirtualBox

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

Last change on this file since 54408 was 54408, checked in by vboxsync, 10 years ago

IPRT/r0drv: Added RTMpOnPair and RTMpOnPairIsConcurrentExecSupported, currently generic wrappers around RTMpOnAll but this will change where possible.

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

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