source: rtems/cpukit/score/src/coremsgsubmit.c @ 1c2d178

5
Last change on this file since 1c2d178 was c3105894, checked in by Sebastian Huber <sebastian.huber@…>, on 10/19/17 at 11:47:57

score: Move thread queue timeout handling

Update #3117.
Update #3182.

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/**
2 * @file
3 *
4 * @brief CORE Message Queue Submit
5 *
6 * @ingroup ScoreMessageQueue
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2009.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <rtems/score/coremsgimpl.h>
23#include <rtems/score/objectimpl.h>
24#include <rtems/score/isr.h>
25#include <rtems/score/threadimpl.h>
26#include <rtems/score/statesimpl.h>
27#include <rtems/score/wkspace.h>
28
29Status_Control _CORE_message_queue_Submit(
30  CORE_message_queue_Control       *the_message_queue,
31  Thread_Control                   *executing,
32  const void                       *buffer,
33  size_t                            size,
34  CORE_message_queue_Submit_types   submit_type,
35  bool                              wait,
36  Thread_queue_Context             *queue_context
37)
38{
39  CORE_message_queue_Buffer_control *the_message;
40  Thread_Control                    *the_thread;
41
42  if ( size > the_message_queue->maximum_message_size ) {
43    _CORE_message_queue_Release( the_message_queue, queue_context );
44    return STATUS_MESSAGE_INVALID_SIZE;
45  }
46
47  /*
48   *  Is there a thread currently waiting on this message queue?
49   */
50
51  the_thread = _CORE_message_queue_Dequeue_receiver(
52    the_message_queue,
53    buffer,
54    size,
55    submit_type,
56    queue_context
57  );
58  if ( the_thread != NULL ) {
59    return STATUS_SUCCESSFUL;
60  }
61
62  /*
63   *  No one waiting on the message queue at this time, so attempt to
64   *  queue the message up for a future receive.
65   */
66  the_message =
67      _CORE_message_queue_Allocate_message_buffer( the_message_queue );
68  if ( the_message ) {
69    _CORE_message_queue_Insert_message(
70      the_message_queue,
71      the_message,
72      buffer,
73      size,
74      submit_type
75    );
76
77#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
78    /*
79     *  According to POSIX, does this happen before or after the message
80     *  is actually enqueued.  It is logical to think afterwards, because
81     *  the message is actually in the queue at this point.
82     */
83    if (
84      the_message_queue->number_of_pending_messages == 1
85        && the_message_queue->notify_handler != NULL
86    ) {
87      ( *the_message_queue->notify_handler )(
88        the_message_queue,
89        queue_context
90      );
91    } else {
92      _CORE_message_queue_Release( the_message_queue, queue_context );
93    }
94#else
95    _CORE_message_queue_Release( the_message_queue, queue_context );
96#endif
97
98    return STATUS_SUCCESSFUL;
99  }
100
101  #if !defined(RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND)
102    _CORE_message_queue_Release( the_message_queue, queue_context );
103    return STATUS_TOO_MANY;
104  #else
105    /*
106     *  No message buffers were available so we may need to return an
107     *  overflow error or block the sender until the message is placed
108     *  on the queue.
109     */
110    if ( !wait ) {
111      _CORE_message_queue_Release( the_message_queue, queue_context );
112      return STATUS_TOO_MANY;
113    }
114
115    /*
116     *  Do NOT block on a send if the caller is in an ISR.  It is
117     *  deadly to block in an ISR.
118     */
119    if ( _ISR_Is_in_progress() ) {
120      _CORE_message_queue_Release( the_message_queue, queue_context );
121      return STATUS_MESSAGE_QUEUE_WAIT_IN_ISR;
122    }
123
124    /*
125     *  WARNING!! executing should NOT be used prior to this point.
126     *  Thus the unusual choice to open a new scope and declare
127     *  it as a variable.  Doing this emphasizes how dangerous it
128     *  would be to use this variable prior to here.
129     */
130    executing->Wait.return_argument_second.immutable_object = buffer;
131    executing->Wait.option = (uint32_t) size;
132    executing->Wait.count = submit_type;
133
134    _Thread_queue_Context_set_thread_state(
135      queue_context,
136      STATES_WAITING_FOR_MESSAGE
137    );
138    _Thread_queue_Enqueue(
139      &the_message_queue->Wait_queue.Queue,
140      the_message_queue->operations,
141      executing,
142      queue_context
143    );
144    return _Thread_Wait_get_status( executing );
145  #endif
146}
Note: See TracBrowser for help on using the repository browser.