mpnotification-r0drv-linux.c revision a472a75ac0d6a734757b66608170c9d67d441722
/* $Id$ */
/** @file
* IPRT - Multiprocessor Event Notifications, Ring-0 Driver, Linux.
*/
/*
* Copyright (C) 2008-2015 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 <iprt/asm-amd64-x86.h>
#include "r0drv/mp-r0drv.h"
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
static int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu);
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/**
* The notifier block we use for registering the callback.
*/
static struct notifier_block g_NotifierBlock =
{
.priority = 0
};
# ifdef CPU_DOWN_FAILED
/**
* The set of CPUs we've seen going offline recently.
*/
static RTCPUSET g_MpPendingOfflineSet;
# endif
/**
* The native callback.
*
* @returns NOTIFY_DONE.
* @param pNotifierBlock Pointer to g_NotifierBlock.
* @param ulNativeEvent The native event.
* @param pvCpu The cpu id cast into a pointer value.
*
* @remarks This can fire with preemption enabled and on any CPU.
*/
static int rtMpNotificationLinuxCallback(struct notifier_block *pNotifierBlock, unsigned long ulNativeEvent, void *pvCpu)
{
bool fProcessEvent = false;
/*
* back to their 2.6.18-92.1.10.el5 kernel but actually don't
* use them. Thus we have to test for both CPU_TASKS_FROZEN and
* the individual event variants.
*/
switch (ulNativeEvent)
{
/*
* Pick up online events or failures to go offline.
* Ignore failure events for CPUs we didn't see go offline.
*/
# ifdef CPU_DOWN_FAILED
case CPU_DOWN_FAILED:
# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_FAILED_FROZEN)
case CPU_DOWN_FAILED_FROZEN:
# endif
break; /* fProcessEvents = false */
/* fall thru */
# endif
case CPU_ONLINE:
# if defined(CPU_TASKS_FROZEN) && defined(CPU_ONLINE_FROZEN)
case CPU_ONLINE_FROZEN:
# endif
# ifdef CPU_DOWN_FAILED
# endif
fProcessEvent = true;
break;
/*
* Pick the earliest possible offline event.
* The only important thing here is that we get the event and that
* it's exactly one.
*/
# ifdef CPU_DOWN_PREPARE
case CPU_DOWN_PREPARE:
# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_PREPARE_FROZEN)
case CPU_DOWN_PREPARE_FROZEN:
# endif
fProcessEvent = true;
# else
case CPU_DEAD:
# if defined(CPU_TASKS_FROZEN) && defined(CPU_DEAD_FROZEN)
case CPU_DEAD_FROZEN:
# endif
/* Don't process CPU_DEAD notifications. */
# endif
# ifdef CPU_DOWN_FAILED
# endif
break;
}
if (!fProcessEvent)
return NOTIFY_DONE;
switch (ulNativeEvent)
{
# ifdef CPU_DOWN_FAILED
case CPU_DOWN_FAILED:
# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_FAILED_FROZEN)
case CPU_DOWN_FAILED_FROZEN:
# endif
# endif
case CPU_ONLINE:
# if defined(CPU_TASKS_FROZEN) && defined(CPU_ONLINE_FROZEN)
case CPU_ONLINE_FROZEN:
# endif
break;
# ifdef CPU_DOWN_PREPARE
case CPU_DOWN_PREPARE:
# if defined(CPU_TASKS_FROZEN) && defined(CPU_DOWN_PREPARE_FROZEN)
case CPU_DOWN_PREPARE_FROZEN:
# endif
break;
# endif
}
return NOTIFY_DONE;
}
DECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
{
int rc;
# ifdef CPU_DOWN_FAILED
# endif
return VINF_SUCCESS;
}
DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
{
}
#else /* Not supported / Not needed */
DECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
{
return VINF_SUCCESS;
}
DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
{
}
#endif /* Not supported / Not needed */