timer-r0drv-freebsd.c revision 004d34f82d0e8a4d58a65cc50eacf298bc6eb956
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync/* $Id$ */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync/** @file
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * innotek Portable Runtime - Memory Allocation, Ring-0 Driver, FreeBSD.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync/*
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync *
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * Permission is hereby granted, free of charge, to any person
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * obtaining a copy of this software and associated documentation
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * files (the "Software"), to deal in the Software without
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * restriction, including without limitation the rights to use,
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * copy, modify, merge, publish, distribute, sublicense, and/or sell
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * copies of the Software, and to permit persons to whom the
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * Software is furnished to do so, subject to the following
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * conditions:
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync *
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * The above copyright notice and this permission notice shall be
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * included in all copies or substantial portions of the Software.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync *
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * OTHER DEALINGS IN THE SOFTWARE.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync/*******************************************************************************
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync* Header Files *
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync*******************************************************************************/
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync#include "the-freebsd-kernel.h"
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync#include <iprt/timer.h>
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync#include <iprt/time.h>
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync#include <iprt/spinlock.h>
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync#include <iprt/err.h>
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync#include <iprt/asm.h>
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync#include <iprt/assert.h>
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync#include <iprt/alloc.h>
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync#include "internal/magics.h"
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync/*******************************************************************************
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync* Structures and Typedefs *
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync*******************************************************************************/
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync/**
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * The internal representation of an FreeBSD timer handle.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsynctypedef struct RTTIMER
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** Magic.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * This is RTTIMER_MAGIC, but changes to something else before the timer
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * is destroyed to indicate clearly that thread should exit. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync uint32_t volatile u32Magic;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** Flag indicating the the timer is suspended. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync uint8_t volatile fSuspended;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** Whether the timer must run on a specific CPU or not. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync uint8_t fSpecificCpu;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** The CPU it must run on if fSpecificCpu is set. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync uint8_t iCpu;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** The FreeBSD callout structure. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync struct callout Callout;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** Callback. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync PFNRTTIMER pfnTimer;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** User argument. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync void *pvUser;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** The timer interval. 0 if one-shot. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync uint64_t u64NanoInterval;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** The start of the current run.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * This is used to calculate when the timer ought to fire the next time. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync uint64_t volatile u64StartTS;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** The start of the current run.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * This is used to calculate when the timer ought to fire the next time. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync uint64_t volatile u64NextTS;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /** The current tick number (since u64StartTS). */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync uint64_t volatile iTick;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync} RTTIMER;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync/*******************************************************************************
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync* Internal Functions *
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync*******************************************************************************/
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncstatic void rtTimerFreeBSDCallback(void *pvTimer);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncRTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync *ppTimer = NULL;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /*
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * Validate flags.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (!RTTIMER_FLAGS_IS_VALID(fFlags))
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_INVALID_PARAMETER;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if ( (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync && (fFlags & RTTIMER_FLAGS_CPU_MASK) > mp_maxid)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_INVALID_PARAMETER;
004d34f82d0e8a4d58a65cc50eacf298bc6eb956vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /*
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * Allocate and initialize the timer handle.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer));
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (!pTimer)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_NO_MEMORY;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->u32Magic = RTTIMER_MAGIC;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->fSuspended = true;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->fSpecificCpu = !!(fFlags & RTTIMER_FLAGS_CPU_SPECIFIC);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->iCpu = fFlags & RTTIMER_FLAGS_CPU_MASK;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->pfnTimer = pfnTimer;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->pvUser = pvUser;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->u64NanoInterval = u64NanoInterval;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->u64StartTS = 0;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync callout_init(&pTimer->Callout, CALLOUT_MPSAFE);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync *ppTimer = pTimer;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VINF_SUCCESS;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync/**
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * Validates the timer handle.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync *
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * @returns true if valid, false if invalid.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * @param pTimer The handle.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncDECLINLINE(bool) rtTimerIsValid(PRTTIMER pTimer)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync AssertReturn(VALID_PTR(pTimer), false);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, false);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return true;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncRTDECL(int) RTTimerDestroy(PRTTIMER pTimer)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /* It's ok to pass NULL pointer. */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (pTimer == /*NIL_RTTIMER*/ NULL)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VINF_SUCCESS;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (!rtTimerIsValid(pTimer))
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_INVALID_HANDLE;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /*
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * Free the associated resources.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->u32Magic++;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync callout_stop(&pTimer->Callout);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync RTMemFree(pTimer);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VINF_SUCCESS;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncRTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync struct timeval tv;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (!rtTimerIsValid(pTimer))
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_INVALID_HANDLE;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (!pTimer->fSuspended)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_TIMER_ACTIVE;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /*
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * Calc when it should start fireing.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync u64First += RTTimeNanoTS();
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->fSuspended = false;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->iTick = 0;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->u64StartTS = u64First;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->u64NextTS = u64First;
004d34f82d0e8a4d58a65cc50eacf298bc6eb956vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync tv.tv_sec = u64First / 1000000000;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync tv.tv_usec = (u64First % 1000000000) / 1000;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync callout_reset(&pTimer->Callout, tvtohz(&tv), rtTimerFreeBSDCallback, pTimer);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VINF_SUCCESS;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncRTDECL(int) RTTimerStop(PRTTIMER pTimer)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (!rtTimerIsValid(pTimer))
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_INVALID_HANDLE;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (pTimer->fSuspended)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_TIMER_SUSPENDED;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /*
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * Suspend the timer.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->fSuspended = true;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync callout_stop(&pTimer->Callout);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VINF_SUCCESS;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync/**
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * smp_rendezvous action callback.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync *
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * This will perform the timer callback if we're on the right CPU.
004d34f82d0e8a4d58a65cc50eacf298bc6eb956vboxsync *
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync * @param pvTimer The timer.
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncstatic void rtTimerFreeBSDIpiAction(void *pvTimer)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
004d34f82d0e8a4d58a65cc50eacf298bc6eb956vboxsync PRTTIMER pTimer = (PRTTIMER)pvTimer;
004d34f82d0e8a4d58a65cc50eacf298bc6eb956vboxsync if ( pTimer->iCpu == RTTIMER_FLAGS_CPU_MASK
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync || (u_int)pTimer->iCpu == curcpu)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->pfnTimer(pTimer, pTimer->pvUser);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncstatic void rtTimerFreeBSDCallback(void *pvTimer)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync PRTTIMER pTimer = (PRTTIMER)pvTimer;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /* calculate and set the next timeout */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (!pTimer->u64NanoInterval)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync {
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->fSuspended = true;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync callout_stop(&pTimer->Callout);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync }
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync else
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync {
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync struct timeval tv;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync const uint64_t u64NanoTS = RTTimeNanoTS();
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->u64NextTS = pTimer->u64StartTS + pTimer->iTick * pTimer->u64NanoInterval;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if (pTimer->u64NextTS < u64NanoTS)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->u64NextTS = u64NanoTS + RTTimerGetSystemGranularity() / 2;
004d34f82d0e8a4d58a65cc50eacf298bc6eb956vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync tv.tv_sec = pTimer->u64NextTS / 1000000000;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync tv.tv_usec = (pTimer->u64NextTS % 1000000000) / 1000;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync callout_reset(&pTimer->Callout, tvtohz(&tv), rtTimerFreeBSDCallback, pTimer);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync }
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync /* callback */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync if ( !pTimer->fSpecificCpu
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync || pTimer->iCpu == curcpu)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync pTimer->pfnTimer(pTimer, pTimer->pvUser);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync else
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync smp_rendezvous(NULL, rtTimerFreeBSDIpiAction, NULL, pvTimer);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncRTDECL(uint32_t) RTTimerGetSystemGranularity(void)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return 1000000000 / hz; /* ns */
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncRTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_NOT_SUPPORTED;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsyncRTDECL(int) RTTimerReleaseSystemGranularity(uint32_t u32Granted)
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync{
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync return VERR_NOT_SUPPORTED;
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync}
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync