summaryrefslogtreecommitdiff
path: root/include/iprt/mp.h
blob: 23ababc368ffdded6a6d3c8082dde2a5484e89b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
/** @file
 * IPRT - Multiprocessor.
 */

/*
 * Copyright (C) 2008-2010 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 * VirtualBox OSE distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 */

#ifndef ___iprt_mp_h
#define ___iprt_mp_h

#include <iprt/cdefs.h>
#include <iprt/types.h>


RT_C_DECLS_BEGIN

/** @defgroup grp_rt_mp RTMp - Multiprocessor
 * @ingroup grp_rt
 * @{
 */

/**
 * Gets the identifier of the CPU executing the call.
 *
 * When called from a system mode where scheduling is active, like ring-3 or
 * kernel mode with interrupts enabled on some systems, no assumptions should
 * be made about the current CPU when the call returns.
 *
 * @returns CPU Id.
 */
RTDECL(RTCPUID) RTMpCpuId(void);

/**
 * Converts a CPU identifier to a CPU set index.
 *
 * This may or may not validate the presence of the CPU.
 *
 * @returns The CPU set index on success, -1 on failure.
 * @param   idCpu       The identifier of the CPU.
 */
RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu);

/**
 * Converts a CPU set index to a a CPU identifier.
 *
 * This may or may not validate the presence of the CPU, so, use
 * RTMpIsCpuPossible for that.
 *
 * @returns The corresponding CPU identifier, NIL_RTCPUID on failure.
 * @param   iCpu    The CPU set index.
 */
RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu);

/**
 * Gets the max CPU identifier (inclusive).
 *
 * Intended for brute force enumerations, but use with
 * care as it may be expensive.
 *
 * @returns The current higest CPU identifier value.
 */
RTDECL(RTCPUID) RTMpGetMaxCpuId(void);

/**
 * Gets the size of a CPU array that is indexed by CPU set index.
 *
 * This takes both online, offline and hot-plugged cpus into account.
 *
 * @returns Number of elements.
 *
 * @remarks Use RTMpCpuIdToSetIndex to convert a RTCPUID into an array index.
 */
RTDECL(uint32_t) RTMpGetArraySize(void);

/**
 * Checks if a CPU exists in the system or may possibly be hotplugged later.
 *
 * @returns true/false accordingly.
 * @param   idCpu       The identifier of the CPU.
 */
RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu);

/**
 * Gets set of the CPUs present in the system plus any that may
 * possibly be hotplugged later.
 *
 * @returns pSet.
 * @param   pSet    Where to put the set.
 */
RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet);

/**
 * Get the count of CPUs present in the system plus any that may
 * possibly be hotplugged later.
 *
 * @returns The count.
 * @remarks Don't use this for CPU array sizing, use RTMpGetArraySize instead.
 */
RTDECL(RTCPUID) RTMpGetCount(void);

/**
 * Get the count of physical CPU cores present in the system plus any that may
 * possibly be hotplugged later.
 *
 * @returns The number of cores.
 */
RTDECL(RTCPUID) RTMpGetCoreCount(void);

/**
 * Gets set of the CPUs present that are currently online.
 *
 * @returns pSet.
 * @param   pSet    Where to put the set.
 */
RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet);

/**
 * Get the count of CPUs that are currently online.
 *
 * @return The count.
 */
RTDECL(RTCPUID) RTMpGetOnlineCount(void);

/**
 * Get the count of physical CPU cores in the system with one or more online
 * threads.
 *
 * @returns The number of online cores.
 */
RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void);

/**
 * Checks if a CPU is online or not.
 *
 * @returns true/false accordingly.
 * @param   idCpu       The identifier of the CPU.
 */
RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu);


/**
 * Gets set of the CPUs present in the system.
 *
 * @returns pSet.
 * @param   pSet    Where to put the set.
 */
RTDECL(PRTCPUSET) RTMpGetPresentSet(PRTCPUSET pSet);

/**
 * Get the count of CPUs that are present in the system.
 *
 * @return The count.
 */
RTDECL(RTCPUID) RTMpGetPresentCount(void);

/**
 * Get the count of physical CPU cores present in the system.
 *
 * @returns The number of cores.
 */
RTDECL(RTCPUID) RTMpGetPresentCoreCount(void);

/**
 * Checks if a CPU is present in the system.
 *
 * @returns true/false accordingly.
 * @param   idCpu       The identifier of the CPU.
 */
RTDECL(bool) RTMpIsCpuPresent(RTCPUID idCpu);


/**
 * Get the current frequency of a CPU.
 *
 * The CPU must be online.
 *
 * @returns The frequency as MHz. 0 if the CPU is offline
 *          or the information is not available.
 * @param   idCpu       The identifier of the CPU.
 */
RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu);

/**
 * Get the maximum frequency of a CPU.
 *
 * The CPU must be online.
 *
 * @returns The frequency as MHz. 0 if the CPU is offline
 *          or the information is not available.
 * @param   idCpu       The identifier of the CPU.
 */
RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu);

/**
 * Get the CPU description string.
 *
 * The CPU must be online.
 *
 * @returns IPRT status code.
 * @param   idCpu       The identifier of the CPU.
 * @param   pszBuf      The output buffer.
 * @param   cbBuf       The size of the output buffer.
 */
RTDECL(int) RTMpGetDescription(RTCPUID idCpu, char *pszBuf, size_t cbBuf);


#ifdef IN_RING0

/**
 * Check if there's work (DPCs on Windows) pending on the current CPU.
 *
 * @return true if there's pending work on the current CPU, false otherwise.
 */
RTDECL(bool) RTMpIsCpuWorkPending(void);


/**
 * Worker function passed to RTMpOnAll, RTMpOnOthers and RTMpOnSpecific that
 * is to be called on the target cpus.
 *
 * @param   idCpu       The identifier for the CPU the function is called on.
 * @param   pvUser1     The 1st user argument.
 * @param   pvUser2     The 2nd user argument.
 */
typedef DECLCALLBACK(void) FNRTMPWORKER(RTCPUID idCpu, void *pvUser1, void *pvUser2);
/** Pointer to a FNRTMPWORKER. */
typedef FNRTMPWORKER *PFNRTMPWORKER;

/**
 * Executes a function on each (online) CPU in the system.
 *
 * @returns IPRT status code.
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system.
 *
 * @param   pfnWorker       The worker function.
 * @param   pvUser1         The first user argument for the worker.
 * @param   pvUser2         The second user argument for the worker.
 *
 * @remarks The execution isn't in any way guaranteed to be simultaneous,
 *          it might even be serial (cpu by cpu).
 */
RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);

/**
 * Executes a function on a all other (online) CPUs in the system.
 *
 * The caller must disable preemption prior to calling this API if the outcome
 * is to make any sense. But do *not* disable interrupts.
 *
 * @returns IPRT status code.
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system.
 *
 * @param   pfnWorker       The worker function.
 * @param   pvUser1         The first user argument for the worker.
 * @param   pvUser2         The second user argument for the worker.
 *
 * @remarks The execution isn't in any way guaranteed to be simultaneous,
 *          it might even be serial (cpu by cpu).
 */
RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);

/**
 * Executes a function on a specific CPU in the system.
 *
 * @returns IPRT status code.
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system.
 * @retval  VERR_CPU_OFFLINE if the CPU is offline.
 * @retval  VERR_CPU_NOT_FOUND if the CPU wasn't found.
 *
 * @param   idCpu           The id of the CPU.
 * @param   pfnWorker       The worker function.
 * @param   pvUser1         The first user argument for the worker.
 * @param   pvUser2         The second user argument for the worker.
 */
RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2);

/**
 * Pokes the specified CPU.
 *
 * This should cause the execution on the CPU to be interrupted and forcing it
 * to enter kernel context. It is optimized version of a RTMpOnSpecific call
 * with a worker which returns immediately.
 *
 * @returns IPRT status code.
 * @retval  VERR_NOT_SUPPORTED if this kind of operation isn't supported by the
 *          system. The caller must not automatically assume that this API works
 *          when any of the RTMpOn* APIs works. This is because not all systems
 *          supports unicast MP events and this API will not be implemented as a
 *          broadcast.
 * @retval  VERR_CPU_OFFLINE if the CPU is offline.
 * @retval  VERR_CPU_NOT_FOUND if the CPU wasn't found.
 *
 * @param   idCpu           The id of the CPU to poke.
 */
RTDECL(int) RTMpPokeCpu(RTCPUID idCpu);


/**
 * MP event, see FNRTMPNOTIFICATION.
 */
typedef enum RTMPEVENT
{
    /** The CPU goes online. */
    RTMPEVENT_ONLINE = 1,
    /** The CPU goes offline. */
    RTMPEVENT_OFFLINE
} RTMPEVENT;

/**
 * Notification callback.
 *
 * The context this is called in differs a bit from platform to
 * platform, so be careful while in here.
 *
 * @param   idCpu       The CPU this applies to.
 * @param   enmEvent    The event.
 * @param   pvUser      The user argument.
 */
typedef DECLCALLBACK(void) FNRTMPNOTIFICATION(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser);
/** Pointer to a FNRTMPNOTIFICATION(). */
typedef FNRTMPNOTIFICATION *PFNRTMPNOTIFICATION;

/**
 * Registers a notification callback for cpu events.
 *
 * On platforms which doesn't do cpu offline/online events this API
 * will just be a no-op that pretends to work.
 *
 * @todo We'll be adding a flag to this soon to indicate whether the callback should be called on all
 *       CPUs that are currently online while it's being registered. This is to help avoid some race
 *       conditions (we'll hopefully be able to implement this on linux, solaris/win is no issue).
 *
 * @returns IPRT status code.
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_NO_MEMORY if a registration record cannot be allocated.
 * @retval  VERR_ALREADY_EXISTS if the pfnCallback and pvUser already exist
 *          in the callback list.
 *
 * @param   pfnCallback     The callback.
 * @param   pvUser          The user argument to the callback function.
 */
RTDECL(int) RTMpNotificationRegister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser);

/**
 * This deregisters a notification callback registered via RTMpNotificationRegister().
 *
 * The pfnCallback and pvUser arguments must be identical to the registration call
 * of we won't find the right entry.
 *
 * @returns IPRT status code.
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_NOT_FOUND if no matching entry was found.
 *
 * @param   pfnCallback     The callback.
 * @param   pvUser          The user argument to the callback function.
 */
RTDECL(int) RTMpNotificationDeregister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser);

#endif /* IN_RING0 */

/** @} */

RT_C_DECLS_END

#endif