123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- /*
- Copyright (c) 2012, Broadcom Europe Ltd
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of the copyright holder nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- /*=============================================================================
- VCOS - packet-like messages, based loosely on those found in TRIPOS.
-
- In the simple case, only the server thread creates a message queue, and
- clients wait for replies on a semaphore. In more complex cases, clients can
- also create message queues (not yet implemented).
-
- Although it's possible for a thread to create multiple queues and listen
- on them in turn, if you find yourself doing this it's probably a bug.
- =============================================================================*/
-
- #ifndef VCOS_MSGQUEUE_H
- #define VCOS_MSGQUEUE_H
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- #include "vcos_types.h"
- #include "pthreads/vcos_platform.h"
- #include "vcos_blockpool.h"
-
- /**
- * \file
- *
- * Packet-like messages, based loosely on those found in TRIPOS and
- * derivatives thereof.
- *
- * A task can send a message *pointer* to another task, where it is
- * queued on a linked list and the task woken up. The receiving task
- * consumes all of the messages on its input queue, and optionally
- * sends back replies using the original message memory.
- *
- * A caller can wait for the reply to a specific message - any other
- * messages that arrive in the meantime are queued separately.
- *
- *
- * All messages have a standard common layout, but the payload area can
- * be used freely to extend this.
- */
-
- #define VCOS_MSGQ_MAGIC 0x5147534d
-
- /** Map the payload portion of a message to a structure pointer.
- */
- #define VCOS_MSG_DATA(_msg) (void*)((_msg)->data)
-
- /** Standard message ids - FIXME - these need to be done properly! */
- #define VCOS_MSG_N_QUIT 1
- #define VCOS_MSG_N_OPEN 2
- #define VCOS_MSG_N_CLOSE 3
- #define VCOS_MSG_N_PRIVATE (1<<20)
-
- #define VCOS_MSG_REPLY_BIT (1<<31)
-
- /** Make gnuc compiler be happy about pointer punning */
- #ifdef __GNUC__
- #define __VCOS_MAY_ALIAS __attribute__((__may_alias__))
- #else
- #define __VCOS_MAY_ALIAS
- #endif
-
- struct VCOS_MSG_T;
-
- /* Replies go to one of these objects.
- */
- typedef struct VCOS_MSG_WAITER_T
- {
- /* When the reply is sent, this function gets called with the
- * address of the waiter.
- */
- void (*on_reply)(struct VCOS_MSG_WAITER_T *waiter,
- struct VCOS_MSG_T *msg);
- } VCOS_MSG_WAITER_T;
-
- /** A single message queue.
- */
- typedef struct VCOS_MSGQUEUE_T
- {
- VCOS_MSG_WAITER_T waiter; /**< So we can wait on a queue */
- struct VCOS_MSG_T *head; /**< head of linked list of messages waiting on this queue */
- struct VCOS_MSG_T *tail; /**< tail of message queue */
- VCOS_SEMAPHORE_T sem; /**< thread waits on this for new messages */
- VCOS_MUTEX_T lock; /**< locks the messages list */
- int attached; /**< Is this attached to a thread? */
- } VCOS_MSGQUEUE_T;
-
- /** A single message
- */
- typedef struct VCOS_MSG_T
- {
- uint32_t magic; /**< Sanity checking */
- uint32_t code; /**< message code */
- struct VCOS_MSG_T *next; /**< next in queue */
- VCOS_THREAD_T *src_thread; /**< for debug */
- struct VCOS_MSG_WAITER_T *waiter; /**< client waiter structure */
- struct VCOS_MSGQ_POOL_T *pool; /**< Pool allocated from, or NULL */
- } VCOS_MSG_T;
-
- #define MSG_REPLY_BIT (1<<31)
-
- /** Initialize a VCOS_MSG_T. Can also use vcos_msg_init().
- */
- #define VCOS_MSG_INITIALIZER {VCOS_MSGQ_MAGIC, 0, NULL, NULL, NULL, 0}
-
- /** A pool of messages. This contains its own waiter and
- * semaphore, as well as a blockpool for the actual memory
- * management.
- *
- * When messages are returned to the waiter, it posts the
- * semaphore.
- *
- * When waiting for a message, we just wait on the semaphore.
- * When allocating without waiting, we just try-wait on the
- * semaphore.
- *
- * If we managed to claim the semaphore, then by definition
- * there must be at least that many free messages in the
- * blockpool.
- */
- typedef struct VCOS_MSGQ_POOL_T
- {
- VCOS_MSG_WAITER_T waiter;
- VCOS_BLOCKPOOL_T blockpool;
- VCOS_SEMAPHORE_T sem;
- uint32_t magic;
- } VCOS_MSGQ_POOL_T;
-
- /** Initalise the library. Normally called from vcos_init().
- */
- VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_msgq_init(void);
-
- /** De-initialise the library. Normally called from vcos_deinit().
- */
- VCOSPRE_ void VCOSPOST_ vcos_msgq_deinit(void);
-
- /** Send a message.
- *
- * @param dest Destination message queue
- * @param code Message code.
- * @param msg Pointer to message to send. Must not go out of scope before
- * message is received (do not declare on the stack).
- */
- VCOSPRE_ void VCOSPOST_ vcos_msg_send(VCOS_MSGQUEUE_T *dest, uint32_t code, VCOS_MSG_T *msg);
-
- /** Send a message and wait for a reply.
- *
- * @param dest Destination message queue
- * @param code Message code.
- * @param msg Pointer to message to send. May be declared on the stack.
- */
- VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_msg_sendwait(VCOS_MSGQUEUE_T *queue, uint32_t code, VCOS_MSG_T *msg);
-
- /** Wait for a message on a queue.
- */
- VCOSPRE_ VCOS_MSG_T * VCOSPOST_ vcos_msg_wait(VCOS_MSGQUEUE_T *queue);
-
- /** Peek for a message on this thread's endpoint. If a message is not
- * available, NULL is returned. If a message is available it will be
- * removed from the endpoint and returned.
- */
- VCOSPRE_ VCOS_MSG_T * VCOSPOST_ vcos_msg_peek(VCOS_MSGQUEUE_T *queue);
-
- /** Send a reply to a message
- */
- VCOSPRE_ void VCOSPOST_ vcos_msg_reply(VCOS_MSG_T *msg);
-
- /** Set the reply queue for a message. When the message is replied-to, it
- * will return to the given queue.
- *
- * @param msg Message
- * @param queue Message queue the message should return to
- */
- VCOSPRE_ void VCOSPOST_ vcos_msg_set_source(VCOS_MSG_T *msg, VCOS_MSGQUEUE_T *queue);
-
- /** Initialise a newly allocated message. This only needs to be called
- * for messages allocated on the stack, heap or statically. It is not
- * needed for messages allocated from a pool.
- */
- VCOSPRE_ void VCOSPOST_ vcos_msg_init(VCOS_MSG_T *msg);
-
- /** Create a message queue to wait on.
- */
- VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_msgq_create(VCOS_MSGQUEUE_T *queue, const char *name);
-
- /** Destroy a queue
- */
- VCOSPRE_ void VCOSPOST_ vcos_msgq_delete(VCOS_MSGQUEUE_T *queue);
-
- /*
- * Message pools
- */
-
- /** Create a pool of messages. Messages can be allocated from the pool and
- * sent to a message queue. Replying to the message will automatically
- * free it back to the pool.
- *
- * The pool is threadsafe.
- *
- * @param count number of messages in the pool
- * @param payload_size maximum message payload size, not including MSG_T.
- */
- VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_msgq_pool_create(
- VCOS_MSGQ_POOL_T *pool,
- size_t count,
- size_t payload_size,
- const char *name);
-
- /** Destroy a message pool.
- */
- VCOSPRE_ void VCOSPOST_ vcos_msgq_pool_delete(VCOS_MSGQ_POOL_T *pool);
-
- /** Allocate a message from a message pool.
- *
- * Note:
- *
- * If the alloc fails (returns NULL) then your worker thread has stopped
- * servicing requests or your pool is too small for the latency in
- * the system. Your best bet to handle this is to fail the call that
- * needs to send the message.
- *
- * The returned message payload area is initialised to zero.
- *
- * @param pool Pool to allocate from.
- * @return Message or NULL if pool exhausted.
- */
- VCOSPRE_ VCOS_MSG_T *VCOSPOST_ vcos_msgq_pool_alloc(VCOS_MSGQ_POOL_T *pool);
-
- /** Wait for a message from a message pool. Waits until a
- * message is available in the pool and then allocates it. If
- * one is already available, returns immediately.
- *
- * This call can never fail.
- *
- * The returned message payload area is initialised to zero.
- *
- * @param pool Pool to allocate from.
- * @return Message
- */
- VCOSPRE_ VCOS_MSG_T *VCOSPOST_ vcos_msgq_pool_wait(VCOS_MSGQ_POOL_T *pool);
-
- /** Explicitly free a message and return it to its pool.
- *
- * @param msg Message to free. No-op if NULL.
- */
- VCOSPRE_ void VCOSPOST_ vcos_msgq_pool_free(VCOS_MSG_T *msg);
-
- #ifdef __cplusplus
- }
- #endif
- #endif
-
|