VirtualBox

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

Last change on this file since 8245 was 8245, checked in by vboxsync, 17 years ago

rebranding: IPRT files again.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.0 KB
Line 
1/* $Id: mp-r0drv-linux.c 8245 2008-04-21 17:24:28Z 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 ? idCpu : -1;
53}
54
55
56RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
57{
58 return iCpu < NR_CPUS ? iCpu : NIL_RTCPUID;
59}
60
61
62RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
63{
64 return NR_CPUS - 1; //???
65}
66
67
68RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
69{
70#ifdef CONFIG_SMP
71 if (RT_UNLIKELY(idCpu >= NR_CPUS))
72 return false;
73# ifdef cpu_online
74 return cpu_online(idCpu);
75# else /* 2.4: */
76 return cpu_online_map & RT_BIT_64(idCpu);
77# endif
78#else
79 return idCpu == RTMpCpuId();
80#endif
81}
82
83
84RTDECL(bool) RTMpDoesCpuExist(RTCPUID idCpu)
85{
86#ifdef CONFIG_SMP
87 if (RT_UNLIKELY(idCpu >= NR_CPUS))
88 return false;
89# ifdef CONFIG_HOTPLUG_CPU /* introduced & uses cpu_present */
90 return cpu_present(idCpu);
91# elif defined(cpu_possible)
92 return cpu_possible(idCpu);
93# else /* 2.4: */
94 return idCpu < (RTCPUID)smp_num_cpus;
95# endif
96#else
97 return idCpu == RTMpCpuId();
98#endif
99}
100
101
102RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
103{
104 RTCPUID idCpu;
105
106 RTCpuSetEmpty(pSet);
107 idCpu = RTMpGetMaxCpuId();
108 do
109 {
110 if (RTMpDoesCpuExist(idCpu))
111 RTCpuSetAdd(pSet, idCpu);
112 } while (idCpu-- > 0);
113 return pSet;
114}
115
116
117RTDECL(RTCPUID) RTMpGetCount(void)
118{
119#ifdef CONFIG_SMP
120# if defined(CONFIG_HOTPLUG_CPU) /* introduced & uses cpu_present */
121 return num_present_cpus();
122# elif defined(num_possible_cpus)
123 return num_possible_cpus();
124# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
125 return smp_num_cpus;
126# else
127 RTCPUSET Set;
128 RTMpGetSet(&Set);
129 return RTCpuSetCount(&Set);
130# endif
131#else
132 return 1;
133#endif
134}
135
136
137RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
138{
139#ifdef CONFIG_SMP
140 RTCPUID idCpu;
141
142 RTCpuSetEmpty(pSet);
143 idCpu = RTMpGetMaxCpuId();
144 do
145 {
146 if (RTMpIsCpuOnline(idCpu))
147 RTCpuSetAdd(pSet, idCpu);
148 } while (idCpu-- > 0);
149#else
150 RTCpuSetEmpty(pSet);
151 RTCpuSetAdd(pSet, RTMpCpuId());
152#endif
153 return pSet;
154}
155
156
157RTDECL(RTCPUID) RTMpGetOnlineCount(void)
158{
159#ifdef CONFIG_SMP
160# if defined(num_online_cpus)
161 return num_online_cpus();
162# else
163 RTCPUSET Set;
164 RTMpGetOnlineSet(&Set);
165 return RTCpuSetCount(&Set);
166# endif
167#else
168 return 1;
169#endif
170}
171
172
173/**
174 * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
175 *
176 * @param pvInfo Pointer to the RTMPARGS package.
177 */
178static void rtmpLinuxWrapper(void *pvInfo)
179{
180 PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
181 ASMAtomicIncU32(&pArgs->cHits);
182 pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
183}
184
185
186RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
187{
188 int rc;
189 RTMPARGS Args;
190
191 Args.pfnWorker = pfnWorker;
192 Args.pvUser1 = pvUser1;
193 Args.pvUser2 = pvUser2;
194 Args.idCpu = NIL_RTCPUID;
195 Args.cHits = 0;
196
197#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
198 rc = on_each_cpu(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
199
200#else /* older kernels */
201
202# ifdef preempt_disable
203 preempt_disable();
204# endif
205 rc = smp_call_function(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
206 local_irq_disable();
207 rtmpLinuxWrapper(&Args);
208 local_irq_enable();
209# ifdef preempt_enable
210 preempt_enable();
211# endif
212#endif /* older kernels */
213 Assert(rc == 0); NOREF(rc);
214 return VINF_SUCCESS;
215}
216
217
218RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
219{
220 int rc;
221 RTMPARGS Args;
222
223 Args.pfnWorker = pfnWorker;
224 Args.pvUser1 = pvUser1;
225 Args.pvUser2 = pvUser2;
226 Args.idCpu = NIL_RTCPUID;
227 Args.cHits = 0;
228
229# ifdef preempt_disable
230 preempt_disable();
231# endif
232 rc = smp_call_function(rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
233# ifdef preempt_enable
234 preempt_enable();
235# endif
236
237 Assert(rc == 0); NOREF(rc);
238 return VINF_SUCCESS;
239}
240
241
242#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
243/**
244 * Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
245 * employed by RTMpOnSpecific on older kernels that lacks smp_call_function_single.
246 *
247 * @param pvInfo Pointer to the RTMPARGS package.
248 */
249static void rtmpOnSpecificLinuxWrapper(void *pvInfo)
250{
251 PRTMPARGS pArgs = (PRTMPARGS)pvInfo;
252 RTCPUID idCpu = RTMpCpuId();
253
254 if (idCpu == pArgs->idCpu)
255 {
256 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
257 ASMAtomicIncU32(&pArgs->cHits);
258 }
259}
260#endif
261
262
263RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
264{
265 int rc;
266 RTMPARGS Args;
267
268 Args.pfnWorker = pfnWorker;
269 Args.pvUser1 = pvUser1;
270 Args.pvUser2 = pvUser2;
271 Args.idCpu = idCpu;
272 Args.cHits = 0;
273
274 if (!RTMpDoesCpuExist(idCpu))
275 return VERR_CPU_NOT_FOUND;
276
277# ifdef preempt_disable
278 preempt_disable();
279# endif
280 if (idCpu != RTMpCpuId())
281 {
282 if (RTMpIsCpuOnline(idCpu))
283 {
284#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
285 rc = smp_call_function_single(idCpu, rtmpLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
286#else
287 rc = smp_call_function(rtmpOnSpecificLinuxWrapper, &Args, 0 /* retry */, 1 /* wait */);
288#endif
289 Assert(rc == 0);
290 rc = Args.cHits ? VINF_SUCCESS : VERR_CPU_OFFLINE;
291 }
292 else
293 rc = VERR_CPU_OFFLINE;
294 }
295 else
296 {
297 rtmpLinuxWrapper(&Args);
298 rc = VINF_SUCCESS;
299 }
300# ifdef preempt_enable
301 preempt_enable();
302# endif
303
304 NOREF(rc);
305 return rc;
306}
307
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