/* $Id$ */
/** @file
* IPRT - Linux Ring-0 Driver Helpers for Abstracting Wait Queues,
*/
/*
* Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* 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.
*/
#include "the-linux-kernel.h"
#include <iprt/asm-math.h>
/** The resolution (nanoseconds) specified when using
* schedule_hrtimeout_range. */
/**
* Kernel mode Linux wait state structure.
*/
typedef struct RTR0SEMLNXWAIT
{
/** The wait queue entry. */
/** The absolute timeout given as nano seconds since the start of the
* monotonic clock. */
/** The timeout in nano seconds relative to the start of the wait. */
/** The native timeout value. */
union
{
#ifdef IPRT_LINUX_HAS_HRTIMER
/** The timeout when fHighRes is true. Absolute, so no updating. */
#endif
/** The timeout when fHighRes is false. Updated after waiting. */
long lTimeout;
} u;
/** Set if we use high resolution timeouts. */
bool fHighRes;
/** Set if it's an indefinite wait. */
bool fIndefinite;
/** Set if we've already timed out.
* Set by rtR0SemLnxWaitDoIt and read by rtR0SemLnxWaitHasTimedOut. */
bool fTimedOut;
/** TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE. */
int iWaitState;
/** The wait queue. */
/** Pointer to a linux wait state. */
/**
* Initializes a wait.
*
* The caller MUST check the wait condition BEFORE calling this function or the
* timeout logic will be flawed.
*
* @returns VINF_SUCCESS or VERR_TIMEOUT.
* @param pWait The wait structure.
* @param fFlags The wait flags.
* @param uTimeout The timeout.
* @param pWaitQueue The wait queue head.
*/
{
/*
* Process the flags and timeout.
*/
if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
{
/** @todo optimize: millisecs -> nanosecs -> millisec -> jiffies */
if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
? uTimeout * RT_US_1SEC
: UINT64_MAX;
if (uTimeout == UINT64_MAX)
else
{
if (fFlags & RTSEMWAIT_FLAGS_RELATIVE)
{
if (uTimeout == 0)
return VERR_TIMEOUT;
u64Now = RTTimeSystemNanoTS();
}
else
{
u64Now = RTTimeSystemNanoTS();
return VERR_TIMEOUT;
}
}
}
if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
{
pWait->fIndefinite = false;
#ifdef IPRT_LINUX_HAS_HRTIMER
{
# if BITS_PER_LONG < 64
if ( KTIME_SEC_MAX <= LONG_MAX
else
# endif
}
else
#endif
{
if (cJiffies >= MAX_JIFFY_OFFSET)
else
{
}
}
}
if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
{
pWait->fIndefinite = true;
}
/*
* Initialize the wait queue related bits.
*/
#else
#endif
return VINF_SUCCESS;
}
/**
* Prepares the next wait.
*
* This must be called before rtR0SemLnxWaitDoIt, and the caller should check
* the exit conditions in-between the two calls.
*
* @param pWait The wait structure.
*/
{
/* Make everything thru schedule*() atomic scheduling wise. (Is this correct?) */
}
/**
* Do the actual wait.
*
* @param pWait The wait structure.
*/
{
if (pWait->fIndefinite)
schedule();
#ifdef IPRT_LINUX_HAS_HRTIMER
{
int rc = schedule_hrtimeout_range(&pWait->u.KtTimeout, HRTIMER_MODE_ABS, RTR0SEMLNXWAIT_RESOLUTION);
if (!rc)
}
#endif
else
{
}
}
/**
* Checks if a linux wait was interrupted.
*
* @returns true / false
* @param pWait The wait structure.
* @remarks This shall be called before the first rtR0SemLnxWaitDoIt().
*/
{
&& signal_pending(current);
}
/**
* Checks if a linux wait has timed out.
*
* @returns true / false
* @param pWait The wait structure.
*/
{
}
/**
* Deletes a linux wait.
*
* @param pWait The wait structure.
*/
{
}
/**
* Gets the max resolution of the timeout machinery.
*
* @returns Resolution specified in nanoseconds.
*/
{
#ifdef IPRT_LINUX_HAS_HRTIMER
return RTR0SEMLNXWAIT_RESOLUTION;
#else
#endif
}
#endif