#ifndef _xmk_sema_h_ #define _xmk_sema_h_ /*---------------------------------------------------------------------------- ** SUMMARY: XMK Semaphore API (SEMA) ** ** DESCRIPTION: ** This file provides interfaces for counting semaphores. Semaphores are ** counters for resources shared between threads. The basic operations on ** semaphores are: increment the counter atomically, and wait until the ** counter is non-null and decrement it atomically. ** ** TIMEOUTS ** -------- ** The default/standard interface for semaphores does not have a timeout ** period associated with the wait/decrement operation. If the timeout ** functionality is needed, use the USE_XMK_SEMAPHORES_WITH_TIMEOUT ** configuration option. If you specify USE_XMK_SEMAPHORES_WITH_TIMEOUT, ** do not specify USE_XMK_SEMAPHORES. ** ** PERFORMACE NOTE ** --------------- ** Semaphores-with-a-timeout have a significantly larger ROM and RAM ** footprint and higher CPU/Run-time overhead compared to the standard ** semaphores. ** ** ** CONFIGURATION OPTION: USE_XMK_SEMAPHORES or ** USE_XMK_SEMAPHORES_WITH_TIMEOUT ** ** DEPENDENCIES: ** To use this interface the following XMK service(s) MUST always be ** enabled/configured: ** USE_XMK_CORE_KERNEL ** USE_XMK_THREAD_xSLEEP (when using USE_XMK_SEMAPHORES_WITH_TIMEOUT) ** ** NOTES: ** 1. 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 a macro. ----------------------------------------------------------------------------*/ #include "xmkcfg.h" /* For: Project/Application kernel configuraiton */ #ifdef __cplusplus extern "C" { #endif /*-------------- MAGIC CONSTANTS -------------------------------------------*/ /** NULL Semaphore handle */ #define XMK_NULL_SEMAPHORE _XMK_NULL_SEMAPHORE /** Maximum legal count for a semaphore */ #define XMK_SEMA_VALUE_MAX _XMK_SEMA_VALUE_MAX /** Infinite timeout period (aka no timeout) */ #define XMK_SEMA_NO_TIMEOUT _XMK_SEMA_NO_TIMEOUT /* ** ERROR CODES */ /** Attempt to destroy a Semaphore that had one or more threads waiting to it */ #define XMK_ERRFATAL_SEMA_STRANDED_WAITERS _XMK_ERRFATAL_SEMA_STRANDED_WAITERS /** An attempt was made to increment and/or set the semaphore count greater than XMK_SEMA_VALUE_MAX. */ #define XMK_ERRFATAL_SEMA_EXCEEDING_MAX_VALUE _XMK_ERRFATAL_SEMA_EXCEEDING_MAX_VALUE /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method is used to iniitalize a semaphore for use by the application. The count associated with the semaphore is set initially to the function arg: value. NOTES: o The application is responsible for allocating the memory for the semaphore data structure. o The range of the semaphore count is the unsigned range of the data type, XMK_SEMA_COUNTER (default data type is: unsigned char). o This method CAN be called ANY time EVEN before Xmk_initialize(). Prototype: void Xmk_semaInit(XMK_SEMAPHORE* sema, XMK_SEMA_COUNTER value); */ #define Xmk_semaInit(s,i) _Xmk_semaInit(s,i) /** This method is used to free kernel resources that are associated with the previously initialized. If there are suspended thread(s) waiting on the the semaphore when this method is called, a fatal error is generated. NOTES: o The application is responsible for freeing the memory of the semaphore data structure. o Passing an uninitialized semaphore will result in un-defined behavior (and most likely crash your application). Prototype: void Xmk_semaDestroy( XMK_SEMAPHORE* sema ); */ #define Xmk_semaDestroy(s) _Xmk_semaDestroy(s) /** This method atomically "increases the count" of the semaphore specified by sema. If there is a suspended thread waiting on the semaphore, the thread is made ready for execution. If no thread is waiting, the semaphore's count is incremented by 1. NOTES: o This method can ONLY be called from a thread context. o Passing an uninitialized semaphore will result in un-defined behavior (and most likely crash your application). Prototype: void Xmk_semaSignal( XMK_SEMAPHORE* sema ); */ #define Xmk_semaSignal(s) _Xmk_semaSignal(s) /** This method is the same as Xmk_semaSignal() except that can ONLY be called from the context of an interrupt service routine. Prototype: void Xmk_isr_semaSignal( XMK_SEMAPHORE* sema ); */ #define Xmk_isr_semaSignal(s) _Xmk_isr_semaSignal(s) /** This method suspends the calling thread until the semaphore pointed to by sema has non-zero count. It then atomically decreases the semaphore count. NOTES: o This method can ONLY be called from a thread context. o Passing an uninitialized semaphore will result in un-defined behavior (and most likely crash your application). Prototype: void Xmk_semaWait( XMK_SEMAPHORE* sema ); */ #define Xmk_semaWait(s) _Xmk_semaWait(s) /** This method is the same as Xmk_semaWait(), except the method will timeout and/or return after the specified time interval if the semaphore was not signaled. The method normally returns non-zero (true). It only returns 0 (false) if the thread 'waited' on the semaphore and the timeout period expired before the semaphore was signaled. NOTES: o This method is ONLY available if the configuration option USE_XMK_SEMAPHORES_WITH_TIMEOUT is used. o This method can ONLY be called from a thread context. o If XMK_SEMA_NO_TIMEOUT is specified as the timeout period, the method behaves exactly the same as Xmk_semaWait(), i.e. nevers times-out. o The longest timeout period is XMK_SLEEP_MAX_DELAY-1 sleep ticks. o If 0 is specified as the timout period, then the call acts as a 'polled' operation on the semaphore in that it will never block even if the semaphore count is zero when called. o CAUTION: Do not assume that since the method returned false due to a time-out, that the semaphore count is now zero. It is possible that the semaphore is/was signaled after the 'time-out', BUT before the application has an opportunity to check the return code. o Passing an uninitialized semaphore will result in un-defined behavior (and most likely crash your application). Prototype: XMK_BOOL Xmk_semaWaitTimeout( XMK_SEMAPHORE* sema, XMK_SLEEPTICKS maxwait ) */ #define Xmk_semaWaitTimeout(s,t) _Xmk_semaWaitTimeout(s,t) #ifdef __cplusplus } #endif /*--------------------------------------------------------------------------*/ #endif /* end _xmk_sema_h_ */