Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreMessageQueue
0007  *
0008  * @brief This source file contains the implementation of
0009  *   _CORE_message_queue_Submit().
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2009.
0014  *  On-Line Applications Research Corporation (OAR).
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041 
0042 #include <rtems/score/coremsgimpl.h>
0043 #include <rtems/score/objectimpl.h>
0044 #include <rtems/score/isr.h>
0045 #include <rtems/score/threadimpl.h>
0046 #include <rtems/score/statesimpl.h>
0047 
0048 Status_Control _CORE_message_queue_Submit(
0049   CORE_message_queue_Control       *the_message_queue,
0050   Thread_Control                   *executing,
0051   const void                       *buffer,
0052   size_t                            size,
0053   CORE_message_queue_Submit_types   submit_type,
0054   bool                              wait,
0055   Thread_queue_Context             *queue_context
0056 )
0057 {
0058   CORE_message_queue_Buffer *the_message;
0059   Thread_Control            *the_thread;
0060 
0061   if ( size > the_message_queue->maximum_message_size ) {
0062     _CORE_message_queue_Release( the_message_queue, queue_context );
0063     return STATUS_MESSAGE_INVALID_SIZE;
0064   }
0065 
0066   /*
0067    *  Is there a thread currently waiting on this message queue?
0068    */
0069 
0070   the_thread = _CORE_message_queue_Dequeue_receiver(
0071     the_message_queue,
0072     buffer,
0073     size,
0074     submit_type,
0075     queue_context
0076   );
0077   if ( the_thread != NULL ) {
0078     return STATUS_SUCCESSFUL;
0079   }
0080 
0081   /*
0082    *  No one waiting on the message queue at this time, so attempt to
0083    *  queue the message up for a future receive.
0084    */
0085   the_message =
0086       _CORE_message_queue_Allocate_message_buffer( the_message_queue );
0087   if ( the_message ) {
0088     _CORE_message_queue_Insert_message(
0089       the_message_queue,
0090       the_message,
0091       buffer,
0092       size,
0093       submit_type
0094     );
0095 
0096 #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
0097     /*
0098      *  According to POSIX, does this happen before or after the message
0099      *  is actually enqueued.  It is logical to think afterwards, because
0100      *  the message is actually in the queue at this point.
0101      */
0102     if (
0103       the_message_queue->number_of_pending_messages == 1
0104         && the_message_queue->notify_handler != NULL
0105     ) {
0106       ( *the_message_queue->notify_handler )(
0107         the_message_queue,
0108         queue_context
0109       );
0110     } else {
0111       _CORE_message_queue_Release( the_message_queue, queue_context );
0112     }
0113 #else
0114     _CORE_message_queue_Release( the_message_queue, queue_context );
0115 #endif
0116 
0117     return STATUS_SUCCESSFUL;
0118   }
0119 
0120 #if !defined(RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND)
0121   _CORE_message_queue_Release( the_message_queue, queue_context );
0122   return STATUS_TOO_MANY;
0123 #else
0124   /*
0125    *  No message buffers were available so we may need to return an
0126    *  overflow error or block the sender until the message is placed
0127    *  on the queue.
0128    */
0129   if ( !wait ) {
0130     _CORE_message_queue_Release( the_message_queue, queue_context );
0131     return STATUS_TOO_MANY;
0132   }
0133 
0134   /*
0135    *  Do NOT block on a send if the caller is in an ISR.  It is
0136    *  deadly to block in an ISR.
0137    */
0138   if ( _ISR_Is_in_progress() ) {
0139     _CORE_message_queue_Release( the_message_queue, queue_context );
0140     return STATUS_MESSAGE_QUEUE_WAIT_IN_ISR;
0141   }
0142 
0143   /*
0144    *  WARNING!! executing should NOT be used prior to this point.
0145    *  Thus the unusual choice to open a new scope and declare
0146    *  it as a variable.  Doing this emphasizes how dangerous it
0147    *  would be to use this variable prior to here.
0148    */
0149   executing->Wait.return_argument_second.immutable_object = buffer;
0150   executing->Wait.option = (uint32_t) size;
0151   executing->Wait.count = submit_type;
0152 
0153   _Thread_queue_Context_set_thread_state(
0154     queue_context,
0155     STATES_WAITING_FOR_MESSAGE
0156   );
0157   _Thread_queue_Enqueue(
0158     &the_message_queue->Wait_queue.Queue,
0159     the_message_queue->operations,
0160     executing,
0161     queue_context
0162   );
0163   return _Thread_Wait_get_status( executing );
0164 #endif
0165 }