timer-r0drv-linux.c revision b377a71756cce9f39d25b561f72bfa33ce8a39de
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * IPRT - Timers, Ring-0 Driver, Linux.
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * available from http://www.virtualbox.org. This file is free software;
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * you can redistribute it and/or modify it under the terms of the GNU
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * General Public License (GPL) as published by the Free Software
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * The contents of this file may alternatively be used under the terms
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * of the Common Development and Distribution License Version 1.0
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * VirtualBox OSE distribution, in which case the provisions of the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * CDDL are applicable instead of those of the GPL.
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * You may elect to license modified versions of this file under the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * terms and conditions of either the GPL or the CDDL or both.
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
#include "the-linux-kernel.h"
# define RT_USE_LINUX_HRTIMER
/* This check must match the ktime usage in rtTimeGetSystemNanoTS() / time-r0drv-linux.c. */
#if defined(RT_USE_LINUX_HRTIMER) \
typedef enum RTTIMERLNXSTATE
typedef struct RTTIMERLNXSUBTIMER
#ifdef RT_USE_LINUX_HRTIMER
typedef struct RTTIMER
bool volatile fSuspended;
bool fSpecificCpu;
#ifdef CONFIG_SMP
bool fAllCpus;
void *pvUser;
} RTTIMER;
typedef struct RTTIMERLINUXSTARTONCPUARGS
DECLINLINE(void) rtTimerLnxSetState(RTTIMERLNXSTATE volatile *penmState, RTTIMERLNXSTATE enmNewState)
DECLINLINE(bool) rtTimerLnxCmpXchgState(RTTIMERLNXSTATE volatile *penmState, RTTIMERLNXSTATE enmNewState, RTTIMERLNXSTATE enmCurState)
static void rtTimerLnxStartSubTimer(PRTTIMERLNXSUBTIMER pSubTimer, uint64_t u64Now, uint64_t u64First)
#ifdef RT_USE_LINUX_HRTIMER
#ifdef RT_USE_LINUX_HRTIMER
#ifdef RT_USE_LINUX_HRTIMER
* @returns HRTIMER_NORESTART or HRTIMER_RESTART depending on whether it's a one-shot or interval timer.
#ifdef RT_USE_LINUX_HRTIMER
#ifdef CONFIG_SMP
# ifdef RT_USE_LINUX_HRTIMER
#ifdef RT_USE_LINUX_HRTIMER
#ifdef RT_USE_LINUX_HRTIMER
uint64_t cJiffies = offDelta / TICK_NSEC; /* (We end up doing 64-bit div here which ever way we go.) */
else if (cJiffies == 0)
#ifdef RT_USE_LINUX_HRTIMER
return rc;
#ifdef CONFIG_SMP
* Per-cpu callback function (RTMpOnAll/RTMpOnSpecific).
* Worker for RTTimerStart() that takes care of the ugly bit.s
int rc2;
if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[iCpu].enmState, RTTIMERLNXSTATE_STOPPED, RTTIMERLNXSTATE_STARTING))
return VINF_SUCCESS;
} while (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[iCpu].enmState, RTTIMERLNXSTATE_STOPPING, enmState));
return VINF_SUCCESS;
if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_MP_STARTING, RTTIMERLNXSTATE_STOPPED))
switch (enmEvent)
case RTMPEVENT_ONLINE:
if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_MP_STARTING, RTTIMERLNXSTATE_STOPPED))
case RTMPEVENT_OFFLINE:
if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_MP_STOPPING, RTTIMERLNXSTATE_ACTIVE))
int rc2;
return VERR_TIMER_ACTIVE;
#ifdef CONFIG_SMP
return rc2;
return VINF_SUCCESS;
return VERR_TIMER_SUSPENDED;
#ifdef CONFIG_SMP
return VINF_SUCCESS;
return VINF_SUCCESS;
#ifdef CONFIG_SMP
return VINF_SUCCESS;
RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser)
unsigned cCpus;
return VERR_INVALID_PARAMETER;
#ifdef CONFIG_SMP
Assert(cCpus <= RTCPUSET_MAX_CPUS); /* On linux we have a 1:1 relationship between cpuid and set index. */
AssertReturn(u64NanoInterval, VERR_NOT_IMPLEMENTED); /* We don't implement single shot on all cpus, sorry. */
if (!pTimer)
return VERR_NO_MEMORY;
#ifdef CONFIG_SMP
pTimer->fSpecificCpu = (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL;
#ifdef RT_USE_LINUX_HRTIMER
#ifdef CONFIG_SMP
return rc;
return VINF_SUCCESS;
#ifdef RT_USE_LINUX_HRTIMER
return VERR_NOT_SUPPORTED;
return VERR_NOT_SUPPORTED;