timer-r0drv-os2.cpp revision 3f1eb07aba9eee6394f3084c956149ee9a27df09
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/* $Id$ */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/** @file
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * IPRT - Memory Allocation, Ring-0 Driver, OS/2.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Permission is hereby granted, free of charge, to any person
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * obtaining a copy of this software and associated documentation
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * files (the "Software"), to deal in the Software without
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * restriction, including without limitation the rights to use,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * copy, modify, merge, publish, distribute, sublicense, and/or sell
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * copies of the Software, and to permit persons to whom the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Software is furnished to do so, subject to the following
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * conditions:
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * The above copyright notice and this permission notice shall be
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * included in all copies or substantial portions of the Software.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
7b9f0c34e9ea328981c99e97054bdf8684d9d620vboxsync * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * OTHER DEALINGS IN THE SOFTWARE.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync/*******************************************************************************
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync* Header Files *
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync*******************************************************************************/
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync#include "the-os2-kernel.h"
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync#include <iprt/timer.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/time.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/spinlock.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/err.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/asm.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/assert.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/alloc.h>
13f1ce3859ee77d9b9f4d2ca9f93e1633cb133bcvboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include "internal/magics.h"
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*******************************************************************************
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync* Structures and Typedefs *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync*******************************************************************************/
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * The internal representation of an OS/2 timer handle.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsynctypedef struct RTTIMER
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Magic.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * This is RTTIMER_MAGIC, but changes to something else before the timer
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * is destroyed to indicate clearly that thread should exit. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync uint32_t volatile u32Magic;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** The next timer in the timer list. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync PRTTIMER pNext;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync /** Flag indicating the the timer is suspended. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync uint8_t volatile fSuspended;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /** Cleared at the start of timer processing, set when calling pfnTimer.
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync * If any timer changes occures while doing the callback this will be used to resume the cycle. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync bool fDone;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** Callback. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PFNRTTIMER pfnTimer;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /** User argument. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync void *pvUser;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync /** The timer interval. 0 if one-shot. */
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync uint64_t u64NanoInterval;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync /** The start of the current run.
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync * This is used to calculate when the timer ought to fire the next time. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync uint64_t volatile u64StartTS;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /** The start of the current run.
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync * This is used to calculate when the timer ought to fire the next time. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync uint64_t volatile u64NextTS;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /** The current tick number (since u64StartTS). */
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync uint64_t volatile iTick;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync} RTTIMER;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync/*******************************************************************************
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync* Global Variables *
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync*******************************************************************************/
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync/** Spinlock protecting the timers. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncstatic RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync/** The timer head. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncstatic PRTTIMER volatile g_pTimerHead = NULL;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync/** The number of active timers. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncstatic uint32_t volatile g_cActiveTimers = 0;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync/** The number of active timers. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncstatic uint32_t volatile g_cTimers = 0;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync/** The change number.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync * This is used to detect list changes during the timer callback loop. */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncstatic uint32_t volatile g_u32ChangeNo;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync/*******************************************************************************
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync* Internal Functions *
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync*******************************************************************************/
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync__BEGIN_DECLS
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncDECLASM(void) rtTimerOs2Tick(void);
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncDECLASM(int) rtTimerOs2Arm(void);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncDECLASM(int) rtTimerOs2Dearm(void);
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync__END_DECLS
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncRTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *ppTimer = NULL;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * We don't support the fancy MP features.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return VERR_NOT_SUPPORTED;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Lazy initialize the spinlock.
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync */
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync if (g_Spinlock == NIL_RTSPINLOCK)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync RTSPINLOCK Spinlock;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync int rc = RTSpinlockCreate(&Spinlock);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertRCReturn(rc, rc);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync //bool fRc;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync //ASMAtomicCmpXchgSize(&g_Spinlock, Spinlock, NIL_RTSPINLOCK, fRc);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync //if (!fRc)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (!ASMAtomicCmpXchgPtr((void * volatile *)&g_Spinlock, Spinlock, NIL_RTSPINLOCK))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync RTSpinlockDestroy(Spinlock);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Allocate and initialize the timer handle.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (!pTimer)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return VERR_NO_MEMORY;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pTimer->u32Magic = RTTIMER_MAGIC;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pTimer->pNext = NULL;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pTimer->fSuspended = true;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync pTimer->pfnTimer = pfnTimer;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync pTimer->pvUser = pvUser;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync pTimer->u64NanoInterval = u64NanoInterval;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync pTimer->u64StartTS = 0;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /*
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync * Insert the timer into the list (LIFO atm).
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync g_u32ChangeNo++;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync pTimer->pNext = g_pTimerHead;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync g_pTimerHead = pTimer;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync g_cTimers++;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync *ppTimer = pTimer;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync return VINF_SUCCESS;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync}
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync * Validates the timer handle.
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync *
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync * @returns true if valid, false if invalid.
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync * @param pTimer The handle.
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncDECLINLINE(bool) rtTimerIsValid(PRTTIMER pTimer)
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync{
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync AssertReturn(VALID_PTR(pTimer), false);
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, false);
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync return true;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync}
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsyncRTDECL(int) RTTimerDestroy(PRTTIMER pTimer)
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync{
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync /* It's ok to pass NULL pointer. */
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync if (pTimer == /*NIL_RTTIMER*/ NULL)
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync return VINF_SUCCESS;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync if (!rtTimerIsValid(pTimer))
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync return VERR_INVALID_HANDLE;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /*
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync * Remove it from the list.
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync g_u32ChangeNo++;
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync if (g_pTimerHead == pTimer)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync g_pTimerHead = pTimer->pNext;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync else
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PRTTIMER pPrev = g_pTimerHead;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync while (pPrev->pNext != pTimer)
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pPrev = pPrev->pNext;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (RT_UNLIKELY(!pPrev))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync return VERR_INVALID_HANDLE;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync }
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync }
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync pPrev->pNext = pTimer->pNext;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync }
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync Assert(g_cTimers > 0);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync g_cTimers--;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync if (!pTimer->fSuspended)
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync {
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync Assert(g_cActiveTimers > 0);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync g_cActiveTimers--;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync if (!g_cActiveTimers)
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync rtTimerOs2Dearm();
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync }
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync /*
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync * Free the associated resources.
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync */
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync pTimer->u32Magic++;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync RTMemFree(pTimer);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync return VINF_SUCCESS;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync}
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncRTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First)
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync{
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync if (!rtTimerIsValid(pTimer))
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync return VERR_INVALID_HANDLE;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync if (!pTimer->fSuspended)
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync return VERR_TIMER_ACTIVE;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync /*
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync * Calc when it should start fireing and give the thread a kick so it get going.
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync u64First += RTTimeNanoTS();
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync g_u32ChangeNo++;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync if (!g_cActiveTimers)
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync {
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync int rc = rtTimerOs2Arm();
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync if (RT_FAILURE(rc))
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync {
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync return rc;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync }
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync }
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync g_cActiveTimers++;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync pTimer->fSuspended = false;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync pTimer->fDone = true; /* next tick, not current! */
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync pTimer->iTick = 0;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync pTimer->u64StartTS = u64First;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync pTimer->u64NextTS = u64First;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync return VINF_SUCCESS;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync}
b8bb9c9f6b8ebfd0a7d6df0c0289f9fe80241750vboxsync
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsyncRTDECL(int) RTTimerStop(PRTTIMER pTimer)
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync{
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync if (!rtTimerIsValid(pTimer))
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync return VERR_INVALID_HANDLE;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync if (pTimer->fSuspended)
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync return VERR_TIMER_SUSPENDED;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync /*
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync * Suspend the timer.
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync g_u32ChangeNo++;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync pTimer->fSuspended = true;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync Assert(g_cActiveTimers > 0);
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync g_cActiveTimers--;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync if (!g_cActiveTimers)
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync rtTimerOs2Dearm();
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync return VINF_SUCCESS;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync}
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync
8bc8d66f188d5357155b8340e2d489573be2b607vboxsyncDECLASM(void) rtTimerOs2Tick(void)
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync{
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Query the current time and then take the lock.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync const uint64_t u64NanoTS = RTTimeNanoTS();
RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
/*
* Clear the fDone flag.
*/
PRTTIMER pTimer;
for (pTimer = g_pTimerHead; pTimer; pTimer = pTimer->pNext)
pTimer->fDone = false;
/*
* Walk the timer list and do the callbacks for any active timer.
*/
uint32_t u32CurChangeNo = g_u32ChangeNo;
pTimer = g_pTimerHead;
while (pTimer)
{
PRTTIMER pNext = pTimer->pNext;
if ( !pTimer->fSuspended
&& !pTimer->fDone
&& pTimer->u64NextTS <= u64NanoTS)
{
pTimer->fDone = true;
/* calculate the next timeout */
if (!pTimer->u64NanoInterval)
pTimer->fSuspended = true;
else
{
pTimer->u64NextTS = pTimer->u64StartTS + pTimer->iTick * pTimer->u64NanoInterval;
if (pTimer->u64NextTS < u64NanoTS)
pTimer->u64NextTS = u64NanoTS + RTTimerGetSystemGranularity() / 2;
}
/* do the callout */
PFNRTTIMER pfnTimer = pTimer->pfnTimer;
void *pvUser = pTimer->pvUser;
RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
pfnTimer(pTimer, pvUser);
RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
/* check if anything changed. */
if (u32CurChangeNo != g_u32ChangeNo)
{
u32CurChangeNo = g_u32ChangeNo;
pNext = g_pTimerHead;
}
}
/* next */
pTimer = pNext;
}
RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
}
RTDECL(uint32_t) RTTimerGetSystemGranularity(void)
{
return 32000000; /* 32ms */
}
RTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted)
{
return VERR_NOT_SUPPORTED;
}
RTDECL(int) RTTimerReleaseSystemGranularity(uint32_t u32Granted)
{
return VERR_NOT_SUPPORTED;
}