You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
11 KiB
306 lines
11 KiB
/*
|
|
* Copyright 2002-2019 Intel Corporation.
|
|
*
|
|
* This software and the related documents are Intel copyrighted materials, and your
|
|
* use of them is governed by the express license under which they were provided to
|
|
* you ("License"). Unless the License provides otherwise, you may not use, modify,
|
|
* copy, publish, distribute, disclose or transmit this software or the related
|
|
* documents without Intel's prior written permission.
|
|
*
|
|
* This software and the related documents are provided as is, with no express or
|
|
* implied warranties, other than those that are expressly stated in the License.
|
|
*/
|
|
|
|
// <COMPONENT>: os-apis
|
|
// <FILE-TYPE>: component public header
|
|
|
|
#ifndef OS_APIS_MUTEX_H_INCLUDED_
|
|
#define OS_APIS_MUTEX_H_INCLUDED_
|
|
|
|
/*!
|
|
* @defgroup OS_APIS_MUTEX Mutex
|
|
* @brief Implementation of mutex lock.
|
|
*/
|
|
|
|
typedef ADDRINT OS_SPINLOCK_TYPE;
|
|
|
|
typedef enum _OS_APIS_MUTEX_KIND {
|
|
OS_MUTEX_DEPTH_SIMPLE = 0, //!< This lock can only be acquired once, no matter if the same thread tried to acquire it twice
|
|
OS_MUTEX_DEPTH_RECURSIVE //!< Recursive lock that can be acquired recursively by the same thread.
|
|
} OS_MUTEX_DEPTH;
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* This type holds a representation of a mutex.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
typedef struct _OS_APIS_MUTEX_TYPE {
|
|
OS_MUTEX_DEPTH kind;
|
|
OS_SPINLOCK_TYPE spinlock;
|
|
OS_EVENT event;
|
|
UINT32 num_waiters;
|
|
UINT32 depth;
|
|
#ifndef TARGET_WINDOWS
|
|
UINT32 spinlock_fork_count;
|
|
#endif
|
|
} OS_MUTEX_TYPE_IMPL;
|
|
|
|
typedef PRE_ALIGNTO(CPU_MEMORY_CACHELINE_SIZE) union
|
|
{
|
|
OS_MUTEX_TYPE_IMPL impl;
|
|
char reserved[2 * CPU_MEMORY_CACHELINE_SIZE];
|
|
} POST_ALIGNTO(CPU_MEMORY_CACHELINE_SIZE) OS_MUTEX_TYPE;
|
|
|
|
#ifdef TARGET_WINDOWS
|
|
#define OS_APIS_MUTEX_IMPL_DEPTH_SIMPLE_INITIALIZER {OS_MUTEX_DEPTH_SIMPLE ,(OS_SPINLOCK_TYPE)0, OS_EVENT_INITIALIZER, \
|
|
(UINT32)0, (UINT32)0}
|
|
#else
|
|
#define OS_APIS_MUTEX_IMPL_DEPTH_SIMPLE_INITIALIZER {OS_MUTEX_DEPTH_SIMPLE ,(OS_SPINLOCK_TYPE)0, OS_EVENT_INITIALIZER, \
|
|
(UINT32)0, (UINT32)0, (UINT32)0}
|
|
#endif
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Static initializer for a mutex.
|
|
* It is guaranteed that a (simple) mutex initialized this way:
|
|
*
|
|
* OS_MUTEX_TYPE mutex = OS_APIS_MUTEX_DEPTH_SIMPLE_INITIALIZER;
|
|
*
|
|
* Will be initialized before any constuctor will be called.
|
|
* Also, the static initializer for a simple mutex must be all zeros.
|
|
* This is because we want mutex that is initialized in a default way
|
|
* (all zeros according to the C++ standard) will be initialized correctly
|
|
* to a simple mutex.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
#define OS_APIS_MUTEX_DEPTH_SIMPLE_INITIALIZER {OS_APIS_MUTEX_IMPL_DEPTH_SIMPLE_INITIALIZER}
|
|
|
|
#ifdef TARGET_WINDOWS
|
|
#define OS_APIS_MUTEX_IMPL_DEPTH_RECURSIVE_INITIALIZER {OS_MUTEX_DEPTH_RECURSIVE ,(OS_SPINLOCK_TYPE)0, OS_EVENT_INITIALIZER, \
|
|
(UINT32)0, (UINT32)0}
|
|
#else
|
|
#define OS_APIS_MUTEX_IMPL_DEPTH_RECURSIVE_INITIALIZER {OS_MUTEX_DEPTH_RECURSIVE ,(OS_SPINLOCK_TYPE)0, OS_EVENT_INITIALIZER, \
|
|
(UINT32)0, (UINT32)0, (UINT32)0}
|
|
#endif
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Static initializer for a mutex.
|
|
* It is guaranteed that a (recursive) mutex initialized this way:
|
|
*
|
|
* OS_MUTEX_TYPE mutex = OS_APIS_MUTEX_DEPTH_SIMPLE_INITIALIZER;
|
|
*
|
|
* Will be initialized before any constuctor will be called.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
#define OS_APIS_MUTEX_DEPTH_RECURSIVE_INITIALIZER {OS_APIS_MUTEX_IMPL_DEPTH_RECURSIVE_INITIALIZER}
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Initialize a mutex.
|
|
* A mutex must be initialized before being used.
|
|
* Use this function to initialize the mutex or use one of the static initializers.
|
|
*
|
|
* @param[in] lock The mutex to initialize.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
void OS_MutexInit(volatile OS_MUTEX_TYPE *lock);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Initialize a recursive mutex.
|
|
* A mutex must be initialized before being used.
|
|
* Use this function to initialize a recursive mutex or use one of the static initializers.
|
|
*
|
|
* @param[in] lock The mutex to initialize.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
void OS_MutexRecursiveInit(volatile OS_MUTEX_TYPE *lock);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Destroys a mutex after it is no longer in use.
|
|
*
|
|
* @note The behavior of a mutex after it was destroyed is undefined.
|
|
* It is the responsibility of the user to verify that no other thread
|
|
* is using the mutex when it comes to destroy it.
|
|
*
|
|
* @param[in] lock The mutex to destroy.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
void OS_MutexDestroy(volatile OS_MUTEX_TYPE *lock);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Aquire a mutex, blocks until the mutex becomes available (according to the mutex's semantics).
|
|
*
|
|
* @param[in] lock The mutex to acquire.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
void OS_MutexLock(volatile OS_MUTEX_TYPE *lock);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Aquire a mutex, blocks until the mutex becomes available (according to the mutex's semantics).
|
|
* This function is similar to OS_MutexLock() except that it accept as an argument the thread ID
|
|
* of the thread that want to acquire the lock (which is usually the current thread).
|
|
*
|
|
* @param[in] lock The mutex to acquire.
|
|
* @param[in] tid The thread ID of the thread that wants to acquire the mutex.
|
|
* This argument can be INVALID_NATIVE_TID if the thread ID is
|
|
* not known (e.g. in a mutex of type OS_MUTEX_DEPTH_SIMPLE).
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
void OS_MutexLockTid(volatile OS_MUTEX_TYPE *lock, NATIVE_TID myTid);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Tries to aquire a mutex:\n
|
|
* - If the mutex is available, acquire it and return true.\n
|
|
* - Otherwise, return false.
|
|
*
|
|
* @param[in] lock The mutex to acquire.
|
|
*
|
|
* @retval TRUE If the mutex was acquired.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
BOOL_T OS_MutexTryLock(volatile OS_MUTEX_TYPE *lock);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Tries to aquire a mutex:\n
|
|
* - If the mutex is available, acquire it and return true.\n
|
|
* - Otherwise, return false.
|
|
* This function is similar to OS_MutexTryLock() except that it accept as an argument the thread ID
|
|
* of the thread that want to acquire the lock (which is usually the current thread).
|
|
*
|
|
* @param[in] lock The mutex to acquire.
|
|
* @param[in] tid The thread ID of the thread that wants to acquire the mutex.
|
|
* This argument can be INVALID_NATIVE_TID if the thread ID is
|
|
* not known (e.g. in a mutex of type OS_MUTEX_DEPTH_SIMPLE).
|
|
*
|
|
* @retval TRUE If the mutex was acquired.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
BOOL_T OS_MutexTryLockTid(volatile OS_MUTEX_TYPE *lock0, NATIVE_TID myTid);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Checks whether a mutex state is locked.\n
|
|
* Doesn't affect the mutex state and doesn't block.
|
|
*
|
|
* @param[in] lock The mutex to check.
|
|
*
|
|
* @retval TRUE If the mutex is locked.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
BOOL_T OS_MutexIsLocked(volatile OS_MUTEX_TYPE *lock);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Aquire a mutex, blocks until the mutex becomes available (according to the mutex's semantics).
|
|
* or 'timeoutMillis' milli seconds passed.
|
|
* When 'timeoutMillis' is zero, this function is identical to @ref OS_MutexTryLock().
|
|
*
|
|
* @param[in] lock The mutex to acquire.
|
|
* @param[in] timeoutMillis The timeout to block.
|
|
*
|
|
* @retval TRUE If the mutex is locked.
|
|
* FALSE If the timeout was expired and the mutex can't be acquired during that time.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
BOOL_T OS_MutexTimedLock(volatile OS_MUTEX_TYPE *lock, UINT32 timeoutMillis);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Aquire a mutex, blocks until the mutex becomes available (according to the mutex's semantics).
|
|
* or 'timeoutMillis' milli seconds passed.
|
|
* When 'timeoutMillis' is zero, this function is identical to @ref OS_MutexTryLock().
|
|
* This function is similar to OS_MutexTimedLock() except that it accept as an argument the thread ID
|
|
* of the thread that want to acquire the lock (which is usually the current thread).
|
|
*
|
|
* @param[in] lock The mutex to acquire.
|
|
* @param[in] timeoutMillis The timeout to block.
|
|
* @param[in] tid The thread ID of the thread that wants to acquire the mutex.
|
|
* This argument can be INVALID_NATIVE_TID if the thread ID is
|
|
* not known (e.g. in a mutex of type OS_MUTEX_DEPTH_SIMPLE).
|
|
*
|
|
* @retval TRUE If the mutex is locked.
|
|
* FALSE If the timeout was expired and the mutex can't be acquired during that time.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
BOOL_T OS_MutexTimedLockTid(volatile OS_MUTEX_TYPE *lock0, NATIVE_TID myTid, UINT32 timeoutMillis);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Queries the owner of a recursive mutex.
|
|
*
|
|
* @param[in] lock The mutex to query.
|
|
*
|
|
* @retval NATIVE_TID The owner of the mutex of INVALID_NATIVE_TID is the mutex is not locked.
|
|
*
|
|
* @note The return value of this function is undefined for non-recursive (simple) mutex.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
NATIVE_TID OS_MutexGetOwner(volatile OS_MUTEX_TYPE *lock);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Queries the recursion of a recursive mutex. I.e. the number of times that the unlock functions needs to be
|
|
* called before the mutex can be acquired by other thread.
|
|
*
|
|
* @param[in] lock The mutex to query.
|
|
*
|
|
* @retval UINT32 The recursion level of the mutex.
|
|
*
|
|
* @note For non-recursive (simple) mutex, the return value of this function is 1 if the mutex is lock,
|
|
* or 0 if the mutex is unlocked.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
UINT32 OS_MutexGetRecursionLevel(volatile OS_MUTEX_TYPE *lock);
|
|
|
|
/*! @ingroup OS_APIS_MUTEX
|
|
* Releases a mutex.
|
|
*
|
|
* @param[in] lock The mutex to release.
|
|
*
|
|
* @retval TRUE If the mutex was locked and as a result of this call was unlocked.
|
|
*
|
|
* @par Availability:
|
|
* - @b O/S: Windows, Linux & macOS*
|
|
* - @b CPU: All
|
|
*/
|
|
BOOL_T OS_MutexUnlock(volatile OS_MUTEX_TYPE *lock);
|
|
|
|
#endif // OS_APIS_MUTEX_H_INCLUDED_
|