vmkdrivers/BLD/build/HEADERS/vmkapi-current-all-public/vmkernel64/release/base/vmkapi_lock.h

1040 lines
32 KiB
C
Raw Normal View History

2015-10-23 19:21:55 +00:00
/* **********************************************************
* 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
2015-10-23 19:48:45 +00:00
* common to give a timer the rank VMK_SP_RANK_LOWEST_MAJOR_LEGACY; this
* allows the callback to acquire any higher-ranked lock, but requires
* that code calling vmk_TimerRemoveSync on the timer hold no locks.
2015-10-23 19:21:55 +00:00
*
* @{
***********************************************************************
*/
#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 */
/**
* \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.
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_RECURSIVE_FLAG_LEGACY _VMK_SP_RANK_RECURSIVE_FLAG_LEGACY
/**
* \brief Mask for major rank value.
*/
#define VMK_SP_RANK_NUMERIC_MASK_MAJOR_LEGACY _VMK_SP_RANK_NUMERIC_MASK_MAJOR_LEGACY
/**
* \brief Mask for minor rank value.
*/
#define VMK_SP_RANK_NUMERIC_MASK_MINOR_LEGACY _VMK_SP_RANK_NUMERIC_MASK_MINOR_LEGACY
/**
* \brief Lowest major rank for locks
*/
#define VMK_SP_RANK_LOWEST_MAJOR_LEGACY _VMK_SP_RANK_LOWEST_MAJOR_LEGACY
2015-10-23 19:21:55 +00:00
/**
2015-10-23 19:48:45 +00:00
* \brief highest major rank for non-IRQ locks
2015-10-23 19:21:55 +00:00
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_HIGHEST_MAJOR_LEGACY _VMK_SP_RANK_HIGHEST_MAJOR_LEGACY
2015-10-23 19:21:55 +00:00
/**
2015-10-23 19:48:45 +00:00
* \brief Maximum minor rank for locks.
2015-10-23 19:21:55 +00:00
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_MAX_MINOR_LEGACY (_VMK_SP_RANK_NUMERIC_MASK_MINOR_LEGACY)
2015-10-23 19:21:55 +00:00
/**
2015-10-23 19:48:45 +00:00
* \brief Minimum minor rank for locks.
2015-10-23 19:21:55 +00:00
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_MIN_MINOR_LEGACY (0)
2015-10-23 19:21:55 +00:00
/**
2015-10-23 19:48:45 +00:00
* \brief Maximum major rank for locks
2015-10-23 19:21:55 +00:00
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_MAX_MAJOR_LEGACY (VMK_SP_RANK_NUMERIC_MASK_MAJOR_LEGACY - 1)
2015-10-23 19:21:55 +00:00
/**
2015-10-23 19:48:45 +00:00
* \brief Minimum major rank for locks
2015-10-23 19:21:55 +00:00
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_MIN_MAJOR_LEGACY (0)
2015-10-23 19:21:55 +00:00
/**
* \brief Leaf rank for IRQ locks
*
* To be used for IRQ locks that leafs, except for log/warning
*
*/
2015-10-23 22:26:03 +00:00
#define VMK_SP_RANK_IRQ_LEAF_LEGACY (0x5ff9)
2015-10-23 19:21:55 +00:00
/**
* \brief Rank used by calls potentially invoked by timers that need
* to manage memory. For instance: an allocator callable by
* timers.
*/
2015-10-23 22:26:03 +00:00
#define VMK_SP_RANK_IRQ_MEMTIMER_LEGACY (0x5000)
2015-10-23 19:21:55 +00:00
/**
* \brief Block rank for IRQ locks
*
* To be used for IRQ locks that depend on eventqueue/cpusched locks
*/
2015-10-23 22:26:03 +00:00
#define VMK_SP_RANK_IRQ_BLOCK_LEGACY (0x4000)
2015-10-23 19:48:45 +00:00
/**
* \brief Lowest major rank for IRQ locks
*/
#define VMK_SP_RANK_IRQ_LOWEST_MAJOR_LEGACY _VMK_SP_RANK_IRQ_LOWEST_MAJOR_LEGACY
2015-10-23 19:21:55 +00:00
/**
2015-10-23 19:48:45 +00:00
* \brief Highest major rank for IRQ locks.
2015-10-23 19:21:55 +00:00
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_IRQ_HIGHEST_MAJOR_LEGACY _VMK_SP_RANK_IRQ_HIGHEST_MAJOR_LEGACY
2015-10-23 19:21:55 +00:00
/**
* \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.
*/
2015-10-23 22:26:03 +00:00
#define VMK_SP_RANK_LEAF_LEGACY (0x2ffd)
2015-10-23 19:21:55 +00:00
/**
* \brief Rank for all SCSI locks
*
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_SCSI_LEGACY _VMK_SP_RANK_SCSI_LEGACY
2015-10-23 19:21:55 +00:00
/**
* \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
*
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_SCSI_LOWEST_LEGACY _VMK_SP_RANK_SCSI_LOWEST_LEGACY
2015-10-23 19:21:55 +00:00
/**
* \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.
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_FDS_LOWEST_LEGACY _VMK_SP_RANK_FDS_LOWEST_LEGACY
2015-10-23 19:21:55 +00:00
/**
* \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.
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_FSDRIVER_LOWEST_LEGACY _VMK_SP_RANK_FSDRIVER_LOWEST_LEGACY
2015-10-23 19:21:55 +00:00
/**
* \brief Rank for Network locks
*
* Usual lock rank used for module internal usage which doesn't imply
* vmkapi call.
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_NETWORK_LEGACY _VMK_SP_RANK_NETWORK_LEGACY
2015-10-23 19:21:55 +00:00
/**
* \brief Lowest Rank for Network locks
*
* Should be used if the module is intended to hold a lock while calling
* a vmkapi function.
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_NETWORK_LOWEST_LEGACY _VMK_SP_RANK_NETWORK_LOWEST_LEGACY
2015-10-23 19:21:55 +00:00
/**
* \brief Highest Rank for Network locks
*
* Should be used if the module is intended to hold a lock while calling
* a vmkapi function.
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_NETWORK_HIGHEST_LEGACY _VMK_SP_RANK_NETWORK_HIGHEST_LEGACY
2015-10-23 19:21:55 +00:00
/**
2015-10-23 19:48:45 +00:00
* \brief Tcpip stack highest rank.
2015-10-23 19:21:55 +00:00
*
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_TCPIP_HIGHEST_LEGACY _VMK_SP_RANK_TCPIP_HIGHEST_LEGACY
2015-10-23 19:21:55 +00:00
/**
* \brief Unranked timers.
*/
2015-10-23 19:48:45 +00:00
#define VMK_SP_RANK_UNRANKED_TIMER_LEGACY VMK_SPINLOCK_UNRANKED
2015-10-23 19:21:55 +00:00
/**
* \brief Handle for lock classes
*/
2015-10-23 19:48:45 +00:00
typedef struct vmk_SpinlockClass_LEGACYInt *vmk_SpinlockClass_LEGACY;
2015-10-23 19:21:55 +00:00
/**
* \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
*/
2015-10-23 19:48:45 +00:00
typedef vmk_uint32 vmk_SpinlockRank;
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPClassCreate_LEGACY -- */ /**
2015-10-23 19:21:55 +00:00
*
* \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
2015-10-23 19:48:45 +00:00
* equal to VMK_SP_RANK_LOWEST_MAJOR_LEGACY
* and less than or equal to
* VMK_SP_RANK_HIGHEST_MAJOR_LEGACY.
2015-10-23 19:21:55 +00:00
*
* \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
2015-10-23 19:48:45 +00:00
* \retval VMK_BAD_PARAM Rank was invalid.
2015-10-23 19:21:55 +00:00
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
VMK_ReturnStatus vmk_SPClassCreate_LEGACY(
vmk_SpinlockClass_LEGACY *lockClass,
2015-10-23 19:21:55 +00:00
vmk_ModuleID moduleID,
const char *name,
vmk_SpinlockRank rank);
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPClassDestroy_LEGACY -- */ /**
2015-10-23 19:21:55 +00:00
*
* \ingroup Spinlocks
* \brief Destroy a spinlock class
*
2015-10-23 19:48:45 +00:00
* Revert all side effects of vmk_SPClassCreate_LEGACY
2015-10-23 19:21:55 +00:00
*
* \param[in] lockClass Pointer to the spinlock class to be deleted.
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
void vmk_SPClassDestroy_LEGACY(vmk_SpinlockClass_LEGACY *lockClass);
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPCreate_LEGACY -- */ /**
2015-10-23 19:21:55 +00:00
*
* \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
2015-10-23 19:48:45 +00:00
* equal to VMK_SP_RANK_LOWEST_MAJOR_LEGACY and
* less than or equal to
* VMK_SP_RANK_HIGHEST_MAJOR_LEGACY.\n
2015-10-23 19:21:55 +00:00
* 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
2015-10-23 19:48:45 +00:00
* \retval VMK_BAD_PARAM Rank was invalid.
2015-10-23 19:21:55 +00:00
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
VMK_ReturnStatus vmk_SPCreate_LEGACY(
2015-10-23 19:21:55 +00:00
vmk_Spinlock *lock,
vmk_ModuleID moduleID,
const char *name,
2015-10-23 19:48:45 +00:00
vmk_SpinlockClass_LEGACY *lockClass,
2015-10-23 19:21:55 +00:00
vmk_SpinlockRank rank);
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPAssertHasState --
2015-10-23 19:21:55 +00:00
*
2015-10-23 19:48:45 +00:00
* This is used by vmk_SPAssertIsLocked() and vmk_SPAssertIsUnlocked().
* VMKAPI clients should not call this function directly.
2015-10-23 19:21:55 +00:00
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
/** \cond nodoc */
void vmk_SPAssertHasState(
vmk_Spinlock *lock,
vmk_Bool locked);
/** \endcond */
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPAssertIsLocked -- */ /**
2015-10-23 19:21:55 +00:00
*
* \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.
2015-10-23 19:48:45 +00:00
* \note This call will not block.
2015-10-23 19:21:55 +00:00
*
* \param[in] lock Non-IRQ spinlock to check
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
static VMK_ALWAYS_INLINE void
vmk_SPAssertIsLocked(
vmk_Spinlock *lock)
{
#ifdef VMX86_DEBUG
vmk_SPAssertHasState(lock, VMK_TRUE);
#endif
}
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPAssertNotUnlocked -- */ /**
2015-10-23 19:21:55 +00:00
*
* \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.
2015-10-23 19:48:45 +00:00
* \note This call will not block.
2015-10-23 19:21:55 +00:00
*
* \param[in] lock Non-IRQ spinlock to check
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
static VMK_ALWAYS_INLINE void
vmk_SPAssertIsUnlocked(
vmk_Spinlock *lock)
{
#ifdef VMX86_DEBUG
vmk_SPAssertHasState(lock, VMK_FALSE);
#endif
}
/*
***********************************************************************
* vmk_SPAssertNoLocksHeldInt -- */ /**
*
* This is used by vmk_SPAssertNoLocksHeld(). VMKAPI clients should
* not call this function directly.
*
***********************************************************************
*/
/** \cond nodoc */
void
vmk_SPAssertNoLocksHeldInt(
void);
/** \endcond */
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPAssertNoLocksHeld -- */ /**
2015-10-23 19:21:55 +00:00
*
* \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.
2015-10-23 19:48:45 +00:00
* \note This call will not block.
2015-10-23 19:21:55 +00:00
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
static VMK_ALWAYS_INLINE void
vmk_SPAssertNoLocksHeld(
void)
{
2015-10-23 19:21:55 +00:00
#ifdef VMX86_DEBUG
2015-10-23 19:48:45 +00:00
vmk_SPAssertNoLocksHeldInt();
2015-10-23 19:21:55 +00:00
#endif
2015-10-23 19:48:45 +00:00
}
/*
***********************************************************************
* vmk_SPAssertNoLocksHeldIRQInt --
*
* This is used by vmk_SPAssertNoLocksHeldIRQ. VMKAPI clients should not
* call this function directly.
*
***********************************************************************
*/
/** \cond nodoc */
void
vmk_SPAssertNoLocksHeldIRQInt(
void);
/** \endcond */
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPAssertNoLocksHeldIRQ -- */ /**
2015-10-23 19:21:55 +00:00
*
* \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.
2015-10-23 19:48:45 +00:00
* \note This call will not block.
2015-10-23 19:21:55 +00:00
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
static VMK_ALWAYS_INLINE void
vmk_SPAssertNoLocksHeldIRQ(
void)
{
2015-10-23 19:21:55 +00:00
#ifdef VMX86_DEBUG
2015-10-23 19:48:45 +00:00
vmk_SPAssertNoLocksHeldIRQInt();
2015-10-23 19:21:55 +00:00
#endif
2015-10-23 19:48:45 +00:00
}
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
* vmk_SPLock -- */ /**
*
* \ingroup Spinlocks
* \brief Acquire the non-IRQ spinlock
*
2015-10-23 19:48:45 +00:00
* \pre The caller shall not already hold a spinlock of equal or
* higher rank.
2015-10-23 19:21:55 +00:00
*
* \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
*
2015-10-23 19:48:45 +00:00
* Revert all side effects of vmk_SPCreate_LEGACY
2015-10-23 19:21:55 +00:00
*
* \param[in] lock Non-IRQ spinlock to be destroyed.
*
***********************************************************************
*/
void vmk_SPDestroy(vmk_Spinlock *lock);
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPCreateIRQ_LEGACY -- */ /**
2015-10-23 19:21:55 +00:00
*
* \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
2015-10-23 19:48:45 +00:00
* The specified rank must be greater than or
* equal to VMK_SP_RANK_MIN_MAJOR_LEGACY and
* less than or equal to
* VMK_SP_RANK_MAX_MAJOR_LEGACY.\n
2015-10-23 19:21:55 +00:00
* 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
2015-10-23 19:48:45 +00:00
* spinlock class. Minor spin ranks must be
* greater than or equal to
* VMK_SP_RANK_MIN_MINOR_LEGACY and less than or
* equal to VMK_SP_RANK_MAX_MINOR_LEGACY.
2015-10-23 19:21:55 +00:00
*
* \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
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
VMK_ReturnStatus vmk_SPCreateIRQ_LEGACY(
2015-10-23 19:21:55 +00:00
vmk_SpinlockIRQ *lock,
vmk_ModuleID moduleID,
const char *name,
2015-10-23 19:48:45 +00:00
vmk_SpinlockClass_LEGACY *lockClass,
2015-10-23 19:21:55 +00:00
vmk_SpinlockRank rank);
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPAssertHasStateIRQ --
2015-10-23 19:21:55 +00:00
*
2015-10-23 19:48:45 +00:00
* This is use by vmk_SPAssertIsLockedIRQ and
* vmk_SPAssertIsUnlockedIRQ(). VMKAPI clients should not call this
* function directly.
2015-10-23 19:21:55 +00:00
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
/** \cond nodoc */
void vmk_SPAssertHasStateIRQ(
vmk_SpinlockIRQ *lock,
vmk_Bool locked);
/** \endcond */
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPAssertIsLockedIRQ -- */ /**
2015-10-23 19:21:55 +00:00
*
* \ingroup Spinlocks
* \brief Assert that an IRQ spinlock is currently locked.
*
* \note This call only performs the check on a debug build.
2015-10-23 19:48:45 +00:00
* \note This call will not block.
2015-10-23 19:21:55 +00:00
*
* \param[in] lock IRQ spinlock to check
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
static VMK_ALWAYS_INLINE void
vmk_SPAssertIsLockedIRQ(
vmk_SpinlockIRQ *lock)
{
#ifdef VMX86_DEBUG
vmk_SPAssertHasStateIRQ(lock, VMK_TRUE);
#endif
}
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_SPAssertIsUnlockedIRQ -- */ /**
2015-10-23 19:21:55 +00:00
*
* \ingroup Spinlocks
* \brief Assert that an IRQ spinlock is currently unlocked.
*
* \note This call only performs the check on a debug build.
2015-10-23 19:48:45 +00:00
* \note This call will not block.
2015-10-23 19:21:55 +00:00
*
* \param[in] lock IRQ spinlock to check
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
static VMK_ALWAYS_INLINE void
vmk_SPAssertIsUnlockedIRQ(
vmk_SpinlockIRQ *lock)
{
#ifdef VMX86_DEBUG
vmk_SPAssertHasStateIRQ(lock, VMK_FALSE);
#endif
}
2015-10-23 19:21:55 +00:00
/*
***********************************************************************
* 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.
*
2015-10-23 19:48:45 +00:00
* \pre The caller shall not already hold a spinlock of equal or
* higher rank.
2015-10-23 19:21:55 +00:00
*
* \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
*
2015-10-23 19:48:45 +00:00
* Revert all side effects of vmk_SPCreateIRQ_LEGACY
2015-10-23 19:21:55 +00:00
*
* \param lock IRQ spinlock to be detroyed.
*
***********************************************************************
*/
void vmk_SPDestroyIRQ(vmk_SpinlockIRQ *lock);
/*
***********************************************************************
2015-10-23 19:48:45 +00:00
* vmk_RWCreate_LEGACY -- */ /**
2015-10-23 19:21:55 +00:00
*
* \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
2015-10-23 19:48:45 +00:00
* equal to VMK_SP_RANK_MIN_MAJOR_LEGACY and
* less than or equal to
* VMK_SP_RANK_MAX_MAJOR_LEGACY.\n
2015-10-23 19:21:55 +00:00
*
* \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
*
***********************************************************************
*/
2015-10-23 19:48:45 +00:00
VMK_ReturnStatus vmk_RWCreate_LEGACY(
2015-10-23 19:21:55 +00:00
vmk_SpinlockRW *lock,
vmk_ModuleID moduleID,
const char *name,
2015-10-23 19:48:45 +00:00
vmk_SpinlockClass_LEGACY *lockClass,
2015-10-23 19:21:55 +00:00
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
*
2015-10-23 19:48:45 +00:00
* Revert all side effects of vmk_RWCreate_LEGACY
2015-10-23 19:21:55 +00:00
*
* \param[in] lock Reader/writer spinlock to be destroyed.
*
***********************************************************************
*/
void vmk_RWDestroy(vmk_SpinlockRW *lock);
#endif /* _VMKAPI_SPLOCK_H_ */
/** @} */