Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:12

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreMessageQueue
0007  *
0008  * @brief This header file provides interfaces of the
0009  *   @ref RTEMSScoreMessageQueue which are used by the implementation and the
0010  *   @ref RTEMSImplApplConfig.
0011  */
0012 
0013 /*
0014  *  COPYRIGHT (c) 1989-2009.
0015  *  On-Line Applications Research Corporation (OAR).
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifndef _RTEMS_SCORE_COREMSGIMPL_H
0040 #define _RTEMS_SCORE_COREMSGIMPL_H
0041 
0042 #include <rtems/score/coremsg.h>
0043 #include <rtems/score/status.h>
0044 #include <rtems/score/chainimpl.h>
0045 #include <rtems/score/threaddispatch.h>
0046 #include <rtems/score/threadqimpl.h>
0047 
0048 #include <limits.h>
0049 #include <string.h>
0050 
0051 #ifdef __cplusplus
0052 extern "C" {
0053 #endif
0054 
0055 /**
0056  * @addtogroup RTEMSScoreMessageQueue
0057  *
0058  * @{
0059  */
0060 
0061 /**
0062  *  @brief Used when appending messages onto a message queue.
0063  *
0064  *  This is the priority constant used when appending messages onto
0065  *  a message queue.
0066  */
0067 #define  CORE_MESSAGE_QUEUE_SEND_REQUEST   INT_MAX
0068 
0069 /**
0070  *  @brief Used when prepending messages onto a message queue.
0071  *
0072  *  This is the priority constant used when prepending messages onto
0073  *  a message queue.
0074  */
0075 #define  CORE_MESSAGE_QUEUE_URGENT_REQUEST INT_MIN
0076 
0077 /**
0078  *  @brief The modes in which a message may be submitted to a message queue.
0079  *
0080  *  The following type details the modes in which a message
0081  *  may be submitted to a message queue.  The message may be posted
0082  *  in a send or urgent fashion.
0083  *
0084  *  @note  All other values are message priorities.  Numerically smaller
0085  *         priorities indicate higher priority messages.
0086  */
0087 typedef int CORE_message_queue_Submit_types;
0088 
0089 /**
0090  * @brief This handler shall allocate the message buffer storage area for a
0091  *   message queue.
0092  *
0093  * The handler shall set the CORE_message_queue_Control::free_message_buffers
0094  * member.
0095  *
0096  * @param[out] the_message_queue is the message queue control.
0097  *
0098  * @param size is the message buffer storage area size to allocate.
0099  *
0100  * @param arg is the handler argument.
0101  *
0102  * @retval NULL The allocation failed.
0103  *
0104  * @return Otherwise the pointer to the allocated message buffer storage area
0105  *   begin shall be returned.
0106  */
0107 typedef void *( *CORE_message_queue_Allocate_buffers )(
0108   CORE_message_queue_Control *the_message_queue,
0109   size_t                      size,
0110   const void                 *arg
0111 );
0112 
0113 /**
0114  * @brief This handler allocates the message buffer storage area for a message
0115  *   queue from the RTEMS Workspace.
0116  *
0117  * The handler sets the CORE_message_queue_Control::free_message_buffers
0118  * to _Workspace_Free().
0119  *
0120  * @param[out] the_message_queue is the message queue control.
0121  *
0122  * @param size is the message buffer storage area size to allocate.
0123  *
0124  * @param arg is the unused handler argument.
0125  *
0126  * @retval NULL The allocation failed.
0127  *
0128  * @return Otherwise the pointer to the allocated message buffer storage area
0129  *   begin is returned.
0130  */
0131 void *_CORE_message_queue_Workspace_allocate(
0132   CORE_message_queue_Control *the_message_queue,
0133   size_t                      size,
0134   const void                 *arg
0135 );
0136 
0137 /**
0138  * @brief Initializes a message queue.
0139  *
0140  * @param[out] the_message_queue is the message queue to initialize.
0141  *
0142  * @param discipline is the blocking discipline for the message queue.
0143  *
0144  * @param maximum_pending_messages is the maximum number of messages that will
0145  *   be allowed to be pending at any given time.
0146  *
0147  * @param maximum_message_size is the size of the largest message that may be
0148  *   sent to this message queue instance.
0149  *
0150  * @param allocate_buffers is the message buffer storage area allocation
0151  *   handler.
0152  *
0153  * @param arg is the message buffer storage area allocation handler argument.
0154  *
0155  * @retval STATUS_SUCCESSFUL The message queue was initialized.
0156  *
0157  * @retval STATUS_MESSAGE_QUEUE_INVALID_SIZE Calculations with the maximum
0158  *   pending messages or maximum message size produced an integer overflow.
0159  *
0160  * @retval STATUS_MESSAGE_QUEUE_NO_MEMORY The message buffer storage area
0161  *   allocation failed.
0162  */
0163 Status_Control _CORE_message_queue_Initialize(
0164   CORE_message_queue_Control          *the_message_queue,
0165   CORE_message_queue_Disciplines       discipline,
0166   uint32_t                             maximum_pending_messages,
0167   size_t                               maximum_message_size,
0168   CORE_message_queue_Allocate_buffers  allocate_buffers,
0169   const void                          *arg
0170 );
0171 
0172 /**
0173  * @brief Closes a message queue.
0174  *
0175  * This package is the implementation of the CORE Message Queue Handler.
0176  * This core object provides task synchronization and communication functions
0177  * via messages passed to queue objects.
0178  *
0179  * This function closes a message by returning all allocated space and
0180  * flushing @a the_message_queue's task wait queue.
0181  *
0182  * @param[in, out] the_message_queue The message queue to close.
0183  * @param[in, out] queue_context The thread queue context used for
0184  *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
0185  */
0186 void _CORE_message_queue_Close(
0187   CORE_message_queue_Control *the_message_queue,
0188   Thread_queue_Context       *queue_context
0189 );
0190 
0191 /**
0192  * @brief Flushes pending messages.
0193  *
0194  * This package is the implementation of the CORE Message Queue Handler.
0195  * This core object provides task synchronization and communication functions
0196  * via messages passed to queue objects.
0197  *
0198  * This function flushes @a the_message_queue's pending message queue.  The
0199  * number of messages flushed from the queue is returned.
0200  *
0201  * @param[in, out] the_message_queue The message queue to flush.
0202  * @param queue_context The thread queue context with interrupts disabled.
0203  *
0204  * @return This method returns the number of message pending messages flushed.
0205  */
0206 uint32_t   _CORE_message_queue_Flush(
0207   CORE_message_queue_Control *the_message_queue,
0208   Thread_queue_Context       *queue_context
0209 );
0210 
0211 #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
0212 /**
0213  * @brief Flushes waiting threads.
0214  *
0215  * This function flushes the threads which are blocked on
0216  * @a the_message_queue's pending message queue.  They are
0217  * unblocked whether blocked sending or receiving. It returns
0218  * the number of messages flushed from the queue.
0219  *
0220  * @param[in, out] the_message_queue The message queue to flush.
0221  *
0222  * @return This method returns the number of messages flushed from the queue.
0223  */
0224   void _CORE_message_queue_Flush_waiting_threads(
0225     CORE_message_queue_Control *the_message_queue
0226   );
0227 #endif
0228 
0229 /**
0230  * @brief Broadcasts a message to the message queue.
0231  *
0232  * This package is the implementation of the CORE Message Queue Handler.
0233  * This core object provides task synchronization and communication functions
0234  * via messages passed to queue objects.
0235  *
0236  * This function sends a message for every thread waiting on the queue and
0237  * returns the number of threads made ready by the message.
0238  *
0239  * @param[in, out] the_message_queue The message queue to operate upon.
0240  * @param buffer The starting address of the message to broadcast.
0241  * @param size The size of the message being broadcast.
0242  * @param[out] count The variable that will contain the
0243  *        number of tasks that are sent this message.
0244  * @param queue_context The thread queue context used for
0245  *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
0246  *
0247  * @retval STATUS_SUCCESSFUL The message was successfully broadcast.
0248  * @retval STATUS_MESSAGE_INVALID_SIZE The message size was too big.
0249  */
0250 Status_Control _CORE_message_queue_Broadcast(
0251   CORE_message_queue_Control *the_message_queue,
0252   const void                 *buffer,
0253   size_t                      size,
0254   uint32_t                   *count,
0255   Thread_queue_Context       *queue_context
0256 );
0257 
0258 /**
0259  * @brief Submits a message to the message queue.
0260  *
0261  * This routine implements the send and urgent message functions. It
0262  * processes a message that is to be submitted to the designated
0263  * message queue.  The message will either be processed as a
0264  * send message which it will be inserted at the rear of the queue
0265  * or it will be processed as an urgent message which will be inserted
0266  * at the front of the queue.
0267  *
0268  * @param[in, out] the_message_queue The message queue to operate upon.
0269  * @param executing The executing thread.
0270  * @param buffer The starting address of the message to send.
0271  * @param size The size of the message being send.
0272  * @param submit_type Determines whether the message is prepended,
0273  *        appended, or enqueued in priority order.
0274  * @param wait Indicates whether the calling thread is willing to block
0275  *        if the message queue is full.
0276  * @param queue_context The thread queue context used for
0277  *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
0278  *
0279  * @retval STATUS_SUCCESSFUL The message was successfully submitted to the message queue.
0280  * @retval STATUS_MESSAGE_INVALID_SIZE The message size was too big.
0281  * @retval STATUS_TOO_MANY No message buffers were available.
0282  * @retval STATUS_MESSAGE_QUEUE_WAIT_IN_ISR The caller is in an ISR, do not block!
0283  * @retval STATUS_TIMEOUT A timeout occurred.
0284  */
0285 Status_Control _CORE_message_queue_Submit(
0286   CORE_message_queue_Control       *the_message_queue,
0287   Thread_Control                   *executing,
0288   const void                       *buffer,
0289   size_t                            size,
0290   CORE_message_queue_Submit_types   submit_type,
0291   bool                              wait,
0292   Thread_queue_Context             *queue_context
0293 );
0294 
0295 /**
0296  * @brief Seizes a message from the message queue.
0297  *
0298  * This package is the implementation of the CORE Message Queue Handler.
0299  * This core object provides task synchronization and communication functions
0300  * via messages passed to queue objects.
0301  *
0302  * This kernel routine dequeues a message, copies the message buffer to
0303  * a given destination buffer, and frees the message buffer to the
0304  * inactive message pool.  The thread will be blocked if wait is true,
0305  * otherwise an error will be given to the thread if no messages are available.
0306  *
0307  * @param[in, out] the_message_queue The message queue to seize a message from.
0308  * @param executing The executing thread.
0309  * @param[out] buffer The starting address of the message buffer to
0310  *        to be filled in with a message.
0311  * @param[out] size_p The size of the @a buffer,
0312  *        indicates the maximum size message that the caller can receive.
0313  * @param wait Indicates whether the calling thread is willing to block
0314  *        if the message queue is empty.
0315  * @param queue_context The thread queue context used for
0316  *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
0317  *
0318  * @retval STATUS_SUCCESSFUL The message was successfully seized from the message queue.
0319  * @retval STATUS_UNSATISFIED Wait was set to false and there is currently no pending message.
0320  * @retval STATUS_TIMEOUT A timeout occurred.
0321  *
0322  * @note Returns message priority via return area in TCB.
0323  *
0324  * - INTERRUPT LATENCY:
0325  *   + available
0326  *   + wait
0327  */
0328 Status_Control _CORE_message_queue_Seize(
0329   CORE_message_queue_Control *the_message_queue,
0330   Thread_Control             *executing,
0331   void                       *buffer,
0332   size_t                     *size_p,
0333   bool                        wait,
0334   Thread_queue_Context       *queue_context
0335 );
0336 
0337 /**
0338  * @brief Inserts a message into the message queue.
0339  *
0340  * Copies the specified content into the message storage space and then
0341  * inserts the message into the message queue according to the submit type.
0342  *
0343  * @param[in, out] the_message_queue The message queue to insert a message in.
0344  * @param[in, out] the_message The message to insert in the message queue.
0345  * @param content_source The message content source.
0346  * @param content_size The message content size in bytes.
0347  * @param submit_type Determines whether the message is prepended,
0348  *        appended, or enqueued in priority order.
0349  */
0350 void _CORE_message_queue_Insert_message(
0351   CORE_message_queue_Control        *the_message_queue,
0352   CORE_message_queue_Buffer         *the_message,
0353   const void                        *content_source,
0354   size_t                             content_size,
0355   CORE_message_queue_Submit_types    submit_type
0356 );
0357 
0358 /**
0359  * @brief Sends a message to the message queue.
0360  *
0361  * @param[in, out] the_message_queue The message queue to send a message to.
0362  * @param buffer The starting address of the message to send.
0363  * @param sizeis The size of the message being send.
0364  * @param wait Indicates whether the calling thread is willing to block
0365  *        if the message queue is full.
0366  * @param queue_context The thread queue context used for
0367  *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
0368  *
0369  * @retval STATUS_SUCCESSFUL The message was successfully submitted to the message queue.
0370  * @retval STATUS_MESSAGE_INVALID_SIZE The message size was too big.
0371  * @retval STATUS_TOO_MANY No message buffers were available.
0372  * @retval STATUS_MESSAGE_QUEUE_WAIT_IN_ISR The caller is in an ISR, do not block!
0373  * @retval STATUS_TIMEOUT A timeout occurred.
0374  */
0375 static inline Status_Control _CORE_message_queue_Send(
0376   CORE_message_queue_Control       *the_message_queue,
0377   const void                       *buffer,
0378   size_t                            size,
0379   bool                              wait,
0380   Thread_queue_Context             *queue_context
0381 )
0382 {
0383   return _CORE_message_queue_Submit(
0384     the_message_queue,
0385     _Thread_Executing,
0386     buffer,
0387     size,
0388     CORE_MESSAGE_QUEUE_SEND_REQUEST,
0389     wait,
0390     queue_context
0391   );
0392 }
0393 
0394 /**
0395  * @brief Sends an urgent message to the message queue.
0396  *
0397  * @param[in, out] the_message_queue The message queue to send an urgent message to.
0398  * @param buffer The starting address of the message to send.
0399  * @param sizeis The size of the message being send.
0400  * @param wait Indicates whether the calling thread is willing to block
0401  *        if the message queue is full.
0402  * @param queue_context The thread queue context used for
0403  *   _CORE_message_queue_Acquire() or _CORE_message_queue_Acquire_critical().
0404  *
0405  * @retval STATUS_SUCCESSFUL The message was successfully submitted to the message queue.
0406  * @retval STATUS_MESSAGE_INVALID_SIZE The message size was too big.
0407  * @retval STATUS_TOO_MANY No message buffers were available.
0408  * @retval STATUS_MESSAGE_QUEUE_WAIT_IN_ISR The caller is in an ISR, do not block!
0409  * @retval STATUS_TIMEOUT A timeout occurred.
0410  */
0411 static inline Status_Control _CORE_message_queue_Urgent(
0412   CORE_message_queue_Control       *the_message_queue,
0413   const void                       *buffer,
0414   size_t                            size,
0415   bool                              wait,
0416   Thread_queue_Context             *queue_context
0417 )
0418 {
0419   return _CORE_message_queue_Submit(
0420     the_message_queue,
0421     _Thread_Executing,
0422     buffer,
0423     size,
0424     CORE_MESSAGE_QUEUE_URGENT_REQUEST,
0425     wait,
0426     queue_context
0427   );
0428 }
0429 
0430 /**
0431  * @brief Acquires the message queue.
0432  *
0433  * @param[in, out] the_message_queue The message queue to acquire.
0434  * @param queue_context The thread queue context.
0435  */
0436 static inline void _CORE_message_queue_Acquire(
0437   CORE_message_queue_Control *the_message_queue,
0438   Thread_queue_Context       *queue_context
0439 )
0440 {
0441   _Thread_queue_Acquire( &the_message_queue->Wait_queue, queue_context );
0442 }
0443 
0444 /**
0445  * @brief Acquires the message queue critical.
0446  *
0447  * @param[in, out] the_message_queue The message queue to acquire critical.
0448  * @param queue_context The thread queue context.
0449  */
0450 static inline void _CORE_message_queue_Acquire_critical(
0451   CORE_message_queue_Control *the_message_queue,
0452   Thread_queue_Context       *queue_context
0453 )
0454 {
0455   _Thread_queue_Acquire_critical( &the_message_queue->Wait_queue, queue_context );
0456 }
0457 
0458 /**
0459  * @brief Releases the message queue.
0460  *
0461  * @param[in, out] the_message_queue The message queue to release.
0462  * @param queue_context The thread queue context.
0463  */
0464 static inline void _CORE_message_queue_Release(
0465   CORE_message_queue_Control *the_message_queue,
0466   Thread_queue_Context       *queue_context
0467 )
0468 {
0469   _Thread_queue_Release( &the_message_queue->Wait_queue, queue_context );
0470 }
0471 
0472 /**
0473  * @brief Copies the source message buffer to the destination message buffer.
0474  *
0475  * This routine copies the contents of the source message buffer
0476  * to the destination message buffer.
0477  *
0478  * @param source The source message buffer to be copied.
0479  * @param[out] destination The destination messag buffer to copy the source to.
0480  * @param size The size of the source buffer.
0481  */
0482 static inline void _CORE_message_queue_Copy_buffer (
0483   const void *source,
0484   void       *destination,
0485   size_t      size
0486 )
0487 {
0488   memcpy(destination, source, size);
0489 }
0490 
0491 /**
0492  * @brief Allocates a message buffer from the inactive message buffer chain.
0493  *
0494  * This function allocates a message buffer from the inactive
0495  * message buffer chain.
0496  *
0497  * @param the_message_queue The message queue to operate upon.
0498  *
0499  * @retval pointer The allocated message buffer.
0500  * @retval NULL The inactive message buffer chain is empty.
0501  */
0502 static inline CORE_message_queue_Buffer *
0503 _CORE_message_queue_Allocate_message_buffer (
0504     CORE_message_queue_Control *the_message_queue
0505 )
0506 {
0507    return (CORE_message_queue_Buffer *)
0508      _Chain_Get_unprotected( &the_message_queue->Inactive_messages );
0509 }
0510 
0511 /**
0512  * @brief Frees a message buffer to inactive message buffer chain.
0513  *
0514  * This routine frees a message buffer to the inactive
0515  * message buffer chain.
0516  *
0517  * @param[in, out] the_message_queue The message queue to free the message buffer to.
0518  * @param[out] the_message The message to be freed.
0519  */
0520 static inline void _CORE_message_queue_Free_message_buffer (
0521   CORE_message_queue_Control *the_message_queue,
0522   CORE_message_queue_Buffer  *the_message
0523 )
0524 {
0525   _Chain_Append_unprotected( &the_message_queue->Inactive_messages, &the_message->Node );
0526 }
0527 
0528 /**
0529  * @brief Gets message priority.
0530  *
0531  * This function returns the priority of @a the_message.
0532  *
0533  * @param the_message The message to obtain the priority from.
0534  *
0535  * @retval priority The priority of this message.
0536  * @retval 0 Message priority is disabled.
0537  *
0538  * @note It encapsulates the optional behavior that message priority is
0539  *       disabled if no API requires it.
0540  */
0541 static inline int _CORE_message_queue_Get_message_priority (
0542   const CORE_message_queue_Buffer *the_message
0543 )
0544 {
0545   #if defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
0546     return the_message->priority;
0547   #else
0548     return 0;
0549   #endif
0550 }
0551 
0552 /**
0553  * @brief Gets first message of message queue and removes it.
0554  *
0555  * This function removes the first message from the_message_queue
0556  * and returns a pointer to it.
0557  *
0558  * @param[in, out] the_message_queue The message queue to get the first message from.
0559  *
0560  * @retval pointer The first message if the message queue is not empty.
0561  * @retval NULL The message queue is empty.
0562  */
0563 static inline
0564   CORE_message_queue_Buffer *_CORE_message_queue_Get_pending_message (
0565   CORE_message_queue_Control *the_message_queue
0566 )
0567 {
0568   return (CORE_message_queue_Buffer *)
0569     _Chain_Get_unprotected( &the_message_queue->Pending_messages );
0570 }
0571 
0572 #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
0573   /**
0574    * @brief Checks if notification is enabled.
0575    *
0576    * This function returns true if notification is enabled on this message
0577    * queue and false otherwise.
0578    *
0579    * @param the_message_queue The message queue to check if the notification is enabled.
0580    *
0581    * @retval true Notification is enabled on this message queue.
0582    * @retval false Notification is not enabled on this message queue.
0583    */
0584   static inline bool _CORE_message_queue_Is_notify_enabled (
0585     CORE_message_queue_Control *the_message_queue
0586   )
0587   {
0588     return (the_message_queue->notify_handler != NULL);
0589   }
0590 #endif
0591 
0592 /**
0593  * @brief Initializes notification information.
0594  *
0595  * This routine initializes the notification information for
0596  * @a the_message_queue.
0597  *
0598  * @param[out] the_message_queue The message queue to initialize the notification information.
0599  * @param[out] the_handler The notification information for the message queue.
0600  */
0601 #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
0602   static inline void _CORE_message_queue_Set_notify (
0603     CORE_message_queue_Control        *the_message_queue,
0604     CORE_message_queue_Notify_Handler  the_handler
0605   )
0606   {
0607     the_message_queue->notify_handler = the_handler;
0608   }
0609 #else
0610   /* turn it into nothing if not enabled */
0611   #define _CORE_message_queue_Set_notify( the_message_queue, the_handler ) \
0612     do { } while ( 0 )
0613 #endif
0614 
0615 /**
0616  * @brief Gets the first locked thread waiting to receive and dequeues it.
0617  *
0618  * This method dequeues the first locked thread waiting to receive a message,
0619  *      dequeues it and returns the corresponding Thread_Control.
0620  *
0621  * @param[in, out] the_message_queue The message queue to operate upon.
0622  * @param buffer The buffer that is copied to the threads mutable_object.
0623  * @param size The size of the buffer.
0624  * @param submit_type Indicates whether the thread should be willing to block in the future.
0625  * @param queue_context The thread queue context.
0626  *
0627  * @retval thread The Thread_Control for the first locked thread, if there is a locked thread.
0628  * @retval NULL There are pending messages or no thread waiting to receive.
0629  */
0630 static inline Thread_Control *_CORE_message_queue_Dequeue_receiver(
0631   CORE_message_queue_Control      *the_message_queue,
0632   const void                      *buffer,
0633   size_t                           size,
0634   CORE_message_queue_Submit_types  submit_type,
0635   Thread_queue_Context            *queue_context
0636 )
0637 {
0638   Thread_queue_Heads *heads;
0639   Thread_Control     *the_thread;
0640 
0641   /*
0642    *  If there are pending messages, then there can't be threads
0643    *  waiting for us to send them a message.
0644    *
0645    *  NOTE: This check is critical because threads can block on
0646    *        send and receive and this ensures that we are broadcasting
0647    *        the message to threads waiting to receive -- not to send.
0648    */
0649   if ( the_message_queue->number_of_pending_messages != 0 ) {
0650     return NULL;
0651   }
0652 
0653   /*
0654    *  There must be no pending messages if there is a thread waiting to
0655    *  receive a message.
0656    */
0657   heads = the_message_queue->Wait_queue.Queue.heads;
0658   if ( heads == NULL ) {
0659     return NULL;
0660   }
0661 
0662   the_thread = ( *the_message_queue->operations->surrender )(
0663     &the_message_queue->Wait_queue.Queue,
0664     heads,
0665     NULL,
0666     queue_context
0667   );
0668 
0669    *(size_t *) the_thread->Wait.return_argument = size;
0670    the_thread->Wait.count = (uint32_t) submit_type;
0671 
0672   _CORE_message_queue_Copy_buffer(
0673     buffer,
0674     the_thread->Wait.return_argument_second.mutable_object,
0675     size
0676   );
0677 
0678   _Thread_queue_Resume(
0679     &the_message_queue->Wait_queue.Queue,
0680     the_thread,
0681     queue_context
0682   );
0683 
0684   return the_thread;
0685 }
0686 
0687 /** @} */
0688 
0689 #ifdef __cplusplus
0690 }
0691 #endif
0692 
0693 #endif
0694 /* end of include file */