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