VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c@ 13476

Last change on this file since 13476 was 12922, checked in by vboxsync, 16 years ago

warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Id: mp-r0drv-linux.c 12922 2008-10-02 10:12:43Z vboxsync $ */
2/** @file
3 * IPRT - Multiprocessor, Ring-0 Driver, Linux.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include "the-linux-kernel.h"
36
37#include <iprt/mp.h>
38#include <iprt/cpuset.h>
39#include <iprt/err.h>
40#include <iprt/asm.h>
41#include "r0drv/mp-r0drv.h"
42
43
44RTDECL(RTCPUID) RTMpCpuId(void)
45{
46 return smp_processor_id();
47}
48
49
50RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
51{
52 return idCpu < NR_CPUS ? (int)idCpu : -1;
53}
54
55
56RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
57{
58 return iCpu < NR_CPUS ? (RTCPUID)iCpu : NIL_RTCPUID;
59}
60
61
62RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
63{
64 return NR_CPUS - 1; //???
65}
66
67
68RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
69{
70#if defined(CONFIG_SMP)
71 if (RT_UNLIKELY(idCpu >= NR_CPUS))
72 return false;
73
74# if defined(cpu_possible)
75 return cpu_possible(idCpu);
76# else /* < 2.5.29 */
77 return idCpu < (RTCPUID)smp_num_cpus;
78# endif
79#else
80 return idCpu == RTMpCpuId();
81#endif
82}
83
84
85RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
86{
87 RTCPUID idCpu;
88
89 RTCpuSetEmpty(pSet);
90 idCpu = RTMpGetMaxCpuId();
91 do
92 {
93 if (RTMpIsCpuPossible(idCpu))
94 RTCpuSetAdd(pSet, idCpu);
95 } while (idCpu-- > 0);
96 return pSet;
97}
98
99
100RTDECL(RTCPUID) RTMpGetCount(void)
101{
102#ifdef CONFIG_SMP
103# if defined(CONFIG_HOTPLUG_CPU) /* introduced & uses cpu_present */
104 return num_present_cpus();
105# elif defined(num_possible_cpus)
106 return num_possible_cpus();
107# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
108 return smp_num_cpus;
109# else
110 RTCPUSET Set;
111 RTMpGetSet(&Set);
112 return RTCpuSetCount(&Set);
113# endif
114#else
115 return 1;
116#endif
117}
118
119
120RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
121{
122#ifdef CONFIG_SMP
123 if (RT_UNLIKELY(idCpu >= NR_CPUS))
124 return false;
125# ifdef cpu_online
126 return cpu_online(idCpu);
127# else /* 2.4: */
128 return cpu_online_map & RT_BIT_64(idCpu);
129# endif
130#else
131 return idCpu == RTMpCpuId();
132#endif
133}
134
135
136RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
137{
138#ifdef CONFIG_SMP
139 RTCPUID idCpu;
140
141 RTCpuSetEmpty(pSet);
142 idCpu = RTMpGetMaxCpuId();
143 do
144 {
145 if (RTMpIsCpuOnline(idCpu))
146 RTCpuSetAdd(pSet, idCpu);
147 } while (idCpu-- > 0);
148#else
149 RTCpuSetEmpty(pSet);
150 RTCpuSetAdd(pSet, RTMpCpuId());
151#endif
152 return pSet;
153}
154
155
156RTDECL(RTCPUID) RTMpGetOnlineCount(void)
157{
158#ifdef CONFIG_SMP
159# if defined(num_online_cpus)
160 return num_online_cpus();
161# else
162 RTCPUSET Set;
163 RTMpGetOnlineSet(&Set);
164 return RTCpuSetCount(&Set);
165# endif
166#else
167 return 1;
168#endif
169}
170
171
172/**
173 * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
174 *
175 * @param pvInfo Pointer to the RTMPARGS package.
176 */
177static void rtmpLinuxWrapper(void *pvInfo)
178{
179 PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
180 ASMAtomicIncU32(&pArgs->cHits);
181 pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
182}
183
184
185RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
186{
187 int rc;
188 RTMPARGS Args;
189
190 Args.pfnWorker = pfnWorker;
191 Args.pvUser1 = pvUser1;
192 Args.pvUser2 = pvUser2;
193 Args.idCpu = NIL_RTCPUID;
194 Args.cHits = 0;
195
196#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
197 rc = on_each_cpu(rtmpLinuxWrapper, &Args, 1 /* wait */);
198#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
199 rc = on_each_cpu(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
200
201#else /* older kernels */
202
203# ifdef preempt_disable
204 preempt_disable();
205# endif
206 rc = smp_call_function(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
207 local_irq_disable();
208 rtmpLinuxWrapper(&Args);
209 local_irq_enable();
210# ifdef preempt_enable
211 preempt_enable();
212# endif
213#endif /* older kernels */
214 Assert(rc == 0); NOREF(rc);
215 return VINF_SUCCESS;
216}
217
218
219RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
220{
221 int rc;
222 RTMPARGS Args;
223
224 Args.pfnWorker = pfnWorker;
225 Args.pvUser1 = pvUser1;
226 Args.pvUser2 = pvUser2;
227 Args.idCpu = NIL_RTCPUID;
228 Args.cHits = 0;
229
230#ifdef preempt_disable
231 preempt_disable();
232#endif
233#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
234 rc = smp_call_function(rtmpLinuxWrapper, &Args, 1 /* wait */);
235#else /* older kernels */
236 rc = smp_call_function(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
237#endif /* older kernels */
238#ifdef preempt_enable
239 preempt_enable();
240#endif
241
242 Assert(rc == 0); NOREF(rc);
243 return VINF_SUCCESS;
244}
245
246
247#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
248/**
249 * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
250 * employed by RTMpOnSpecific on older kernels that lacks smp_call_function_single.
251 *
252 * @param pvInfo Pointer to the RTMPARGS package.
253 */
254static void rtmpOnSpecificLinuxWrapper(void *pvInfo)
255{
256 PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
257 RTCPUID idCpu = RTMpCpuId();
258
259 if (idCpu == pArgs->idCpu)
260 {
261 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
262 ASMAtomicIncU32(&pArgs->cHits);
263 }
264}
265#endif
266
267
268RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
269{
270 int rc;
271 RTMPARGS Args;
272
273 Args.pfnWorker = pfnWorker;
274 Args.pvUser1 = pvUser1;
275 Args.pvUser2 = pvUser2;
276 Args.idCpu = idCpu;
277 Args.cHits = 0;
278
279 if (!RTMpIsCpuPossible(idCpu))
280 return VERR_CPU_NOT_FOUND;
281
282# ifdef preempt_disable
283 preempt_disable();
284# endif
285 if (idCpu != RTMpCpuId())
286 {
287 if (RTMpIsCpuOnline(idCpu))
288 {
289#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
290 rc = smp_call_function_single(idCpu, rtmpLinuxWrapper, &Args, 1 /* wait */);
291#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
292 rc = smp_call_function_single(idCpu, rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
293#else /* older kernels */
294 rc = smp_call_function(rtmpOnSpecificLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
295#endif /* older kernels */
296 Assert(rc == 0);
297 rc = Args.cHits ? VINF_SUCCESS : VERR_CPU_OFFLINE;
298 }
299 else
300 rc = VERR_CPU_OFFLINE;
301 }
302 else
303 {
304 rtmpLinuxWrapper(&Args);
305 rc = VINF_SUCCESS;
306 }
307# ifdef preempt_enable
308 preempt_enable();
309# endif
310
311 NOREF(rc);
312 return rc;
313}
314
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