/* $Id$ */
/** @file
* IPRT - Multiprocessor, Ring-0 Driver, Linux.
*/
/*
* Copyright (C) 2008-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "the-linux-kernel.h"
#include "r0drv/mp-r0drv.h"
{
return smp_processor_id();
}
{
return smp_processor_id();
}
{
return *pidCpu = smp_processor_id();
}
{
}
{
}
{
}
{
#if defined(CONFIG_SMP)
return false;
# if defined(cpu_possible)
return cpu_possible(idCpu);
# else /* < 2.5.29 */
# endif
#else
#endif
}
{
idCpu = RTMpGetMaxCpuId();
do
{
if (RTMpIsCpuPossible(idCpu))
} while (idCpu-- > 0);
return pSet;
}
{
#ifdef CONFIG_SMP
# if defined(CONFIG_HOTPLUG_CPU) /* introduced & uses cpu_present */
return num_present_cpus();
# elif defined(num_possible_cpus)
return num_possible_cpus();
return smp_num_cpus;
# else
RTMpGetSet(&Set);
return RTCpuSetCount(&Set);
# endif
#else
return 1;
#endif
}
{
#ifdef CONFIG_SMP
return false;
# ifdef cpu_online
return cpu_online(idCpu);
# else /* 2.4: */
# endif
#else
#endif
}
{
#ifdef CONFIG_SMP
idCpu = RTMpGetMaxCpuId();
do
{
if (RTMpIsCpuOnline(idCpu))
} while (idCpu-- > 0);
#else
#endif
return pSet;
}
{
#ifdef CONFIG_SMP
# if defined(num_online_cpus)
return num_online_cpus();
# else
return RTCpuSetCount(&Set);
# endif
#else
return 1;
#endif
}
{
/** @todo (not used on non-Windows platforms yet). */
return false;
}
/**
* Wrapper between the native linux per-cpu callbacks and PFNRTWORKER.
*
* @param pvInfo Pointer to the RTMPARGS package.
*/
{
}
/**
* Wrapper between the native linux per-cpu callbacks and PFNRTWORKER, does hit
* increment after calling the worker.
*
* @param pvInfo Pointer to the RTMPARGS package.
*/
{
}
/**
* Wrapper between the native linux all-cpu callbacks and PFNRTWORKER.
*
* @param pvInfo Pointer to the RTMPARGS package.
*/
{
{
}
}
{
int rc;
{
/* Fire the function on all other CPUs without waiting for completion. */
#else
#endif
}
/* Fire the function on this CPU. */
/* Wait for all of them finish. */
cLoops = 64000;
{
/* Periodically check if any CPU in the wait set has gone offline, if so update the wait set. */
if (!cLoops--)
{
cLoops = 64000;
}
ASMNopPause();
}
return VINF_SUCCESS;
}
{
int rc;
#else /* older kernels */
#endif /* older kernels */
return VINF_SUCCESS;
}
/**
* Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
* employed by RTMpOnPair on older kernels that lacks smp_call_function_many.
*
* @param pvInfo Pointer to the RTMPARGS package.
*/
{
{
}
}
#endif
RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
{
int rc;
/*
* Check that both CPUs are online before doing the broadcast call.
*/
if ( RTMpIsCpuOnline(idCpu1)
&& RTMpIsCpuOnline(idCpu2))
{
/*
* Use the smp_call_function variant taking a cpu mask where available,
* falling back on broadcast with filter. Slight snag if one of the
* CPUs is the one we're running on, we must do the call and the post
* call wait ourselves.
*/
#endif
#endif
rc = 0;
#else /* older kernels */
#endif /* older kernels */
/* Call ourselves if necessary and wait for the other party to be done. */
if (fCallSelf)
{
{
break;
cLoops++;
ASMNopPause();
}
}
rc = VINF_SUCCESS;
else
rc = VERR_CPU_IPE_1;
}
/*
* A CPU must be present to be considered just offline.
*/
else if ( RTMpIsCpuPresent(idCpu1)
&& RTMpIsCpuPresent(idCpu2))
else
return rc;
}
{
return true;
}
/**
* Wrapper between the native linux per-cpu callbacks and PFNRTWORKER
* employed by RTMpOnSpecific on older kernels that lacks smp_call_function_single.
*
* @param pvInfo Pointer to the RTMPARGS package.
*/
{
{
}
}
#endif
{
int rc;
if (!RTMpIsCpuPossible(idCpu))
return VERR_CPU_NOT_FOUND;
{
if (RTMpIsCpuOnline(idCpu))
{
#else /* older kernels */
#endif /* older kernels */
}
else
}
else
{
rc = VINF_SUCCESS;
}
return rc;
}
/**
* Dummy callback used by RTMpPokeCpu.
*
* @param pvInfo Ignored.
*/
{
}
#endif
{
int rc;
if (!RTMpIsCpuPossible(idCpu))
return VERR_CPU_NOT_FOUND;
if (!RTMpIsCpuOnline(idCpu))
return VERR_CPU_OFFLINE;
# else /* older kernels */
# endif /* older kernels */
return VINF_SUCCESS;
#else /* older kernels */
/* no unicast here? */
return VERR_NOT_SUPPORTED;
#endif /* older kernels */
}
{
return true;
}