timer-r0drv-os2.cpp revision 590bfe12ce22cd3716448fbb9f4dc51664bfe5e2
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Memory Allocation, Ring-0 Driver, OS/2.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Permission is hereby granted, free of charge, to any person
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * obtaining a copy of this software and associated documentation
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * files (the "Software"), to deal in the Software without
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * restriction, including without limitation the rights to use,
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * copy, modify, merge, publish, distribute, sublicense, and/or sell
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * copies of the Software, and to permit persons to whom the
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Software is furnished to do so, subject to the following
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * conditions:
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * The above copyright notice and this permission notice shall be
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * included in all copies or substantial portions of the Software.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * OTHER DEALINGS IN THE SOFTWARE.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync/*******************************************************************************
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync* Header Files *
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync*******************************************************************************/
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync/*******************************************************************************
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync* Structures and Typedefs *
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync*******************************************************************************/
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * The internal representation of an OS/2 timer handle.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsynctypedef struct RTTIMER
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * This is RTTIMER_MAGIC, but changes to something else before the timer
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * is destroyed to indicate clearly that thread should exit. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /** The next timer in the timer list. */
9621896680fea9b2078823e8ef2e64cec5bf2da0vboxsync /** Flag indicating the timer is suspended. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /** Cleared at the start of timer processing, set when calling pfnTimer.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * If any timer changes occures while doing the callback this will be used to resume the cycle. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /** Callback. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /** User argument. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /** The timer interval. 0 if one-shot. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /** The start of the current run.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * This is used to calculate when the timer ought to fire the next time. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /** The start of the current run.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * This is used to calculate when the timer ought to fire the next time. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /** The current tick number (since u64StartTS). */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync/*******************************************************************************
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync* Global Variables *
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync*******************************************************************************/
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync/** Spinlock protecting the timers. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync/** The timer head. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync/** The number of active timers. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync/** The number of active timers. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync/** The change number.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * This is used to detect list changes during the timer callback loop. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync/*******************************************************************************
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync* Internal Functions *
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync*******************************************************************************/
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsyncRTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, unsigned fFlags, PFNRTTIMER pfnTimer, void *pvUser)
3f1eb07aba9eee6394f3084c956149ee9a27df09vboxsync * We don't support the fancy MP features.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Lazy initialize the spinlock.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync //bool fRc;
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync //ASMAtomicCmpXchgSize(&g_Spinlock, Spinlock, NIL_RTSPINLOCK, fRc);
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync //if (!fRc)
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync if (!ASMAtomicCmpXchgPtr((void * volatile *)&g_Spinlock, Spinlock, NIL_RTSPINLOCK))
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Allocate and initialize the timer handle.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer));
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Insert the timer into the list (LIFO atm).
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Validates the timer handle.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * @returns true if valid, false if invalid.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * @param pTimer The handle.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, false);
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync return true;
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /* It's ok to pass NULL pointer. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Remove it from the list.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Free the associated resources.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsyncRTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First)
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Calc when it should start fireing and give the thread a kick so it get going.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync pTimer->fDone = true; /* next tick, not current! */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Suspend the timer.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Query the current time and then take the lock.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Clear the fDone flag.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync for (pTimer = g_pTimerHead; pTimer; pTimer = pTimer->pNext)
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync * Walk the timer list and do the callbacks for any active timer.
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /* calculate the next timeout */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync pTimer->u64NextTS = pTimer->u64StartTS + pTimer->iTick * pTimer->u64NanoInterval;
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync pTimer->u64NextTS = u64NanoTS + RTTimerGetSystemGranularity() / 2;
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /* do the callout */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsync /* check if anything changed. */
d1c5a03c19683c719b94496bb998fde2f2e5e622vboxsyncRTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted)