diff options
Diffstat (limited to 'src/VBox/Runtime/r0drv/solaris/mpnotification-r0drv-solaris.c')
-rw-r--r-- | src/VBox/Runtime/r0drv/solaris/mpnotification-r0drv-solaris.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/VBox/Runtime/r0drv/solaris/mpnotification-r0drv-solaris.c b/src/VBox/Runtime/r0drv/solaris/mpnotification-r0drv-solaris.c new file mode 100644 index 00000000..1ba45d86 --- /dev/null +++ b/src/VBox/Runtime/r0drv/solaris/mpnotification-r0drv-solaris.c @@ -0,0 +1,139 @@ +/* $Id: mpnotification-r0drv-solaris.c $ */ +/** @file + * IPRT - Multiprocessor Event Notifications, Ring-0 Driver, Solaris. + */ + +/* + * Copyright (C) 2008-2020 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. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "the-solaris-kernel.h" +#include "internal/iprt.h" + +#include <iprt/errcore.h> +#include <iprt/mp.h> +#include <iprt/cpuset.h> +#include <iprt/string.h> +#include <iprt/thread.h> +#include "r0drv/mp-r0drv.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** Whether CPUs are being watched or not. */ +static volatile bool g_fSolCpuWatch = false; +/** Set of online cpus that is maintained by the MP callback. + * This avoids locking issues querying the set from the kernel as well as + * eliminating any uncertainty regarding the online status during the + * callback. */ +RTCPUSET g_rtMpSolCpuSet; + +/** + * Internal solaris representation for watching CPUs. + */ +typedef struct RTMPSOLWATCHCPUS +{ + /** Function pointer to Mp worker. */ + PFNRTMPWORKER pfnWorker; + /** Argument to pass to the Mp worker. */ + void *pvArg; +} RTMPSOLWATCHCPUS; +typedef RTMPSOLWATCHCPUS *PRTMPSOLWATCHCPUS; + + +/** + * Solaris callback function for Mp event notification. + * + * @returns Solaris error code. + * @param CpuState The current event/state of the CPU. + * @param iCpu Which CPU is this event for. + * @param pvArg Ignored. + * + * @remarks This function assumes index == RTCPUID. + * We may -not- be firing on the CPU going online/offline and called + * with preemption enabled. + */ +static int rtMpNotificationCpuEvent(cpu_setup_t CpuState, int iCpu, void *pvArg) +{ + RTMPEVENT enmMpEvent; + + /* + * Update our CPU set structures first regardless of whether we've been + * scheduled on the right CPU or not, this is just atomic accounting. + */ + if (CpuState == CPU_ON) + { + enmMpEvent = RTMPEVENT_ONLINE; + RTCpuSetAdd(&g_rtMpSolCpuSet, iCpu); + } + else if (CpuState == CPU_OFF) + { + enmMpEvent = RTMPEVENT_OFFLINE; + RTCpuSetDel(&g_rtMpSolCpuSet, iCpu); + } + else + return 0; + + rtMpNotificationDoCallbacks(enmMpEvent, iCpu); + NOREF(pvArg); + return 0; +} + + +DECLHIDDEN(int) rtR0MpNotificationNativeInit(void) +{ + if (ASMAtomicReadBool(&g_fSolCpuWatch) == true) + return VERR_WRONG_ORDER; + + /* + * Register the callback building the online cpu set as we do so. + */ + RTCpuSetEmpty(&g_rtMpSolCpuSet); + + mutex_enter(&cpu_lock); + register_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */); + + for (int i = 0; i < (int)RTMpGetCount(); ++i) + if (cpu_is_online(cpu[i])) + rtMpNotificationCpuEvent(CPU_ON, i, NULL /* pvArg */); + + ASMAtomicWriteBool(&g_fSolCpuWatch, true); + mutex_exit(&cpu_lock); + + return VINF_SUCCESS; +} + + +DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void) +{ + if (ASMAtomicReadBool(&g_fSolCpuWatch) == true) + { + mutex_enter(&cpu_lock); + unregister_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */); + ASMAtomicWriteBool(&g_fSolCpuWatch, false); + mutex_exit(&cpu_lock); + } +} + |