#ifndef _aplmt_kernelapi_h_ #define _aplmt_kernelapi_h_ /*---------------------------------------------------------------------------- ** SUMMARY: Basic Kernel/Thead Interfaces (KRN) ** ** DESCRIPTION: ** This file provides the interface for the most basic kernel/threading ** operations. ** ** ABOUT THREAD FACTORIES - Thread factories are great tools for creating ** threads with a no knowledge about the platform/OS. However, the ** concept gets complicated when it comes to deleting/destorying threads. ** The biggest issue with thread factories is deleting threads and how to ** reclaim the memory from the defunct threads. Dependening on the ** underlying OS/Kernel, it may or may not be possible to build a thread ** factory that does not leak memory. The standard workaround is not to ** delete/destory threads once they are created (duh ;-). There are several ** approaches for mimicking the behaviour of dynamic threads without actually ** physically destroying them in between 'uses'. ** ** DO I HAVE TO USE THE THREAD FACTORY INTERFACE? Yes and no. If you want make ** your code as platform independent as possible, then yes. If you don't care ** about platform independence, or you have sufficiently isolate the 'creator' ** poritions of your of code, then the answer is maybe. The multi-thread ** interfaces defined by the APL library include the concept of a thread- ** semaphore. For OS/Kernels do not natively support thread-semaphores, this ** functionality must be provided by platform specific APL code. To implement ** thread-semaphores externally to the OS/Kernel requires the use of thread ** specific storage for each thread. So to summarize, if the underlying ** OS/kernel does NOT natively support thread-semaphores, then the use of ** thread factory inteface IS REQUIRED. If your OS/Kernel provides direct ** support for thread-semaphore, then use of thread factory interface is ** OPTIONAL. ** ** NOTE: There is a platform independent alternative to thread factories. ** Thread Worker Pool Interface can be used as a poor-man's thread ** factory (i.e. when the platform's kernel does not deal well ** with recycling threads). The caveat is that the Thread Worker ** Pool approach only works if the order of thread creation is well ** defined and/or known. See the header file: src/aplmt/os/workerapi.h ** for more details. ** ** ** CONFIGURATION ** ------------- ** COMPILE: none. ** ** APPLICATION: none. ** ** PLATFORM: Data Types: ** PLATFORM_APLMT_THREADHDL_T ** PLATFORM_APLMT_THREADPRIORITY_T ** PLATFORM_APLMT_THREADFACHDL_T ** PLATFORM_APLMT_THREADENTRY_T ** PLATFORM_APLMT_CBFUNCTHREADLIST_T ** ** Definitions: ** PLATFORM_APLMT_THREADSTATE_WAITING ** PLATFORM_APLMT_THREADSTATE_READY ** PLATFORM_APLMT_THREADSTATE_READY_SIGNALED ** PLATFORM_APLMT_NULL_THREAD_HANDLE ** PLATFORM_APLMT_WAIT_NO_TIMEOUT ** ** ** 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 -------------------------------------------------*/ /** The following are intial states to be used when initializing threads. */ #define APLMT_THREADSTATE_WAITING PLATFORM_APLMT_THREADSTATE_WAITING #define APLMT_THREADSTATE_READY PLATFORM_APLMT_THREADSTATE_READY #define APLMT_THREADSTATE_READY_SIGNALED PLATFORM_APLMT_THREADSTATE_READY_SIGNALED /** NULL Thread Handle */ #define APLMT_NULL_THREAD_HANDLE PLATFORM_APLMT_NULL_THREAD_HANDLE /** Used to indicate no-timeout/infinite wait when using wait-with-timeout method (is required to be largest possible wait time for the timeout mechanism). */ #define APLMT_WAIT_NO_TIMEOUT PLATFORM_APLMT_WAIT_NO_TIMEOUT /** Maximum 'valid' timeout for wait-with-timeout method */ #define APLMT_WAIT_MAX_TIMEOUT (APLMT_WAIT_NO_TIMEOUT-1) /*-------------- TYPES -----------------------------------------------------*/ /** Thread Handle/Identifier */ #define AplmtThreadHdl PLATFORM_APLMT_THREADHDL_T /** Thread Priority */ #define AplmtThreadPriority PLATFORM_APLMT_THREADPRIORITY_T /** Handle to a thread Factory */ #define AplmtThreadfacHdl PLATFORM_APLMT_THREADFACHDL_T /** Thread entry function */ #define AplmtThreadEntry PLATFORM_APLMT_THREADENTRY_T /** Callback function for walking the thread list */ #define AplmtCBFuncThreadList PLATFORM_APLMT_CBFUNCTHREADLIST_T /*-------------- INLINE PLATFORM IMPLEMENTATION ----------------------------*/ #include "platform/kernelapi.h" /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method returns non-zero (true) if the underlying kernel/RTOS/OS is running. NOTES: o If the method returns true, it does not necessarily mean that the current thread/context was created via Aplmt_createThread(). o If the method return false, it does not necessarily mean that interrupts are currently disabled (though typically it does, but is it not guarantied by this interface). Prototype: AplBool Aplmt_isKernelRunning(void); */ #define Aplmt_isKernelRunning _Aplmt_isKernelRunning /** This method defines an interface for a thread factory for creating threads. The method returns the handle to the new created thread or NULL if there was an error (i.e. out-of-memory). DETAILS: -------- Naming: The specified 'threadName' must be a null terminated string. If the specified string exceeded the maximum length of the platform, it will be truncated. Priority: Priorities range from 0 to N, where N is dependent on the underlying OS. Zero is the highest priority, N is the lowest. Entry Function: The entry function must have the following function signature: void myEntryFunction(void* args); Thread Arguments: Data and/or parameter(s) can be passed to a thread when it is created through the 'args' function argument. 'Args' is a pointer to 'something', which is defined by the application. If no thread parameters are needed, set 'args' to zero. Thread and Stack Memory: The specified 'threadFactoryToUse' is responsible for providing any/all of the client supplied memory required by the platform's OS/Kernel. Initial states: The application is allowed to set the initial state of the thread's thread semaphore. By controlling the state of the thread semaphore, the application can control how a thread is 'started'. READY - The thread will run immediately upon creation assuming it is the highest priority thread ready to run. READY/SIGNALED - The same as READY except that the FIRST time the thread calls Aplmt_waitThread(), the thread will NOT block. WAITING - The thread will not run until some other thread signals its thread semaphore. Maximum Number of Threads The maximum number of threads is factory and/or platform dependent. Thread Handles: Thread handles are NOT guaranteed to be unique over time. As threads are created and deleted over time a newly create thread may have the same thread handle as a thread that previously existed. Thread handles are only guaranteed to be unique with respect to the current set of active/created threads. Prototype: AplmtThreadHdl Aplmt_createThread ( AplmtThreadfacHdl threadFactoryToUse, const char* threadName, AplmtThreadPriority priority, AplmtThreadEntry start, void* args, AplByte initialState ); */ #define Aplmt_createThread _Aplmt_createThread /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method causes the current thread to yield control of the CPU and wait on the thread's thread-semaphore. Prototype: void Aplmt_waitThread(void); */ #define Aplmt_waitThread _Aplmt_waitThread /** This method is the same as Aplmt_waitThread(), except the method will timeout and/or return after the specified time interval (in milliseconds), if the thread was not signaled. The method normally returns non-zero (true). It only returns 0 (false) if the thread 'waited' on the thread-semaphore and the timeout period expired before the thread was signaled. NOTES: o If APLMT_WAIT_NO_TIMEOUT is specified as the timeout period, the method behaves exactly the same as Aplmt_waitThread(), i.e. nevers times-out. o The longest timeout period is APLMT_WAIT_MAX_TIMEOUT. o If 0 is specified as the timout period, then the call acts as a 'polled' operation on the thread-semaphore in that it will never block even if the thread-semaphore is not currently signaled when called. o CAUTION: Do not assume that since the method returned false due to a time-out, that the thread-semaphore is not signaled (i.e. its count is zero). It is possible that the thread is/was signaled after the 'time-out', BUT before the application has an opportunity to check the return code. o This method is consider OPTIONAL, i.e. the underlaying platform is NOT REQUIRED to support this method. CHECK YOUR Platform's documentation before using this method. Prototype: AplBool Aplmt_waitThreadTimeout( AplSize_t maxWaitInMilliseconds ) */ #define Aplmt_waitThreadTimeout _Aplmt_waitThreadTimeout /** This method signals the specified thread's thread-semaphore and causes thread to become unblocked and/or ready to run. Prototype: void Aplmt_signalThread( AplmtThreadHdl threadToSignal ); */ #define Aplmt_signalThread _Aplmt_signalThread /** This method is same as Aplmt_signalThread(), except that it can ONLY be called from the context of an interrupt service routine. Prototype: void Aplmt_isr_signalThread( AplmtThreadHdl threadToSignal ); */ #define Aplmt_isr_signalThread _Aplmt_isr_signalThread /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method returns the handle of the currently running thread. Prototype: AplmtThreadHdl Aplmt_getCurrentThread(void); */ #define Aplmt_getCurrentThread _Aplmt_getCurrentThread /** This method returns the thread's priority, and thread name of the specified thread. The method will return false if the specified thread does not exists. NOTES: o The caller must supply the memory for storing the returned thread priority and thread name. Prototype: AplBool Aplmt_getThreadInfo( AplmtThreadHdl thread, AplmtThreadPriority* threadPriority, char* nameBuffer, AplSize_t nameBufferSize ); */ #define Aplmt_getThreadInfo _Aplmt_getThreadInfo /** This method provide a mechanism for walking the platform's list of currently create threads. The specified callback function is called once for every created thread. The callback routine can prematurely terminate the traversal by returning false, else true to continue the traversal. During the callback, the application may call the Aplmt_getThreadInfo() methods to get more details about each thread. The function signature of the callback is: AplBool myCallback( AplmtThreadHdl nextThreadHandle ); NOTES: o Thread scheduling may be temporarily suspended until the traversal is completed. So be careful/prudent on how much time you spend in the callback routine. o There is NO guaranteed order to the traversal - only that all created threads will be reported. o DO NOT, repeat DO NOT, create or delete any threads directly or indirectly from the callback routine. o The IDLE and SYSTEM threads may or may not be reported. This is platform dependent. Prototype: void Aplmt_walkThreadList( AplmtCBFuncThreadList callbackFunc ); */ #define Aplmt_walkThreadList _Aplmt_walkThreadList #ifdef __cplusplus } #endif /*--------------------------------------------------------------------------*/ #endif /* end _aplmt_kernelapi_h_ */