518 lines
15 KiB
C
518 lines
15 KiB
C
/* **********************************************************
|
|
* Copyright 2004 - 2009 VMware, Inc. All rights reserved.
|
|
* **********************************************************/
|
|
|
|
/*
|
|
* @VMKAPIMOD_LICENSE@
|
|
*/
|
|
|
|
/*
|
|
***********************************************************************
|
|
* Semaphores */ /**
|
|
* \addtogroup Core
|
|
* @{
|
|
* \defgroup Semaphores Semaphores
|
|
* @{
|
|
***********************************************************************
|
|
*/
|
|
|
|
#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 */
|
|
|
|
/**
|
|
* \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 -- */ /**
|
|
*
|
|
* \brief Allocate and initialize a counting semaphore
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* \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 -- */ /**
|
|
*
|
|
* \brief Allocate and initialize a binary semaphore
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* \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.
|
|
*
|
|
* \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_SemaAssertHasState --
|
|
*
|
|
* This is used by vmk_SemaAssertLocked() and vmk_SemaAssertUnlocked().
|
|
* VMKAPI clients should not call this function directly.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
/** \cond nodoc */
|
|
void vmk_SemaAssertHasState(
|
|
vmk_Semaphore *sema,
|
|
vmk_Bool locked);
|
|
/** \endcond */
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SemaAssertIsLocked -- */ /**
|
|
*
|
|
* \brief Assert that a semaphore is currently locked.
|
|
*
|
|
* \note This function will not block.
|
|
* \note This call only performs the check on a debug build.
|
|
*
|
|
* \param[in] sema Semaphore to check.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
static VMK_ALWAYS_INLINE void
|
|
vmk_SemaAssertIsLocked(
|
|
vmk_Semaphore *sema)
|
|
{
|
|
#ifdef VMX86_DEBUG
|
|
vmk_SemaAssertHasState(sema, VMK_TRUE);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SemaAssertIsUnlocked -- */ /**
|
|
*
|
|
* \brief Assert that a semaphore is currently unlocked.
|
|
*
|
|
* \note This function will not block.
|
|
* \note This call only performs the check on a debug build.
|
|
*
|
|
* \param[in] sema Semaphore to check.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
static VMK_ALWAYS_INLINE void
|
|
vmk_SemaAssertIsUnlocked(
|
|
vmk_Semaphore *sema)
|
|
{
|
|
#ifdef VMX86_DEBUG
|
|
vmk_SemaAssertHasState(sema, VMK_FALSE);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SemaLock -- */ /**
|
|
*
|
|
* \brief Acquire a semaphore
|
|
*
|
|
* \note This function may block.
|
|
*
|
|
* \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 -- */ /**
|
|
*
|
|
* \brief Try to acquire a semaphore.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* 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 -- */ /**
|
|
*
|
|
* \brief Release a semaphore
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* \param[in] sema Semaphore to unlock.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void vmk_SemaUnlock(
|
|
vmk_Semaphore *sema);
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SemaDestroy -- */ /**
|
|
*
|
|
* \brief Destroy a semaphore
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* Revert all side effects of vmk_SemaCreate or
|
|
* vmk_BinarySemaCreate.
|
|
*
|
|
* \param[in] sema Semaphore to destroy.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void vmk_SemaDestroy(vmk_Semaphore *sema);
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaCreate -- */ /**
|
|
*
|
|
* \brief Allocate and initialize a readers-writers semaphore
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* \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 -- */ /**
|
|
*
|
|
* \brief Destroy a readers-writers semaphore
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* Revert all side effects of vmk_RWSemaCreate.
|
|
*
|
|
* \param[in] sema Readers-writers semaphore to destroy.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void vmk_RWSemaDestroy(vmk_SemaphoreRW *sema);
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaReadLock -- */ /**
|
|
*
|
|
* \brief Acquire a readers-writers semaphore for shared read access.
|
|
*
|
|
* \note This function may block.
|
|
*
|
|
* \pre Shall be called from a blockable context.
|
|
*
|
|
* \param[in] sema Readers-writers semaphore to acquire.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void vmk_RWSemaReadLock(vmk_SemaphoreRW *sema);
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaWriteLock -- */ /**
|
|
*
|
|
* \brief Acquire a readers-writers semaphore for exclusive write
|
|
* access.
|
|
*
|
|
* \note This function may block.
|
|
*
|
|
* \pre Shall be called from a blockable context.
|
|
*
|
|
* \param[in] sema Readers-writers semaphore to acquire.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void vmk_RWSemaWriteLock(vmk_SemaphoreRW *sema);
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaReadUnlock -- */ /**
|
|
*
|
|
* \brief Release a readers-writers semaphore from shared read access.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* \param[in] sema Readers-writers semaphore to release.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void vmk_RWSemaReadUnlock(vmk_SemaphoreRW *sema);
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaWriteUnlock -- */ /**
|
|
*
|
|
* \brief Release a readers-writers semaphore from exclusive write
|
|
* access.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* \param[in] sema Readers-writers semaphore to release.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void vmk_RWSemaWriteUnlock(vmk_SemaphoreRW *sema);
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaUpgradeFromRead -- */ /**
|
|
*
|
|
* \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.
|
|
*
|
|
* \note This function may block.
|
|
*
|
|
* \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 -- */ /**
|
|
*
|
|
* \brief Attempt to upgrade a readers-writers semaphore to
|
|
* exclusive write access.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* 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 -- */ /**
|
|
*
|
|
* \brief Downgrade a readers-writers semaphore from exclusive
|
|
* write access to shared read access.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* \pre Shall already have write access to the semaphore.
|
|
*
|
|
* \param[in] sema Readers-writers semaphore to downgrade.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void vmk_RWSemaDowngradeToRead(vmk_SemaphoreRW *sema);
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaAssertHasReadersInt --
|
|
*
|
|
* This is used internally by vmk_RWSemaAssertHasReaders. VMKAPI
|
|
* clients should not call this function directly.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
/** \cond nodoc */
|
|
void vmk_RWSemaAssertHasReadersInt(vmk_SemaphoreRW *sema);
|
|
/** \endcond */
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaAssertHasReaders -- */ /**
|
|
*
|
|
* \brief Assert that a readers-writers semaphore has at least one
|
|
* shared reader. The check is only performed in debug builds.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
* \param[in] sema Semaphore to check.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
static VMK_ALWAYS_INLINE void
|
|
vmk_RWSemaAssertHasReaders(vmk_SemaphoreRW *sema)
|
|
{
|
|
#ifdef VMX86_DEBUG
|
|
vmk_RWSemaAssertHasReadersInt(sema);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SemaAssertHasWriterInt --
|
|
*
|
|
* This is used internally by vmk_RWSemaAssertHasWriter. VMKAPI
|
|
* clients should not call this function directly.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
/** \cond nodoc */
|
|
void vmk_RWSemaAssertHasWriterInt(vmk_SemaphoreRW *sema);
|
|
/** \endcond */
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaAssertHasWriter -- */ /**
|
|
*
|
|
* \brief Assert that a readers-writers semaphore has a writer.
|
|
* The check is only performed in debug builds.
|
|
*
|
|
* \note This call will not block.
|
|
*
|
|
* \param[in] sema Semaphore to check.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
static VMK_ALWAYS_INLINE void
|
|
vmk_RWSemaAssertHasWriter(vmk_SemaphoreRW *sema)
|
|
{
|
|
#ifdef VMX86_DEBUG
|
|
vmk_RWSemaAssertHasWriterInt(sema);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SemaAssertHasReadersWriterInt --
|
|
*
|
|
* This is used internally by vmk_RWSemaAssertHasReadersWriter.
|
|
* VMKAPI clients should not call this function directly.
|
|
*
|
|
* \note This function will not block.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
/** \cond nodoc */
|
|
void vmk_RWSemaAssertHasReadersWriterInt(vmk_SemaphoreRW *sema);
|
|
/** \endcond */
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_RWSemaAssertHasReadersWriter -- */ /**
|
|
*
|
|
* \brief Assert that a readers-writers semaphore has either readers
|
|
* or a writer. The check is only performed on debug builds.
|
|
*
|
|
* \note This call will not block.
|
|
*
|
|
* \param[in] sema Semaphore to check.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
static VMK_ALWAYS_INLINE void
|
|
vmk_RWSemaAssertHasReadersWriter(vmk_SemaphoreRW *sema)
|
|
{
|
|
#ifdef VMX86_DEBUG
|
|
vmk_RWSemaAssertHasReadersWriterInt(sema);
|
|
#endif
|
|
}
|
|
|
|
|
|
#endif /* _VMKAPI_SEM_H_ */
|
|
/** @} */
|
|
/** @} */
|