/* ********************************************************** * Copyright 2004 - 2009 VMware, Inc. All rights reserved. * **********************************************************/ /* * @VMKAPIMOD_LICENSE@ */ /* *********************************************************************** * Semaphores */ /** * \defgroup Semaphores Semaphores * * \par Binary Semaphore Ranks: * Binary semaphores are semaphores which may be treated like blocking * locks. As such, they take a rank and sub-rank in a manner analogous * the the lock ranking used for spinlocks.\n * \n * When a world locks a binary semaphore \em BS1 with major rank \em R1 and * minor rank \em r1, it may only lock another binary semaphore BS2 with * major rank \em R2 and minor rank \em r2 when: * \n * \em R2 > \em R1 \n * or \n * \em R2 == \em R1 and \em r2 > \em r1 \n * \n * Be aware that rank checking is only performed on debug builds. * @{ *********************************************************************** */ #ifndef _VMKAPI_SEM_H_ #define _VMKAPI_SEM_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_module.h" #include "base/vmkapi_status.h" /** \cond nodoc */ /* Private definitions */ #define _VMK_SEMA_RANK_UNRANKED 0x10000 #define _VMK_SEMA_RANK_MAX 0xffff #define _VMK_SEMA_RANK_MIN 0 #define _VMK_SEMA_RANK_LEAF _VMK_SEMA_RANK_MAX #define _VMK_SEMA_RANK_STORAGE 0x8000 typedef vmk_uint32 _vmk_SemaRank, _vmk_SemaRankMinor; /** \endcond nodoc */ /** * \brief unranked rank */ #define VMK_SEMA_RANK_UNRANKED _VMK_SEMA_RANK_UNRANKED /** * \brief Leaf rank for semaphores */ #define VMK_SEMA_RANK_LEAF _VMK_SEMA_RANK_LEAF /** * \brief Maximum rank for semaphores */ #define VMK_SEMA_RANK_MAX _VMK_SEMA_RANK_MAX /** * \brief Minimum rank for semaphores */ #define VMK_SEMA_RANK_MIN _VMK_SEMA_RANK_MIN /** * \brief Rank for semaphores in storage components */ #define VMK_SEMA_RANK_STORAGE _VMK_SEMA_RANK_STORAGE /** * \brief Rank for semaphores */ typedef _vmk_SemaRank vmk_SemaphoreRank; /** * \brief Sub rank for semaphores */ typedef _vmk_SemaRankMinor vmk_SemaphoreRankMinor; /** * \brief Opaque handle for semaphores */ typedef struct vmk_SemaphoreInt *vmk_Semaphore; /** * \brief Opaque handle for readers-writers semaphores */ typedef struct vmk_SemaphoreRWInt *vmk_SemaphoreRW; /* *********************************************************************** * vmk_SemaCreate -- */ /** * * \ingroup Semaphores * \brief Allocate and initialize a counting semaphore * * \note Requires that the module heap be initialized. * * \param[out] sema New counting semaphore. * \param[in] moduleID Module on whose behalf the semaphore * is created. * \param[in] name Human-readable name of the semaphore. * \param[in] value Initial count. * * \retval VMK_OK The semaphore was successfully created * \retval VMK_NO_MEMORY The semaphore could not be allocated * \retval VMK_NO_MODULE_HEAP The module has no heap to allocate from * *********************************************************************** */ VMK_ReturnStatus vmk_SemaCreate( vmk_Semaphore *sema, vmk_ModuleID moduleID, const char *name, vmk_int32 value); /* *********************************************************************** * vmk_BinarySemaCreate -- */ /** * * \ingroup Semaphores * \brief Allocate and initialize a binary semaphore * * \note Requires that the module heap be initialized. * * \param[out] sema New counting semaphore. * \param[in] moduleID Module on whose behalf the semaphore * is created. * \param[in] name Human-readable name of the semaphore. * \param[in] majorRank Major rank of the semaphore. * The rank value must be greater than or * equal to VMK_SEMA_RANK_MIN and less than * or equal to VMK_SEMA_RANK_MAX. * \param[in] minorRank Minor rank of the semaphore. * The rank value must be greater than or * equal to VMK_SEMA_RANK_MIN and less than * or equal to VMK_SEMA_RANK_MAX. * * \retval VMK_OK The semaphore was successfully created * \retval VMK_NO_MEMORY The semaphore could not be allocated * \retval VMK_NO_MODULE_HEAP The module has no heap to allocate from * *********************************************************************** */ VMK_ReturnStatus vmk_BinarySemaCreate( vmk_Semaphore *sema, vmk_ModuleID moduleID, const char *name, vmk_SemaphoreRank majorRank, vmk_SemaphoreRankMinor minorRank); /* *********************************************************************** * _vmkSemaIsLocked * * This is used by VMK_ASSERT_SEMA_LOCKED and VMK_ASSERT_SEMA_UNLOCKED. * VMKAPI users should not call this function directly. * *********************************************************************** */ /** \cond nodoc */ VMK_ReturnStatus _vmkSemaIsLocked( vmk_Semaphore *sema, vmk_Bool *isLocked); /** \endcond */ /* *********************************************************************** * VMK_ASSERT_SEMA_LOCKED -- */ /** * * \ingroup Semaphores * \brief Assert that a semaphore is currently locked only in * debug builds. * * \param[in] sema Semaphore to check. * *********************************************************************** */ #if defined(VMX86_DEBUG) #define VMK_ASSERT_SEMA_LOCKED(sema) \ do { \ vmk_Bool _vmkCheckLockState ; \ VMK_ASSERT(_vmkSemaIsLocked((sema),&_vmkCheckLockState) == \ VMK_OK); \ VMK_ASSERT(_vmkCheckLockState); \ } while(0) #else #define VMK_ASSERT_SEMA_LOCKED(sema) #endif /* *********************************************************************** * VMK_ASSERT_SEMA_UNLOCKED -- */ /** * * \ingroup Semaphores * \brief Assert that a semaphore is currently unlocked only in * debug builds. * * \param[in] sema Semaphore to check. * *********************************************************************** */ #if defined(VMX86_DEBUG) #define VMK_ASSERT_SEMA_UNLOCKED(sema) \ do { \ vmk_Bool _vmkCheckLockState ; \ VMK_ASSERT(_vmkSemaIsLocked((sema),&_vmkCheckLockState) == \ VMK_OK); \ VMK_ASSERT(!_vmkCheckLockState); \ } while(0) #else #define VMK_ASSERT_SEMA_UNLOCKED(sema) #endif /* *********************************************************************** * vmk_SemaLock -- */ /** * * \ingroup Semaphores * \brief Acquire a semaphore * * \pre Shall be called from a blockable context. * \pre The caller shall not already hold a semaphore of lower or equal * rank if the semaphore is a binary semaphore. * * \param[in] sema The semaphore to acquire. * *********************************************************************** */ void vmk_SemaLock( vmk_Semaphore *sema); /* *********************************************************************** * vmk_SemaTryLock -- */ /** * * \ingroup Semaphores * \brief Try to acquire a semaphore. * * This tries to acquire the given semaphore once. * If the semaphore is already locked, it returns immediately. * * \pre Shall be called from a blockable context. * * \param[in] sema Semaphore to attempt to acquire. * * \retval VMK_OK The semaphore was successfully acquired. * \retval VMK_BUSY The semaphore is currently locked. * *********************************************************************** */ VMK_ReturnStatus vmk_SemaTryLock( vmk_Semaphore *sema); /* *********************************************************************** * vmk_SemaUnlock -- */ /** * * \ingroup Semaphores * \brief Release a semaphore * * \param[in] sema Semaphore to unlock. * *********************************************************************** */ void vmk_SemaUnlock( vmk_Semaphore *sema); /* *********************************************************************** * vmk_SemaDestroy -- */ /** * * \ingroup Semaphores * \brief Destroy a semaphore * * Revert all side effects of vmk_SemaCreate or vmk_BinarySemaCreate. * * \param[in] sema Semaphore to destroy. * *********************************************************************** */ void vmk_SemaDestroy(vmk_Semaphore *sema); /* *********************************************************************** * VMK_ASSERT_RWSEMA_HAS_READERS -- */ /** * * \ingroup Semaphores * \brief Assert that a readers-writers semaphore has at least one * shared reader only in debug builds. * * \param[in] sema Semaphore to check. * *********************************************************************** */ #if defined(VMX86_DEBUG) #define VMK_ASSERT_RWSEMA_HAS_READERS(sema) \ do { \ VMK_ASSERT(vmk_RWSemaHasReaders(sema) == VMK_TRUE); \ } while(0) #else #define VMK_ASSERT_RWSEMA_HAS_READERS(sema) #endif /* *********************************************************************** * VMK_ASSERT_RWSEMA_HAS_WRITER -- */ /** * * \ingroup Semaphores * \brief Assert that a readers-writers semaphore has a writer only in * debug builds. * * \param[in] sema Semaphore to check. * *********************************************************************** */ #if defined(VMX86_DEBUG) #define VMK_ASSERT_RWSEMA_HAS_WRITER(sema) \ do { \ VMK_ASSERT(vmk_RWSemaHasWriter(sema) == VMK_TRUE); \ } while(0) #else #define VMK_ASSERT_RWSEMA_HAS_WRITER(sema) #endif /* *********************************************************************** * VMK_ASSERT_RWSEMA_HAS_READERS_WRITERS -- */ /** * * \ingroup Semaphores * \brief Assert that a readers-writers semaphore has a writer only in * debug builds. * * \param[in] sema Semaphore to check. * *********************************************************************** */ #if defined(VMX86_DEBUG) #define VMK_ASSERT_RWSEMA_HAS_READERS_WRITERS(sema) \ do { \ VMK_ASSERT(vmk_RWSemaHasReadersWriters(sema) == VMK_TRUE); \ } while(0) #else #define VMK_ASSERT_RWSEMA_HAS_READERS_WRITERS(sema) #endif /* *********************************************************************** * vmk_RWSemaCreate -- */ /** * * \ingroup Semaphores * \brief Allocate and initialize a readers-writers semaphore * * \param[out] sema New readers-writers semaphore. * \param[in] moduleID Module on whose behalf the semaphore * is created. * \param[in] name Human-readable name of the semaphore. * *********************************************************************** */ VMK_ReturnStatus vmk_RWSemaCreate( vmk_SemaphoreRW *sema, vmk_ModuleID moduleID, const char *name); /* *********************************************************************** * vmk_RWSemaDestroy -- */ /** * * \ingroup Semaphores * \brief Destroy a readers-writers semaphore * * Revert all side effects of vmk_RWSemaCreate. * * \param[in] sema Readers-writers semaphore to destroy. * *********************************************************************** */ void vmk_RWSemaDestroy(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_RWSemaReadLock -- */ /** * * \ingroup Semaphores * \brief Acquire a readers-writers semaphore for shared read access. * * \pre Shall be called from a blockable context. * * \param[in] sema Readers-writers semaphore to acquire. * *********************************************************************** */ void vmk_RWSemaReadLock(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_RWSemaWriteLock -- */ /** * * \ingroup Semaphores * \brief Acquire a readers-writers semaphore for exclusive write * access. * * \pre Shall be called from a blockable context. * * \param[in] sema Readers-writers semaphore to acquire. * *********************************************************************** */ void vmk_RWSemaWriteLock(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_RWSemaReadUnlock -- */ /** * * \ingroup Semaphores * \brief Release a readers-writers semaphore from shared read access. * * \param[in] sema Readers-writers semaphore to release. * *********************************************************************** */ void vmk_RWSemaReadUnlock(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_RWSemaWriteUnlock -- */ /** * * \ingroup Semaphores * \brief Release a readers-writers semaphore from exclusive write * access. * * \param[in] sema Readers-writers semaphore to release. * *********************************************************************** */ void vmk_RWSemaWriteUnlock(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_RWSemaUpgradeFromRead -- */ /** * * \ingroup Semaphores * \brief Upgrade a readers-writers semaphore to exclusive write access. * * This requests an upgrade to exclusive writers access for the * readers-writers semaphore while already holding shared reader access. * If the upgrade is not immediately available, only the first caller * can block waiting for the upgrade. Others fail, but they retain * shared reader access. * * \pre Shall be called from a blockable context. * \pre Shall already have read access to the semaphore. * * \param[in] sema Readers-writers semaphore to upgrade. * * \retval VMK_OK The semaphore was upgraded. * \retval VMK_BUSY The semaphore could not be upgraded. * *********************************************************************** */ VMK_ReturnStatus vmk_RWSemaUpgradeFromRead(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_RWSemaTryUpgradeFromRead -- */ /** * * \ingroup Semaphores * \brief Attempt to upgrade a readers-writers semaphore to * exclusive write access. * * This attempts to obtain exclusive writers access to the * readers-writers semaphore while already holding shared reader access. * If the upgrade is not immediately available, shared reader access * is retained. * * \pre Shall already have read access to the semaphore. * * \param[in] sema Readers-writers semaphore to upgrade. * * \retval VMK_OK The semaphore was upgraded. * \retval VMK_BUSY The semaphore could not be upgraded. * *********************************************************************** */ VMK_ReturnStatus vmk_RWSemaTryUpgradeFromRead(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_RWSemaDowngradeToRead -- */ /** * * \ingroup Semaphores * \brief Downgrade a readers-writers semaphore from exclusive * write access to shared read access. * * \pre Shall already have write access to the semaphore. * * \param[in] sema Readers-writers semaphore to downgrade. * *********************************************************************** */ void vmk_RWSemaDowngradeToRead(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_RWSemaHasReaders -- */ /** * * \ingroup Semaphores * \brief Determine if a readers-writers semaphore currently has one or * more readers. * * \param[in] sema Readers-writers semaphore to inspect. * *********************************************************************** */ vmk_Bool vmk_RWSemaHasReaders(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_SemaHasWriter -- */ /** * * \ingroup Semaphores * \brief Determine if a readers-writers semaphore currently has * a writer. * * \param[in] sema Readers-writers semaphore to inspect. * *********************************************************************** */ vmk_Bool vmk_RWSemaHasWriter(vmk_SemaphoreRW *sema); /* *********************************************************************** * vmk_SemaHasReadersWriters -- */ /** * * \ingroup Semaphores * \brief Determine if a readers-writers semaphore currently has any * readers or an exclusive writer. * * \param[in] sema Readers-writers semaphore to inspect. * *********************************************************************** */ vmk_Bool vmk_RWSemaHasReadersWriters(vmk_SemaphoreRW *sema); #endif /* _VMKAPI_SEM_H_ */ /** @} */