d38598568c6e70e0644317f24dc89e1221218524vboxsync * IPRT - Linux Ring-0 Driver Helpers for Abstracting Wait Queues,
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Copyright (C) 2006-2010 Oracle Corporation
d38598568c6e70e0644317f24dc89e1221218524vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d38598568c6e70e0644317f24dc89e1221218524vboxsync * available from http://www.virtualbox.org. This file is free software;
d38598568c6e70e0644317f24dc89e1221218524vboxsync * you can redistribute it and/or modify it under the terms of the GNU
d38598568c6e70e0644317f24dc89e1221218524vboxsync * General Public License (GPL) as published by the Free Software
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
d38598568c6e70e0644317f24dc89e1221218524vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d38598568c6e70e0644317f24dc89e1221218524vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * The contents of this file may alternatively be used under the terms
d38598568c6e70e0644317f24dc89e1221218524vboxsync * of the Common Development and Distribution License Version 1.0
d38598568c6e70e0644317f24dc89e1221218524vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
d38598568c6e70e0644317f24dc89e1221218524vboxsync * VirtualBox OSE distribution, in which case the provisions of the
d38598568c6e70e0644317f24dc89e1221218524vboxsync * CDDL are applicable instead of those of the GPL.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * You may elect to license modified versions of this file under the
d38598568c6e70e0644317f24dc89e1221218524vboxsync * terms and conditions of either the GPL or the CDDL or both.
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync/** The resolution (nanoseconds) specified when using
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync * schedule_hrtimeout_range. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Kernel mode Linux wait state structure.
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** The wait queue entry. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** The absolute timeout given as nano seconds since the start of the
d38598568c6e70e0644317f24dc89e1221218524vboxsync * monotonic clock. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** The timeout in nano seconds relative to the start of the wait. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** The native timeout value. */
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync /** The timeout when fHighRes is true. Absolute, so no updating. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** The timeout when fHighRes is false. Updated after waiting. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** Set if we use high resolution timeouts. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** Set if it's an indefinite wait. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** Set if we've already timed out.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Set by rtR0SemLnxWaitDoIt and read by rtR0SemLnxWaitHasTimedOut. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync /** The wait queue. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync/** Pointer to a linux wait state. */
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Initializes a wait.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * The caller MUST check the wait condition BEFORE calling this function or the
d38598568c6e70e0644317f24dc89e1221218524vboxsync * timeout logic will be flawed.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @returns VINF_SUCCESS or VERR_TIMEOUT.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @param pWait The wait structure.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @param fFlags The wait flags.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @param uTimeout The timeout.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @param pWaitQueue The wait queue head.
d38598568c6e70e0644317f24dc89e1221218524vboxsyncDECLINLINE(int) rtR0SemLnxWaitInit(PRTR0SEMLNXWAIT pWait, uint32_t fFlags, uint64_t uTimeout,
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Process the flags and timeout.
d38598568c6e70e0644317f24dc89e1221218524vboxsync/** @todo optimize: millisecs -> nanosecs -> millisec -> jiffies */
446339370a612cb2cf7d523122584ac05b59b0devboxsync uTimeout = uTimeout < UINT64_MAX / RT_US_1SEC * RT_US_1SEC
d38598568c6e70e0644317f24dc89e1221218524vboxsync if ( (fFlags & (RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE))
446339370a612cb2cf7d523122584ac05b59b0devboxsync && pWait->uNsAbsTimeout >= KTIME_SEC_MAX * RT_NS_1SEC_64 + (RT_NS_1SEC - 1))
d38598568c6e70e0644317f24dc89e1221218524vboxsync pWait->u.KtTimeout = ns_to_ktime(pWait->uNsAbsTimeout);
446339370a612cb2cf7d523122584ac05b59b0devboxsync uint64_t cJiffies = ASMMultU64ByU32DivByU32(pWait->cNsRelTimeout, HZ, RT_NS_1SEC);
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Initialize the wait queue related bits.
d38598568c6e70e0644317f24dc89e1221218524vboxsync pWait->iWaitState = fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Prepares the next wait.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * This must be called before rtR0SemLnxWaitDoIt, and the caller should check
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * the exit conditions in-between the two calls.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @param pWait The wait structure.
d38598568c6e70e0644317f24dc89e1221218524vboxsyncDECLINLINE(void) rtR0SemLnxWaitPrepare(PRTR0SEMLNXWAIT pWait)
d38598568c6e70e0644317f24dc89e1221218524vboxsync /* Make everything thru schedule*() atomic scheduling wise. (Is this correct?) */
d38598568c6e70e0644317f24dc89e1221218524vboxsync prepare_to_wait(pWait->pWaitQueue, &pWait->WaitQE, pWait->iWaitState);
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Do the actual wait.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @param pWait The wait structure.
d38598568c6e70e0644317f24dc89e1221218524vboxsyncDECLINLINE(void) rtR0SemLnxWaitDoIt(PRTR0SEMLNXWAIT pWait)
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync int rc = schedule_hrtimeout_range(&pWait->u.KtTimeout, HRTIMER_MODE_ABS, RTR0SEMLNXWAIT_RESOLUTION);
d38598568c6e70e0644317f24dc89e1221218524vboxsync pWait->u.lTimeout = schedule_timeout(pWait->u.lTimeout);
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Checks if a linux wait was interrupted.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @returns true / false
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @param pWait The wait structure.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @remarks This shall be called before the first rtR0SemLnxWaitDoIt().
d38598568c6e70e0644317f24dc89e1221218524vboxsyncDECLINLINE(bool) rtR0SemLnxWaitWasInterrupted(PRTR0SEMLNXWAIT pWait)
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Checks if a linux wait has timed out.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @returns true / false
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @param pWait The wait structure.
d38598568c6e70e0644317f24dc89e1221218524vboxsyncDECLINLINE(bool) rtR0SemLnxWaitHasTimedOut(PRTR0SEMLNXWAIT pWait)
d38598568c6e70e0644317f24dc89e1221218524vboxsync * Deletes a linux wait.
d38598568c6e70e0644317f24dc89e1221218524vboxsync * @param pWait The wait structure.
d38598568c6e70e0644317f24dc89e1221218524vboxsyncDECLINLINE(void) rtR0SemLnxWaitDelete(PRTR0SEMLNXWAIT pWait)
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync * Gets the max resolution of the timeout machinery.
e0e7da0420be1398d23ffa9953686d3a43619abdvboxsync * @returns Resolution specified in nanoseconds.