#ifndef _aplmt_itc_imboxapi_h_ #define _aplmt_itc_imboxapi_h_ /*---------------------------------------------------------------------------- ** SUMMARY: Inter-Thread Communications Mailbox Interfaces (IMBOX) ** ** DESCRIPTION: ** This file provides the interface for delivering ITC messages. The following ** descriptions assumes that the reader is familiar with general concepts of ** inter-thread-communications. ** ** TERMS: ** ------ ** Client - The orginator (i.e. source) of an ITC transaction. ** Server - The recipient (i.e. destination) of an ITC transaction. ** Transaction - An ITC transaction starts with a client posting a message ** and ends the delivery of the message to a server. ** Request - The client posts a message to a server. At this point the ** client gives up ownership of the message and should not ** access the message until it receives the server's response. ** Response - The server provides an 'acknowlegement' to the client that ** originated the message request, that the server has received ** and/or relinquished ownership of the client's message. ** request. ** Post - The process of inserting a message into an ITC mailbox. ** Delivery - The process of extracting a message from an ITC mailbox. ** Asynchronous - The client does not wait/block for the server to complete ** its processing. ** Synchronous - The client waits/block until the server has generated its ** response. ** ** ** MODELS: ** ------- ** The APL IMSG/IMBOX interfaces supports four 'models' of ITC. The ** different models allows the application to select/use what functionality ** it needs, while minimizing the RAM/ROM footprint of the ITC engine. The ** four models are (listed in order of the smallest footprint): ** XSMALL - Request messages only. The client has to poll for the ** server's response. ** SMALL - Request and Response messages. ** NORMAL - Same as 'SMALL' with the added ability for the client to ** post messages synchronously. ** LARGE - Same as 'NORMAL' except the application is responsible ** for allocating the mailboxes and messages. ** ** ** MESSAGES: ** --------- ** Messages are unique and there is NO support for 'broadcasting' messages. ** What this means, is that once a client has claimed ownership of a message ** it can not be used by another client until the original client has ** released ownership (i.e. after recieving the server's response). In ** addition, for models XS, S, and N ALL messages and message data fields ** are statically allocated. The application can control how many messages ** are allocated and how many messages contain data at compile time. ** ** ** MESSAGE DATA: ** ------------- ** All request messages can be data-less or have data associated with them. ** The application determines the mix of data-less vs. data messages. Repsonse ** message are a little different. Repsonse message can ONLY have data ** associated with them if their corresponding request message has a data ** field. This restriction is because the request/response message pairs ** SHARE the same data field. If the server needs to return data to the ** client, the client's original request message MUST have a data field. ** ** ** MAILBOXES: ** ---------- ** A mailbox is basically a FIFO queue that is used as the storage and ** delivery mechanism for ITC messages. Mailboxes are logically bound to ** threads. Mailboxes are automatically bound to the thread of the caller ** of Aplmt_imboxGetNextMessage(). Technically, the 'binding' last on for ** during of call, so it is possible to change the 'binding' of mailbox ** on every call to Aplmt_imboxGetNextMessage(). HOWEVER, it is strongly ** recommended that the application binds a given mailbox to one and only ** thread. ** ** Mailboxes do NOT have limit on how many messages they can store and/or ** queue. Additionally, for models XS, S, and N all mailboxes are statically ** allocated. The application can control how many mailboxes are allocated ** at compile time. ** ** Mailboxes have an additional feature in that they can be 'signaled'. This ** feature allows mailboxs to receive messages AND support the thread- ** semaphore semantics at the same time. ** ** ** TIMEOUTS: ** --------- ** The default implementation of the mailbox method: Aplmt_imboxGetNextMessage() ** waits indefinitely until until a message arrives. There is an OPTIONAL ** (read as not supported by all platforms) compile switch that enables ** an additional get-next-message method: Aplmt_imboxGetNextMessageTimeout(), ** that takes a timeout parameter. ** ** ** THREAD-SEMAPHORE ** ---------------- ** The ITC engine use the OS layer's thread-semaphore as its synchronization ** primitive. The ITC engine use the thread-semaphore intelligently, in that ** application can still use the thread-semaphore for 'synchronous' operations. ** In fact, this is exactly how the ITC engine implements synchronous ITC ** calls. ** RULE: Do NOT asynchronous signal a thread's thread-semaphore when the ** thread 'has' a mailbox. ** NOTE: Mailboxes have a 'signalling' interface, so the application can (in ** most cases) substitute signalling the thread's mailbox in place of ** signalling the thread's thead-semaphore. ** ** ** LIMITS: ** ------- ** When using the LARGE model, the number of messages and mailboxes ** are only limited by the amount of available RAM. The message ID field ** for the LARGE model is of type Apl16u. The following are the limits ** for messages and mailboxes when using models: XSMALL, SMALL, and NORMAL ** ** Item Data Type Data Type Size Limit ** ------------------- --------- -------------- ----- ** Maximum messages** AplmtImsgHdl Apl8u (default) 254 ** Apl16u 65533 ** Maximum mailboxes AplmtImboxHdl Apl8u (default) 254 ** Apl16u 65533 ** ** **Note: This the number of TOTAL messages. For models S,N: the ITC ** engine automagically creates RESPONSE messages, thus ** 'consuming' half the total possible range for message IDs. ** However, it is possible by using the config switches (see ** imsgapi.h) to fine tune/limit how many 'message slots' get ** allocated for response messages. The default setting is to ** allocate a RESPONSE message for every 'message'. ** ** ** LARGE MODEL: ** ------------ ** The major change for the LARGE model is that the mailbox and message ** handles are pointers to structs, instead of indexes into statically ** allocated arrays. This has the following benefits/side effects: ** o The application is responsible for allocating the memory for all ** mailbox instances. It is also responsible for initialize each ** individual mailbox. ** o Each client is responsible for allocating and identifying its ** own message(s). ** o A given message is both a request and response message. It is ** the message's ID field that indicates/marks it as a request or ** response. In addition, the client is required to initialize and set ** the message's ID field EACH time (and before) it post a message. ** o A message instance can have a different message ID each time ** the client posts it. ** o Messages are compatible with the ILNODE inteface so that the ** application can use the Single-Linked List interface for managing ** messages (see the apl/containers directory for details about the list * interfaces). ** o The range of message IDs is 0 to 0x7FFE. However, message IDs ** are only required to be unique by their respective destination ** servers. For example: If the messages sent to Server-A are never ** sent to Server-B and vis-versus, then the message IDs for the two ** sets of messages IDs can overlap. ** o None the IMSG application options, OPTION_APLMT_IMSG_xxxx, have ** any meaning and/or effect. ** o None the IMBOX application options, OPTION_APLMT_IMBOX_xxxx, have ** any meaning and/or effect. ** o The application can not/does not override the types: AplmtImboxHdl and ** AplmtImsgHdl. The application can still define/override the AplmtImsgData ** type. ** o There is no error checking regardless of the compile switch. ** o RAM Usage: The size of a LARGE model message is noticeably bigger than ** the other models. However, when you factor in how client's manage ** message memory in the LARGE model, the overall RAM usage can be smaller ** than when using the other models. This is due to the fact that most ** clients send many different messages, but typically only have one or two ** messages outstanding at any one time. Since in the LARGE model, ** messages can be 'reused', a client only needs to allocate memory for ** maximum number of message(s) it can have outstanding at any one time. ** ** ** FOOTPRINT: ** ---------- ** For determining the RAM usage of a mailbox, the following C struct is ** functionally equilivant to the actual implementation. ** struct IMailbox ** { ** AplmtThreadHdl _myThread; ** AplmtImsgHdl _msgListHeadPointer; ** AplmtImsgHdl _msgListTailPointer; ** AplByte _flags; ** }; ** ** For determining the RAM usage of a message, the following C struct is ** functionally equilivant to the actual implementation. ** struct IMessage ** { ** AplmtImsgHdl _listPointer; // Used by the mailboxes to implement their FIFO queues ** AplmtImsgData _payload; // ONLY applies to messages that 'HAVE' data and/or LARGE model ** AplmtImboxHdl _responseMbox; // ONLY applies if using models: SMALL, NORMAL, LARGE ** AplmtThreadHdl _syncClientThread; // ONLY applies if using models: NORMAL, LARGE ** AplmtImsgId _messageID; // ONLY applies if using models: LARGE ** }; ** ** ** ERROR CHECKING: ** --------------- ** The default configuration has no error checking and/or validation of of ** message and mailbox handles/identifiers. When error checking is enable, all ** function calls attempt to valid their respective input data. If an ** error and/or invalid value is detected a FATAL ERROR will be generated. To ** enable error checking use the switch USE_APLMT_ITC_INCLUDE_ERROR_CHECKING. ** ** ** CONFIGURATION ** ------------- ** COMPILE: USE_APLMT_ITC_MODEL_XSMALL ** USE_APLMT_ITC_MODEL_SMALL ** USE_APLMT_ITC_MODEL_NORMAL ** USE_APLMT_ITC_MODEL_LARGE ** USE_APLMT_ITC_INCLUDE_ERROR_CHECKING ** USE_APLMT_IMBOX_WITH_TIMEOUT ** USE_APLMT_INIT_IMBOX_IN_SYSTEM_INIT ** ** APPLICATION: The application can override the following types/defintions ** AplmtImboxHdl ** OPTION_APLMT_IMBOX_MAX_MAILBOXES ** ** PLATFORM: none. ** ** ** 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 "aplcfg.h" /* For: Application configuration */ #include "apl/types/types.h" /* For: basic types */ #ifdef __cplusplus extern "C" { #endif /*-------------- ERRORS ----------------------------------------------------*/ /** An invalid mailbox handle was specified when calling an Aplmt_imboxXXX() method. Note: Error Checking must be enable for this error to occur. */ #define APLMT_ERRSTR_IMBOX_INVALID_HANDLE "IMBOX: A invalid mailbox handle was used when making a all to an IMBOX method." /***/ #define APLMT_ERR_IMBOX_INVALID_HANDLE _APLMT_ERR_IMBOX_INVALID_HANDLE /*-------------- CONSTANTS -------------------------------------------------*/ /** Number of mailboxes (default value) */ #ifndef OPTION_APLMT_IMBOX_MAX_MAILBOXES #define OPTION_APLMT_IMBOX_MAX_MAILBOXES 8 #endif /** NULL Mailbox Handle. */ #define APLMT_NULL_IMBOX_HANDLE _APLMT_NULL_IMBOX_HANDLE /** Return code for Aplmt_imboxGetNextMessageTimeout() that indicates the call timed-out before a message/signal was received. */ #define APLMT_IMBOX_GETNEXT_TIMEOUT _APLMT_IMBOX_GETNEXT_TIMEOUT /*-------------- TYPES -----------------------------------------------------*/ /** Mailbox Handle. For the models: XS, S, N, the default limits the maximum number of mailboxes to 254 */ #ifndef AplmtImboxHdl #define AplmtImboxHdl _AplmtImboxHdl #endif /*-------------- INLINE IMPLEMENTATION -------------------------------------*/ #include "aplmt/itc/iprivate.h" /* For: inline implementation */ /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method is used to initalize the mailbox sub-system. It must be called BEFORE any other Aplmt_imsgXXX() and Aplmt_imboxXXX() methods (except for Aplmt_imsgInitialize()). NOTES: o If USE_APLMT_INIT_IMBOX_IN_SYSTEM_INIT is defined, then APL will internally call this method as part of the Aplmt_systemInit() o This method has no meaning if the application is using the LARGE model (i.e. do not need to call, but if called does nothing). Prototype: void Aplmt_imboxInitialize(void) */ #define Aplmt_imboxInitialize _Aplmt_imboxInitialize /** This method is used to initalize a ITC mailbox. This method must called before the mailbox is first used. This method should only be called once per mailbox. NOTES: o The application is required allocate/create the mailbox. Use the data type: AplmtImbox to allocate a concrete mailbox instance. o Data types: AplmtImbox* == AplmtImboxHdl. The application must provide an actual INSTANCE, not just a pointer, to the mailbox being initialized.: o This method is ONLY valid/available when using the LARGE model. Prototype: void Aplmt_imboxInit( AplmtImbox* mboxToInit ) */ #define Aplmt_imboxInit _Aplmt_imboxInit /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method is used by clients to send/post an ITC message to a server. The server is identified by the destination mailbox. It is acceptable for the client and server to share the same thread (i.e. post a message to 'myself'). Prototype: void Aplmt_imboxPost( AplmtImboxHdl destMbox, AplmtImsgHdl msg ); */ #define Aplmt_imboxPost _Aplmt_imboxPost /** This method is the same as Aplmt_imboxPost(), except that it can be called from an interrupt service routine. NOTE: The interrupt service routine is REQUIRED to ensure that the message is NOT-IN-USE when calling this mesage. Prototype: void Aplmt_isr_imboxPost( AplmtImboxHdl destMbox, AplmtImsgHdl msg ); */ #define Aplmt_isr_imboxPost _Aplmt_isr_imboxPost /** This method is used to signal the specified mailbox. Signalling a mailbox has the same semantics as the mailbox waiting on its thread's thread-semaphore and the client signalling the waiting thread's thread-semaphore. Prototype: void Aplmt_imboxSignal( AplmtImboxHdl destMbox ); */ #define Aplmt_imboxSignal _Aplmt_imboxSignal /** This method is the same as Aplmt_imboxSignal(), except that it can be called from an interrupt service routine. Prototype: void Aplmt_isr_imboxSignal( AplmtImboxHdl destMbox ); */ #define Aplmt_isr_imboxSignal _Aplmt_isr_imboxSignal /** This method is used by a server to retrieve posted ITC messages. This is a blocking call in that if no messages are currently available then the calling thread blocks until a new message is received. It is acceptable for the client and server to share the thread (i.e. post a message to 'myself'). The method returns the handle to the next/currently received message. If the mailbox was signaled, then the method returns APLMT_NULL_IMSG_HANDLE. Note: The 'signaled' condition takes precedence over queued messages (i.e. the 'signal' state is not queued/sync'd with the received message, but is 'delivered' immediately). The following psuedo code demostrates how a 'server thread' should use this method: void threadEntryFunction( void* args ) { .... for(;;) { AplmtImsgHdl msg = Aplmt_imboxGetNextMessage( myMailbox ) switch ( Aplmt_imsgGetId(msg) ) { case APLMT_IMSG_SIGNAL_RECEIVED: do_mailbox_was_signaled(); break; case MSG_1: do_msg1_was_received(); break; ... case MSG_N: do_msgN_was_received(); break; } } } Prototype: AplmtImsgHdl Aplmt_imboxGetNextMessage( AplmtImboxHdl mbox ); */ #define Aplmt_imboxGetNextMessage _Aplmt_imboxGetNextMessage /** This method is the same as Aplmt_imboxGetNextMessage(), except the method will timeout and/or return after the specified time interval (in milliseconds) if a message was not received. Also, there is an additional return code, APLMT_IMBOX_GETNEXT_TIMEOUT, that is returned to indicate that the call timed-out (i.e. was not signaled and no message receivied). BY DEFAULT THIS METHOD IS DISABLED. It must be enabled by the application using the compile switch: USE_APLMT_IMBOX_WITH_TIMEOUT. NOTES: o If APLMT_WAIT_NO_TIMEOUT is specified as the timeout period, the method behaves exactly the same as Aplmt_imboxGetNextMessage(), i.e. nevers times-out. See aplmt/os/kernelapi.h for details on APLMT_WAIT_NO_TIMEOUT. o The longest timeout period is APLMT_WAIT_MAX_TIMEOUT. Again see aplmt/os/kernelapi.h for details. o If 0 is specified as the timout period, then the call acts as a 'polled' operation on the mailbox in that it will never block even if the mailbox is currently empty when called. o CAUTION: The application must test the return code for APLMT_NULL_IMSG_HANDLE *and* APLMT_IMBOX_GETNEXT_TIMEOUT before calling Aplmt_imsgGetId() (since either one of these return codes will crash the system if passed to Aplmt_imsgGetId()). o CAUTION: This method is dependent on Aplmt_waitThreadTimeout() which is OPTIONAL. Check your platform's documentation before using this method. Prototype: AplmtImsgHdl Aplmt_imboxGetNextMessageTimeout( AplmtImboxHdl mbox, AplSize_t maxWaitInMilliseconds ) */ #define Aplmt_imboxGetNextMessageTimeout _Aplmt_imboxGetNextMessageTimeout /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method performs the same function as Aplmt_imboxPost(), except that the client will receive a response message/event when the destination server calls Aplmt_imsgReturnToSender() on the posted message. Message Identifiers: SERVER - The server receives the request message. The message ID is the message ID that was posted by the client. CLIENT - The client recieves the response message. The message ID is the message ID of original request message arithmetically added with APLMT_IMSG_RESPONSE_ID. The 'renaming' of the request message to the corresponding response message is done automagically and does NOT require any intervention from the application. Data/Payload: Request messages can have a data/payload field. Response messages never have a data/payload field. If the server needs to return data to the client, it puts/plants the data in the data/payload field of the request message. Receiveing a response message indicates that the client now has ownership of the original request message and can safely access the request message's data/payload field. Mailboxes. The client thread is REQUIRED to have a mailbox and have a message processing loop just a like server, since when the server generates the response message, the server is acting as ITC client, the client that originated the request message is now a server for the ITC response message. Arguments: requestMbox - Destination mailbox of the server msg - Message to post responseMbox - Source mailbox of the client issuing the request NOTE: This method only has meaning if the application selects the SMALL, NORMAL, or LARGE ITC models. Prototype: void Aplmt_imboxPostRequest( AplmtImboxHdl requestMbox, AplmtImsgHdl msg, AplmtImboxHdl responseMbox ); */ #define Aplmt_imboxPostRequest _Aplmt_imboxPostRequest /*-------------- PUBLIC/PUBLISHED API --------------------------------------*/ /** This method peforms the same function as Aplmt_imboxPost(), except that the client's thread will block until the destination server calls Aplmt_imsgReturnToSender() on the posted message. The client's thread is NOT required to have mailbox. However, the client's thread MUST be a different thread from that of the destination server. NOTES: o This method only has meaning if the application selects the NORMAL or LARGE ITC models. Prototype: void Aplmt_imboxPostSync( AplmtImboxHdl destMbox, AplmtImsgHdl msg ); */ #define Aplmt_imboxPostSync _Aplmt_imboxPostSync #ifdef __cplusplus } #endif /*--------------------------------------------------------------------------*/ #endif /* end _aplmt_itc_imboxapi_h_ */