vmkdrivers/BLD/build/HEADERS/vmkapi-current/vmkernel64/release/base/vmkapi_lock.h
2015-10-23 15:21:55 -04:00

951 lines
30 KiB
C

/* **********************************************************
* Copyright 2007 - 2009 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* Spinlocks */ /**
* \defgroup Spinlocks Spin Locks
*
* \par Lock and Timer Ranks:
* All locks are associated with a numeric major rank \em R and a
* numeric minor rank \em r. While holding lock \em L1 (ranks: \em R1,
* \em r1) a lock \em L2 (ranks: \em R2, \em r2) can be acquired if one
* of the following hold true:\n
* - \em R2 > \em R1 \n
* - \em R2 == \em R1, \em L2 and \em L1 belong to the same class,
* and \em r2 > \em r1.\n
* \n
* The only exception to the above rule is for "unranked locks", which
* are applicable only for timers. An unranked timer does not participate
* in the ranking rules. Standalone unranked spinlocks are not supported.\n
* \n
* Two types of spinlocks, with respect to lock ranks are supported:\n
* \n
* \li <b>Simple Ranked Spinlock:</b> \n
* A stand-alone spinlock which has an explicit major rank other
* than VMK_SP_RANK_UNRANKED. The minor rank (which is implicitly set)
* is always equal to '0'.
* \li <b>Class Based Ranked Spinlock:</b>\n
* Belongs to a class of spinlocks all of which share the same
* explicit major rank other than VMK_SP_RANK_UNRANKED. Members of
* the same class differ only with respect to their minor rank, which is
* explicitly set to a desired value, other than VMK_SP_RANK_UNRANKED,
* during lock initialization.
*
* \par Timers and Ranks:
* Timers also have ranks within the lock ranking system. While a
* timer callback is firing, the callback is treated as holding a lock
* of the timer's rank, so it is not allowed to acquire locks of lower
* rank. A call to vmk_TimerRemoveSync is treated as acquiring (and
* releasing) a lock of the timer's rank, and thus is not allowed when
* holding locks of higher or equal rank.\n
* \n
* Timers can only be unranked or simple, not class-based. It is
* common to give a timer the rank VMK_SP_RANK_LOWEST; this allows the
* callback to acquire any higher-ranked lock, but requires that code
* calling vmk_TimerRemoveSync on the timer hold no locks.
*
* @{
***********************************************************************
*/
#ifndef _VMKAPI_SPLOCK_H_
#define _VMKAPI_SPLOCK_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
#include "base/vmkapi_types.h"
#include "base/vmkapi_status.h"
#include "base/vmkapi_assert.h"
#include "base/vmkapi_module.h"
#include "base/vmkapi_lock_rank.h"
/**
* \brief Recursive flag
*
* Recursive flag indicates that an instace of lock \em L can be held while
* acquiring another instance of lock \em L. It is assumed the caller knows
* what they're doing.
*/
#define VMK_SP_RANK_RECURSIVE_FLAG _VMK_SP_RANK_RECURSIVE_FLAG
/**
* \brief Mask for rank value
*/
#define VMK_SP_RANK_NUMERIC_MASK _VMK_SP_RANK_NUMERIC_MASK
/**
* \brief Lowest rank for locks
*/
#define VMK_SP_RANK_LOWEST _VMK_SP_RANK_LOWEST
/**
* \brief highest rank for locks
*/
#define VMK_SP_RANK_HIGHEST _VMK_SP_RANK_HIGHEST
/**
* \brief Maximum rank for locks
*/
#define VMK_SP_RANK_MAX (VMK_SP_RANK_NUMERIC_MASK - 1)
/**
* \brief Minimum rank for locks
*/
#define VMK_SP_RANK_MIN (0)
/**
* \brief Leaf rank for IRQ locks
*
* To be used for IRQ locks that leafs, except for log/warning
*
*/
#define VMK_SP_RANK_IRQ_LEAF _VMK_SP_RANK_IRQ_LEAF
/**
* \brief Rank used by calls potentially invoked by timers that need
* to manage memory. For instance: an allocator callable by
* timers.
*/
#define VMK_SP_RANK_IRQ_MEMTIMER _VMK_SP_RANK_IRQ_MEMTIMER
/**
* \brief Block rank for IRQ locks
*
* To be used for IRQ locks that depend on eventqueue/cpusched locks
*/
#define VMK_SP_RANK_IRQ_BLOCK _VMK_SP_RANK_IRQ_BLOCK
/**
* \brief Lowest rank for IRQ locks
*/
#define VMK_SP_RANK_IRQ_LOWEST _VMK_SP_RANK_IRQ_LOWEST
/**
* \brief Leaf rank for locks
*
* Leaf locks are ranked lower than spin locks protecting semaphores,
* so that one can grab a semaphore, grab a leaf lock and then call
* vmk_SemaIsLocked() on the semaphore.
*/
#define VMK_SP_RANK_LEAF _VMK_SP_RANK_LEAF
/**
* \brief Rank for all SCSI locks
*
*/
#define VMK_SP_RANK_SCSI _VMK_SP_RANK_SCSI
/**
* \brief Rank for all SCSI plugin locks
*
*/
#define VMK_SP_RANK_SCSI_PLUGIN2 _VMK_SP_RANK_SCSI_PLUGIN2
#define VMK_SP_RANK_SCSI_PLUGIN1 _VMK_SP_RANK_SCSI_PLUGIN1
/**
* \brief Lowest rank for all SCSI locks
*
*/
#define VMK_SP_RANK_SCSI_LOWEST _VMK_SP_RANK_SCSI_LOWEST
/**
* \brief Lowest rank for locks in FS Device Switch component
*
* Lowest possible rank for locks used by FS Device Switch. Modules
* operating above the device switch, and calling into the device switch
* should use locks ranked lower than this.
*/
#define VMK_SP_RANK_FDS_LOWEST _VMK_SP_RANK_FDS_LOWEST
/**
* \brief Lowest rank for locks in VMK FS drivers
*
* Lowest possible rank for locks used by VMK FS drivers. FSS and everyone
* above should use locks ranked lower than this.
*/
#define VMK_SP_RANK_FSDRIVER_LOWEST _VMK_SP_RANK_FSDRIVER_LOWEST
/**
* \brief Rank for Network locks
*
* Usual lock rank used for module internal usage which doesn't imply
* vmkapi call.
*/
#define VMK_SP_RANK_NETWORK _VMK_SP_RANK_NETWORK
/**
* \brief Lowest Rank for Network locks
*
* Should be used if the module is intended to hold a lock while calling
* a vmkapi function.
*/
#define VMK_SP_RANK_NETWORK_LOWEST _VMK_SP_RANK_NETWORK_LOWEST
/**
* \brief Highest Rank for Network locks
*
* Should be used if the module is intended to hold a lock while calling
* a vmkapi function.
*/
#define VMK_SP_RANK_NETWORK_HIGHEST _VMK_SP_RANK_NETWORK_HIGHEST
/**
* \brief Tcpip2 stack highest rank.
*
*/
#define VMK_SP_RANK_TCPIP_HIGHEST _VMK_SP_RANK_TCPIP_HIGHEST
/**
* \brief Unranked timers.
*/
#define VMK_SP_RANK_UNRANKED_TIMER _VMK_SP_RANK_UNRANKED_TIMER
/**
* \brief Handle for lock classes
*/
typedef struct vmk_SpinlockClassInt *vmk_SpinlockClass;
/**
* \brief Handle for non-IRQ locks
*/
typedef struct vmk_SpinlockInt *vmk_Spinlock;
/**
* \brief Handle for IRQ locks
*/
typedef struct vmk_SpinlockIRQInt *vmk_SpinlockIRQ;
/**
* \brief Handle for non-IRQ rw locks
*/
typedef struct vmk_SpinlockRWInt *vmk_SpinlockRW;
/**
* \brief Rank for locks
*/
typedef _vmk_SP_Rank vmk_SpinlockRank;
/*
***********************************************************************
* vmk_SPClassCreate -- */ /**
*
* \ingroup Spinlocks
* \brief Allocate and initialize a spinlock class
*
* Creates a new spinlock class and initializes it.
*
* The spinlock class's rank serves as the major rank for the
* spinlocks that are members of the class.
*
* \note Requires that the module heap be initialized.
*
* \param[out] lockClass Pointer to the new spinlock class.
* \param[in] moduleID Module ID who manages the created
* spinlock class.
* \param[in] name Name of the spinlock class.
* \param[in] rank Rank of the spinlock class.
* The specified rank must be greater than or
* equal to VMK_SP_RANK_LOWEST and less than or
* equal to VMK_SP_RANK_HIGHEST.
*
* \retval VMK_OK The spinlock class was successfully initialized
* \retval VMK_NO_MEMORY The spinlock class could not be allocated
* \retval VMK_NO_MODULE_HEAP The module has no heap to allocate from
*
***********************************************************************
*/
VMK_ReturnStatus vmk_SPClassCreate(
vmk_SpinlockClass *lockClass,
vmk_ModuleID moduleID,
const char *name,
vmk_SpinlockRank rank);
/*
***********************************************************************
* vmk_SPClassDestroy -- */ /**
*
* \ingroup Spinlocks
* \brief Destroy a spinlock class
*
* Revert all side effects of vmk_SPClassCreate
*
* \param[in] lockClass Pointer to the spinlock class to be deleted.
*
***********************************************************************
*/
void vmk_SPClassDestroy(vmk_SpinlockClass *lockClass);
/*
***********************************************************************
* vmk_SPCreate -- */ /**
*
* \ingroup Spinlocks
* \brief Allocate and initialize a non-IRQ spinlock
*
* Creates a new non-IRQ spinlock and initializes it.
*
* \note Requires that the module heap be initialized.
*
* \param[out] lock Pointer to the new spinlock class.
* \param[in] moduleID Module that owns the new spinlock.
* \param[in] name Name of the spinlock,
* \param[in] lockClass Pointer to a spinlock class, or NULL if the
* new spinlock should be a simple (non-classed)
* spinlock.
* \param[in] rank The spinlock's rank.\n
* If lockClass is NULL then this parameter
* specifies the lock's major rank.
* The specified rank must be greater than or
* equal to VMK_SP_RANK_LOWEST and less than or
* equal to VMK_SP_RANK_HIGHEST.\n
* If lockClass is set to a valid spinlock
* class then this parameter specifies the
* new spinlock's minor rank with the lock's
* major rank being inherited from the
* spinlock class.
* The specified rank must be greater than or
* equal to VMK_SP_RANK_MIN and less than or
* equal to VMK_SP_RANK_MAX.\n
*
* \retval VMK_OK The spinlock was successfully initialized
* \retval VMK_NO_MEMORY The spinlock could not be allocated
* \retval VMK_NO_MODULE_HEAP The module has no heap to allocate from
*
***********************************************************************
*/
VMK_ReturnStatus vmk_SPCreate(
vmk_Spinlock *lock,
vmk_ModuleID moduleID,
const char *name,
vmk_SpinlockClass *lockClass,
vmk_SpinlockRank rank);
/*
***********************************************************************
* vmk_SPIsLocked -- */ /*
*
* \ingroup Spinlocks
* \brief Tests a non-IRQ spinlock to see if it is currently locked.
*
* \note This call is only available on debug builds.
*
* \param[in] lock Non-IRQ spinlock to check.
*
* \retval VMK_OK Lock is unlocked.
* \retval VMK_BUSY Lock is locked.
* \retval VMK_BAD_PARAM Not a valid lock.
*
***********************************************************************
*/
#ifdef VMX86_DEBUG
VMK_ReturnStatus vmk_SPIsLocked(
vmk_Spinlock *lock);
#endif
/*
***********************************************************************
* VMK_ASSERT_SPLOCK_LOCKED -- */ /**
*
* \ingroup Spinlocks
* \brief Assert that a spinlock is currently locked.
*
* \note This call only performs the check on a debug build.
* Other builds always succeed.
*
* \param[in] lock Non-IRQ spinlock to check
*
***********************************************************************
*/
#define VMK_ASSERT_SPLOCK_LOCKED(lock) \
VMK_ASSERT(vmk_SPIsLocked(lock) == VMK_BUSY)
/*
***********************************************************************
* VMK_ASSERT_SPLOCK_UNLOCKED -- */ /**
*
* \ingroup Spinlocks
* \brief Assert that a spinlock is currently unlocked.
*
* \note This call only performs the check on a debug build.
* Other builds always succeed.
*
* \param[in] lock Non-IRQ spinlock to check
*
***********************************************************************
*/
#define VMK_ASSERT_SPLOCK_UNLOCKED(lock) \
VMK_ASSERT(vmk_SPIsLocked(lock) == VMK_OK)
/*
***********************************************************************
* vmk_AssertNoSPLocksHeld -- */ /**
*
* \ingroup Spinlocks
* \brief Assert that no non-IRQ spinlocks are held by this CPU.
*
* \note This call only performs the check on a debug build.
* Other builds always succeed.
*
***********************************************************************
*/
#ifdef VMX86_DEBUG
void vmk_AssertNoSPLocksHeld(
void);
#else
static inline void vmk_AssertNoSPLocksHeld(
void) {}
#endif
/*
***********************************************************************
* vmk_AssertNoSPLocksHeldIRQ -- */ /**
*
* \ingroup Spinlocks
* \brief Assert that no IRQ spinlocks are held by this CPU.
*
* \note This call only performs the check on a debug build.
* Other builds always succeed.
*
***********************************************************************
*/
#ifdef VMX86_DEBUG
void vmk_AssertNoSPLocksHeldIRQ(
void);
#else
static inline void vmk_AssertNoSPLocksHeldIRQ(
void) {}
#endif
/*
***********************************************************************
* vmk_SPLock -- */ /**
*
* \ingroup Spinlocks
* \brief Acquire the non-IRQ spinlock
*
* \pre The caller shall not already hold a spinlock of lower or
* equal rank.
*
* \param[in,out] lock Non-IRQ spinlock to acquire.
*
* \return None.
*
***********************************************************************
*/
void vmk_SPLock(
vmk_Spinlock *lock);
/*
***********************************************************************
* vmk_SPTryLock -- */ /**
*
* \ingroup Spinlocks
* \brief Try acquire a non-IRQ spinlock
*
* This function tries to acquire the given spinlock:
* - If the given spinlock has not been locked, this function locks it.
* - If the given spinlock has been locked already, this function does
* nothing and returns immediately.
*
* \pre This caller shall not already hold a spinlock of lower or
* equal rank.
*
* \param[in,out] lock Non-IRQ spinlock to attempt to acquire.
*
* \retval VMK_OK The given spinlock is successfully locked by this
* call.
* \retval VMK_BUSY The given spinlock has been locked already.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_SPTryLock(
vmk_Spinlock *lock);
/*
***********************************************************************
* vmk_SPUnlock -- */ /**
*
* \ingroup Spinlocks
* \brief Release a non-IRQ spinlock
*
* \pre The caller currently owns the spinlock.
*
* \param[in,out] lock Non-IRQ spinlock to release.
*
***********************************************************************
*/
void vmk_SPUnlock(
vmk_Spinlock *lock);
/*
***********************************************************************
* vmk_SPDestroy -- */ /**
*
* \ingroup Spinlocks
* \brief Destroy a non-IRQ spinlock
*
* Revert all side effects of vmk_SPCreate
*
* \param[in] lock Non-IRQ spinlock to be destroyed.
*
***********************************************************************
*/
void vmk_SPDestroy(vmk_Spinlock *lock);
/*
***********************************************************************
* vmk_SPCreateIRQ -- */ /**
*
* \ingroup Spinlocks
* \brief Allocate and initialize an IRQ spinlock
*
* Creates a new IRQ spinlock and initializes it.
*
* \note Requires that the module heap be initialized.
*
* \param[out] lock Pointer to the new spinlock class.
* \param[in] moduleID Module that owns the new spinlock.
* \param[in] name Name of the spinlock,
* \param[in] lockClass Pointer to a spinlock class, or NULL if the
* new spinlock should be a simple (non-classed)
* spinlock.
* \param[in] rank The spinlock's rank.\n
* If lockClass is NULL then this parameter
* specifies the lock's major rank.
* The specified rank must be greater than or
* equal to VMK_SP_RANK_IRQ_LOWEST and less
* than or equal to VMK_SP_RANK_IRQ_HIGHEST.\n
* If lockClass is set to a valid spinlock
* class then this parameter specifies the
* new spinlock's minor rank with the lock's
* major rank being inherited from the
* spinlock class.
* The specified rank must be greater than or
* equal to VMK_SP_RANK_MIN and less than or
* equal to VMK_SP_RANK_MAX.\n
*
* \retval VMK_OK The spinlock was successfully initialized
* \retval VMK_NO_MEMORY The spinlock could not be allocated
* \retval VMK_NO_MODULE_HEAP The module has no heap to allocate from
*
***********************************************************************
*/
VMK_ReturnStatus vmk_SPCreateIRQ(
vmk_SpinlockIRQ *lock,
vmk_ModuleID moduleID,
const char *name,
vmk_SpinlockClass *lockClass,
vmk_SpinlockRank rank);
/*
***********************************************************************
* vmk_SPIsLockedIRQ -- */ /*
*
* \ingroup Spinlocks
* \brief Tests an IRQ spinlock to see if it is currently locked.
*
* \note This call is only available on debug builds.
*
* \param[in] lock IRQ spinlock to check
*
* \retval VMK_OK Lock is unlocked.
* \retval VMK_BUSY Lock is locked.
* \retval VMK_BAD_PARAM Not a valid lock.
*
***********************************************************************
*/
#ifdef VMX86_DEBUG
VMK_ReturnStatus vmk_SPIsLockedIRQ(
vmk_SpinlockIRQ *lock);
#endif
/*
***********************************************************************
* VMK_ASSERT_SPLOCK_LOCKED_IRQ -- */ /**
*
* \ingroup Spinlocks
* \brief Assert that an IRQ spinlock is currently locked.
*
* \note This call only performs the check on a debug build.
* Other builds always succeed.
*
* \param[in] lock IRQ spinlock to check
*
***********************************************************************
*/
#define VMK_ASSERT_SPLOCK_LOCKED_IRQ(lock) \
VMK_ASSERT(vmk_SPIsLockedIRQ(lock) == VMK_BUSY)
/*
***********************************************************************
* VMK_ASSERT_SPLOCKIRQ_UNLOCKED_IRQ -- */ /**
*
* \ingroup Spinlocks
* \brief Assert that an IRQ spinlock is currently unlocked.
*
* \note This call only performs the check on a debug build.
* Other builds always succeed.
*
* \param[in] lock IRQ spinlock to check
*
***********************************************************************
*/
#define VMK_ASSERT_SPLOCKIRQ_UNLOCKED_IRQ(lock) \
VMK_ASSERT(vmk_SPIsLockedIRQ(lock) == VMK_OK)
/*
***********************************************************************
* vmk_SPLockIRQ -- */ /**
*
* \ingroup Spinlocks
* \brief Acquire the IRQ spinlock
*
* Acquires an IRQ spinlock and disable interrupts on the current CPU
* if they are not already disabled.
*
* \pre The caller shall not already hold a spinlock of lower or
* equal rank.
*
* \param[in,out] lock IRQ spinlock to acquire.
*
* \return Previous IRQ state.
* \retval 0 interrupts were enabled.
* \retval 1 interrupts were disabled.
*
***********************************************************************
*/
unsigned long vmk_SPLockIRQ(
vmk_SpinlockIRQ *lock);
/*
***********************************************************************
* vmk_SPTryLockIRQ -- */ /**
*
* \ingroup Spinlocks
* \brief Try acquire an IRQ spinlock
*
* This function tries to acquire the given spinlock:
* - If the given IRQ spinlock has not been locked, this function locks it
* and disables interrupts on the current CPU if interrupts were not
* already disabled.
* - If the given IRQ spinlock has been locked already, this function does
* nothing and returns immediately.
*
* \pre This caller shall not already hold a spinlock of lower or
* equal rank.
*
* \param[in,out] lock IRQ spinlock to attempt to acquire.
* \param[out] flags Previous IRQ level. 0 if interrupts were enabled.
* 1 if interrupts were disabled.
*
* \retval VMK_OK The given spinlock is successfully locked by this
* call.
* \retval VMK_BUSY The given spinlock has been locked already.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_SPTryLockIRQ(
vmk_SpinlockIRQ *lock,
unsigned long *flags);
/*
***********************************************************************
* vmk_SPUnlockIRQ -- */ /**
*
* \ingroup Spinlocks
* \brief Release an IRQ spinlock
*
* \pre The caller currently owns the spinlock.
*
* \param[in,out] lock IRQ spinlock to unlock.
* \param[in] prevIRQ IRQ level from returned from vmk_SPLockIRQ
* or vmk_SPTryLockIRQ.
*
***********************************************************************
*/
void vmk_SPUnlockIRQ(
vmk_SpinlockIRQ *lock,
unsigned long prevIRQ);
/*
***********************************************************************
* vmk_SPDestroyIRQ -- */ /**
*
* \ingroup Spinlocks
* \brief Destroy an IRQ spinlock
*
* Revert all side effects of vmk_SPCreateIRQ
*
* \param lock IRQ spinlock to be detroyed.
*
***********************************************************************
*/
void vmk_SPDestroyIRQ(vmk_SpinlockIRQ *lock);
/*
***********************************************************************
* vmk_RWCreate -- */ /**
*
* \ingroup Spinlocks
* \brief Allocate and initialize a reader/writer spinlock
*
* Creates a new reader/writer spinlock and initializes it as
* ranked spinlock.
*
* \note Requires that the module heap be initialized.
*
* \param[out] lock Pointer to the new spinlock class.
* \param[in] moduleID Module that owns the new spinlock.
* \param[in] name Name of the spinlock,
* \param[in] lockClass Pointer to a spinlock class, or NULL if the
* new spinlock should be a simple (non-classed)
* spinlock.
* \param[in] rank The spinlock's rank.\n
* If lockClass is NULL then this parameter
* specifies the lock's major rank.
* The specified rank must be greater than or
* equal to VMK_SP_RANK_LOWEST and less than or
* equal to VMK_SP_RANK_HIGHEST.\n
* If lockClass is set to a valid spinlock
* class then this parameter specifies the
* new spinlock's minor rank with the lock's
* major rank being inherited from the
* spinlock class.
* The specified rank must be greater than or
* equal to VMK_SP_RANK_MIN and less than or
* equal to VMK_SP_RANK_MAX.\n
*
* \retval VMK_OK The spinlock was successfully initialized
* \retval VMK_NO_MEMORY The spinlock could not be allocated
* \retval VMK_NO_MODULE_HEAP The module has no heap to allocate from
*
***********************************************************************
*/
VMK_ReturnStatus vmk_RWCreate(
vmk_SpinlockRW *lock,
vmk_ModuleID moduleID,
const char *name,
vmk_SpinlockClass *lockClass,
vmk_SpinlockRank rank);
/*
***********************************************************************
* vmk_RWReadLock -- */ /**
*
* \ingroup Spinlocks
* \brief Acquire a reader/writer spinlock for reading.
*
* \pre The caller shall not already hold a spinlock of lower or
* equal rank.
*
* \param[in,out] lock Reader/writer spinlock to acquire.
*
***********************************************************************
*/
void vmk_RWReadLock(
vmk_SpinlockRW *lock);
/*
***********************************************************************
* vmk_RWTryReadLock -- */ /**
*
* \ingroup Spinlocks
* \brief Try acquire the reader/writer spinlock for reading
*
* This function tries to acquire the given spinlock:
* - If the given r/w spinlock has not been locked, this function locks it.
* - If the given r/w spinlock has been locked already, this function does
* nothing and returns immediately.
*
* \pre This caller shall not already hold a spinlock of lower or
* equal rank.
*
* \param[in,out] lock Reader/writer spinlock to attempt to acquire.
*
* \retval VMK_OK The given spinlock is successfully locked by
* this call.
* \retval VMK_BUSY The given spinlock has been locked already.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_RWTryReadLock(
vmk_SpinlockRW *lock);
/*
***********************************************************************
* vmk_RWIsRLocked -- */ /**
*
* \ingroup Spinlocks
* \brief Tests a reader/writer spinlock to see if it is currently
* read-locked.
*
* \param[in] lock Reader/writer spinlock to check
*
* \retval VMK_OK Lock is unlocked.
* \retval VMK_BUSY Lock is locked.
* \retval VMK_BAD_PARAM Not a valid lock.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_RWIsRLocked(
vmk_SpinlockRW *lock);
/*
***********************************************************************
* VMK_ASSERT_RWLOCK_RLOCKED -- */ /**
*
* \ingroup Spinlocks
* \brief Assert that a reader/writer lock is currently read-locked.
*
* \note This call only performs the check on a debug build.
* Other builds always succeed.
*
* \param[in] lock Reader/writer spinlock to check
*
***********************************************************************
*/
#define VMK_ASSERT_RWLOCK_RLOCKED(lock) \
VMK_ASSERT(vmk_RWIsRLocked(lock) == VMK_BUSY)
/*
***********************************************************************
* vmk_RWWriteLock -- */ /**
*
* \ingroup Spinlocks
* \brief Acquire a reader/writer spinlock for writing.
*
* \pre The caller shall not already hold a spinlock of lower or
* equal rank.
*
* \param[in,out] lock Reader/writer spinlock to acquire.
*
* \return None.
*
***********************************************************************
*/
void vmk_RWWriteLock(
vmk_SpinlockRW *lock);
/*
***********************************************************************
* vmk_RWTryWriteLock -- */ /**
*
* \ingroup Spinlocks
* \brief Try acquire the reader/writer spinlock for writing
*
* This function tries to acquire the given spinlock:
* - If the given r/w spinlock has not been locked, this function locks it.
* - If the given r/w spinlock has been locked already, this function does
* nothing and returns immediately.
*
* \pre This caller shall not already hold a spinlock of lower or
* equal rank.
*
* \param[in,out] lock Reader/writer spinlock to attempt to acquire.
*
* \retval VMK_OK The given spinlock is successfully locked by this
* call.
* \retval VMK_BUSY The given spinlock has been locked already.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_RWTryWriteLock(
vmk_SpinlockRW *lock);
/*
***********************************************************************
* vmk_RWIsWLocked -- */ /**
*
* \ingroup Spinlocks
* \brief Tests a reader/writer spinlock to see if it is currently
* write-locked.
*
* \param[in] lock Reader/writer spinlock to check
*
* \retval VMK_OK Lock is unlocked.
* \retval VMK_BUSY Lock is locked.
* \retval VMK_BAD_PARAM Not a valid lock.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_RWIsWLocked(
vmk_SpinlockRW *lock);
/*
***********************************************************************
* VMK_ASSERT_RWLOCK_WLOCKED -- */ /**
*
* \ingroup Spinlocks
* \brief Assert that a reader/writer lock is currently write-locked.
*
* \note This call only performs the check on a debug build.
* Other builds always succeed.
*
* \param[in] lock Reader/writer spinlock to check
*
***********************************************************************
*/
#define VMK_ASSERT_RWLOCK_WLOCKED(lock) \
VMK_ASSERT(vmk_RWIsWLocked(lock) == VMK_BUSY)
/*
***********************************************************************
* vmk_RWReadUnlock -- */ /**
*
* \ingroup Spinlocks
* \brief Release a reader/writer spinlock from a read-lock.
*
* \pre The caller currently has a read-lock on the spinlock.
*
* \param[in,out] lock Reader/writer spinlock to release.
*
***********************************************************************
*/
void vmk_RWReadUnlock(
vmk_SpinlockRW *lock);
/*
***********************************************************************
* vmk_RWWriteUnlock -- */ /**
*
* \ingroup Spinlocks
* \brief Release a reader/writer spinlock from a write-lock.
*
* \pre The caller currently has a write-lock on the spinlock.
*
* \param[in,out] lock Reader/writer spinlock to release.
*
***********************************************************************
*/
void vmk_RWWriteUnlock(
vmk_SpinlockRW *lock);
/*
***********************************************************************
* vmk_SPDestroy -- */ /**
*
* \ingroup Spinlocks
* \brief Destroy a reader/writer spinlock
*
* Revert all side effects of vmk_RWCreate
*
* \param[in] lock Reader/writer spinlock to be destroyed.
*
***********************************************************************
*/
void vmk_RWDestroy(vmk_SpinlockRW *lock);
#endif /* _VMKAPI_SPLOCK_H_ */
/** @} */