timer-r0drv-solaris.c revision 1c40a35cf13ebdc58846245af594c36070bcc015
* Copyright (C) 2006-2014 Oracle Corporation * This file is part of VirtualBox Open Source Edition (OSE), as * you can redistribute it and/or modify it under the terms of the GNU * 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. /******************************************************************************* *******************************************************************************/ /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ * The internal representation of a Solaris timer handle. * This is RTTIMER_MAGIC, but changes to something else before the timer * is destroyed to indicate clearly that thread should exit. */ /** Reference counter. */ /** Flag indicating that the timer is suspended (hCyclicId should be /** Flag indicating that the timer was suspended from the timer callback and * therefore the hCyclicId may still be valid. */ /** Flag indicating that the timer interval was changed and that it requires * manual expiration time programming for each callout. */ /** Whether the timer must run on all CPUs or not. */ /** Whether the timer must run on a specific CPU or not. */ /** The CPU it must run on if fSpecificCpu is set. */ /** The nano second interval for repeating timers. */ /** Cyclic timer Id. This is CYCLIC_NONE if no active timer. * @remarks Please keep in mind that cyclic may call us back before the * unguarded with cyclic_reprogram. */ /** The user callback. */ /** The argument for the user callback. */ /** Union with timer type specific data. */ /** Single timer (fAllCpus == false). */ /** Cyclic time and interval representation. */ /** The next tick when fIntervalChanged is true, otherwise 0. */ /** The (interrupt) thread currently active in the callback. */ /** Omni timer (fAllCpus == true). */ /** Absolute timestamp of when the timer should fire first when starting up. */ /** Array of per CPU data (variable size). */ /** Timer ticks (reinitialized when online'd). */ /** The (interrupt) thread currently active in the callback. */ /** The next tick when fIntervalChanged is true, otherwise 0. */ /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /** Validates that the timer is valid. */ /******************************************************************************* *******************************************************************************/ * Retains a reference to the timer. * @returns New reference counter value. * @param pTimer The timer. * Destroys the timer when the reference counter has reached zero. * @returns 0 (new references counter value). * @param pTimer The timer. * Releases a reference to the timer. * @returns New reference counter value. * @param pTimer The timer. * RTMpOnSpecific callback used by rtTimerSolCallbackWrapper() to deal with * callouts on the wrong CPU (race with cyclic_bind). * @param idCpu The CPU this is fired on. * @param pvUser1 Opaque pointer to the timer. * @param pvUser2 Not used, NULL. /* This avoids some code duplication. */ * Callback wrapper for single-CPU timers. * @param pvArg Opaque pointer to the timer. * @remarks This will be executed in interrupt context but only at the specified * level i.e. CY_LOCK_LEVEL in our case. We -CANNOT- call into the * cyclic subsystem here, neither should pfnTimer(). /* Make sure one-shots do not fire another time. */ /* Make sure we are firing on the right CPU. */ /* For one-shot, we may allow the callback to restart them. */ * The interval was changed, we need to set the expiration time * ourselves before returning. This comes at a slight cost, * which is why we don't do it all the time. * The timer has been suspended, set expiration time to infinitiy. * Callback wrapper for Omni-CPU timers. * @param pvArg Opaque pointer to the timer. * @remarks This will be executed in interrupt context but only at the specified * level i.e. CY_LOCK_LEVEL in our case. We -CANNOT- call into the * cyclic subsystem here, neither should pfnTimer(). * The interval was changed, we need to set the expiration time * ourselves before returning. This comes at a slight cost, * which is why we don't do it all the time. * Note! The cyclic_reprogram call only affects the omni cyclic * component for this CPU. * The timer has been suspended, set expiration time to infinitiy. * Omni-CPU cyclic online event. This is called before the omni cycle begins to * fire on the specified CPU. * @param pvArg Opaque pointer to the timer. * @param pCpu Pointer to the CPU on which it will fire. * @param pCyclicHandler Pointer to a cyclic handler to add to the CPU * @param pCyclicTime Pointer to the cyclic time and interval object. * @remarks We -CANNOT- call back into the cyclic subsystem here, we can however /* One-shot omni timers are not supported by the cyclic system. */ * Allocate and initialize the timer handle. The omni variant has a * variable sized array of ticks counts, thus the size calculation. * Checks if the calling thread is currently executing the timer proceduce for * @returns true if it is, false if it isn't. * @param pTimer The timer in question. * It is not possible to destroy a timer from it's callback function. * Cyclic makes that impossible (or at least extremely risky). * Invalidate the handle, make sure it's stopped nad free the associated resources. * It's not possible to restart a one-shot time from it's callback function, * at least not at the moment. * Make sure it's not active already. If it was suspended from a timer * callback function, we need to do some cleanup work here before we can * Setup omni (all CPU) timer. The Omni-CPU online event will fire * and from there we setup periodic timers per CPU. * Setup a single CPU timer. If a specific CPU was requested, it * must be online or the timer cannot start. /** @todo we probably don't need to have cyc_handler_t and cyc_time_t in the * Use a large interval (1 hour) so that we don't get a timer-callback between * cyclic_add() and cyclic_bind(). Program the correct interval once cyclic_bind() is done. * See @bugref{7691} comment #20. * Worker common for RTTimerStop and RTTimerDestroy. * @param pTimer The timer to stop. /* Trying the cpu_lock stuff and calling cyclic_remove may deadlock the system, so just mark the timer as suspened and deal with it in the callback wrapper function above. */