#ifndef _aplmt_os_mutexapi_h_ #define _aplmt_os_mutexapi_h_ /*---------------------------------------------------------------------------- ** SUMMARY: Mutex API (MX) ** ** DESCRIPTION: ** This file provides generic interfaces for mutual exclusion, a.k.a ** mutexes. Types of mutexes currently supported: ** - Non-recursive mutexes. This type of mutex is functionally ** the same as using a binary semaphore for mutual exclusion. ** ** - Exclusive mutex. The Exclusive mutex (there is only one) is ** a mutex-object that does not cause the caller block, but still ** provides mutual exclusion. In addition, the Exclusive mutex provides ** mutual exclusion across interrupt and thread contexts. Typically the ** Exclusive mutex is implemented by enabling/disabling interrupts. The ** Exclusive mutex should be used with care since it can/will impact the ** responsiveness of the ENTIRE application. ** ** - Threading mutex. The Threading mutex (there is only one) is very ** similar to the Exclusive mutex, in that it provides mutual exclusion ** without causing the caller to block. But it is different in that it ** ONLY provides mutual exclusion across thread contexts. Typically the ** Threading mutex is implemented by enabling/disabling thread ** scheduling. Using this mutex is 'less dangerous' than using the ** Exclusive mutex, but it can/will impact the performance of the ** application by increasing the thread-switching latencies. ** ** ** CONFIGURATION ** ------------- ** COMPILE: none. ** ** APPLICATION: none. ** ** PLATFORM: Definitions: ** PLATFORM_APLMT_NULL_MUTEX_HANDLE ** ** Data Types: ** PLATFORM_APLMT_MUTEX_HDL_T ** PLATFORM_APLMT_MUTEXFAC_HDL_T ** ** NOTES: ** 1. Unless explicitly stated otherwise, NONE of the following methods may be ** called from interrupt service routines. ** 2. Unless explicitly stated otherwise, NONE of the following methods may be ** called before the platform's kernel is running. ** 3. Unless explicitly stated otherwise, all of the following methods ARE ** thread-safe. ** 4. For efficency/optimization some methods are 'inlined'. The inlining ** is done by using the preprocessor/macros. The application should ** treat all methods as function calls and not rely on the fact they may ** be currently defined as macros. ----------------------------------------------------------------------------*/ #include "apl/types/types.h" /* For: basic types */ #ifdef __cplusplus extern "C" { #endif /*-------------- CONSTANTS/MACROS --------------------------------------------*/ /** NULL Thread Handle */ #define APLMT_NULL_MUTEX_HANDLE PLATFORM_APLMT_NULL_MUTEX_HANDLE /** The following Macros allow the application to 'nest' calls to the Exclusive mutex. VERY IMPORATANT: See the description of Aplmt_exclusiveLock() for when it is appropriate to use the Exclusive-Lock. The following code snippets show how to use the macros. void foo(void) { APLMT_MUTEX_DECL_EXLOCK_STATE(lockstate); ... // Enter critical section APLMT_MUTEX_EXLOCK_ENTER(lockstate); if ( ) foo(); // Exit critical section APLMT_MUTEX_EXLOCK_EXIT(lockstate); } */ #define APLMT_MUTEX_DECL_EXLOCK_STATE(s) _APLMT_MUTEX_DECL_EXLOCK_STATE(s) #define APLMT_MUTEX_EXLOCK_ENTER(s) _APLMT_MUTEX_EXLOCK_ENTER(s) #define APLMT_MUTEX_EXLOCK_EXIT(s) _APLMT_MUTEX_EXLOCK_EXIT(s) /*-------------- TYPES -----------------------------------------------------*/ /** Handle to a mutex */ #define AplmtMutexHdl PLATFORM_APLMT_MUTEX_HDL_T /** Handle to a non-recursive mutexe Factory */ #define AplmtMutexfacHdl PLATFORM_APLMT_MUTEXFAC_HDL_T /*-------------- INLINE PLATFORM IMPLEMENTATION ----------------------------*/ #include "platform/mutexapi.h" #include "aplmt/os/mutex.h" /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method locks the specified NON-RECURSIVE mutex. If the mutex is currently unlocked, it becomes locked and owned by the calling thread, and the method returns immediately. If the mutex is already locked by another thread, the method suspends the calling thread until the mutex is unlocked. Prototype: void Aplmt_mutexLock( AplmtMutexHdl mutex ); */ #define Aplmt_mutexLock _Aplmt_mutexLock /** This method unlocks the specified NON-RECURSIVE mutex. The mutex is assumed to be locked and owned by the calling thread. Prototype: void Aplmt_mutexUnlock( AplmtMutexHdl mutex ); */ #define Aplmt_mutexUnlock _Aplmt_mutexUnlock /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method locks the platform's Exclusive Mutex. This is a non-recursive lock, i.e. you can NOT nest calls to this method. This method can be called from a thread context as well as an interrupt service routine. NOTES: o BE VERY CAREFUL when using this method. Since this method typically maps to disable interrupts. The first issue is the impact on the application interrupt latency if interrupts are left disabled too long. The second issue deals with potential context switches. Depending on the underlying implementation is is possible/probable that if the application calls an OS method, that a context switch can occur - EVEN if Exclusive-Lock is locked (i.e. interrupts are disabled). If/when a context switch does occur, there is no guaranty that interrupts stay disabled, especially when the new/next thread runs. If interrupts do get enabled, then the 'lock' is defeated and your MX region is NOT protected! SUMMARY: 1) Do NOT use this method if you don't absolutely have to. 2) You can NOT use the Exclusive-Lock if the MX region it is protecting makes direct or indirect calls to any APLMT OS abstaction layer method. Prototype: void Aplmt_exclusiveLock(); */ #define Aplmt_exclusiveLock _Aplmt_exclusiveLock /** This method unlocks the platform's Exclusive Mutex. This method can be called from a thread context as well as an interrupt service routine. NOTES: o See note above about the dangers involved with this method. Prototype: void Aplmt_exclusiveUnlock(); */ #define Aplmt_exclusiveUnlock _Aplmt_exclusiveUnlock /** This method returns non-zero (true) if the Exclusive Mutex is currently locked. This method can be called from a thread context as well as an interrupt service routine. Prototype: AplBool Aplmt_isExclusiveLocked(void); */ #define Aplmt_isExclusiveLocked _Aplmt_isExclusiveLocked /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method locks the platform's Threading Mutex. This is a recursive lock, i.e. you CAN nested calls to this method as long as there is a matching number of calls to Aplmt_threadUnlock(). Prototype: void Aplmt_thread(); */ #define Aplmt_thread _Aplmt_threadLock /** This method unlocks the platform's Threading Mutex. Prototype: void Aplmt_threadUnlock(); */ #define Aplmt_threadUnlock _Aplmt_threadUnlock /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method creates a non-recursive mutex. The method returns a handle to the newly created mutex, or NULL if the was an error. Prototype: AplmtMutexHdl Aplmt_createMutex(AplmtMutexfacHdl mutexFactoryToUse); */ #define Aplmt_createMutex _Aplmt_createMutex /** This method is used to destroy a non-recursive mutex that was created by the specified mutex factory. Prototype: void Aplmt_destroyMutex(AplmtMutexfacHdl mutexFactoryToUse, AplmtMutexHdl mutexToDestroy); */ #define Aplmt_destroyMutex _Aplmt_destroyMutex #ifdef __cplusplus } #endif /*--------------------------------------------------------------------------*/ #endif /* end _aplmt_os_mutexapi_h_ */