VirtualBox

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

Last change on this file since 62691 was 62473, checked in by vboxsync, 8 years ago

(C) 2016

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