source: rtems/cpukit/score/src/coremsgsubmit.c @ dce48791

5
Last change on this file since dce48791 was dce48791, checked in by Sebastian Huber <sebastian.huber@…>, on 05/23/16 at 11:37:59

score: Add Status_Control for all APIs

Unify the status codes of the Classic and POSIX API to use the new enum
Status_Control. This eliminates the Thread_Control::Wait::timeout_code
field and the timeout parameter of _Thread_queue_Enqueue_critical() and
_MPCI_Send_request_packet(). It gets rid of the status code translation
tables and instead uses simple bit operations to get the status for a
particular API. This enables translation of status code constants at
compile time. Add _Thread_Wait_get_status() to avoid direct access of
thread internal data structures.

  • 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  Watchdog_Interval                 timeout,
37  Thread_queue_Context             *queue_context
38)
39{
40  CORE_message_queue_Buffer_control *the_message;
41  Thread_Control                    *the_thread;
42
43  if ( size > the_message_queue->maximum_message_size ) {
44    _CORE_message_queue_Release( the_message_queue, queue_context );
45    return STATUS_MESSAGE_INVALID_SIZE;
46  }
47
48  /*
49   *  Is there a thread currently waiting on this message queue?
50   */
51
52  the_thread = _CORE_message_queue_Dequeue_receiver(
53    the_message_queue,
54    buffer,
55    size,
56    submit_type,
57    queue_context
58  );
59  if ( the_thread != NULL ) {
60    return STATUS_SUCCESSFUL;
61  }
62
63  /*
64   *  No one waiting on the message queue at this time, so attempt to
65   *  queue the message up for a future receive.
66   */
67  the_message =
68      _CORE_message_queue_Allocate_message_buffer( the_message_queue );
69  if ( the_message ) {
70    _CORE_message_queue_Insert_message(
71      the_message_queue,
72      the_message,
73      buffer,
74      size,
75      submit_type
76    );
77
78#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
79    /*
80     *  According to POSIX, does this happen before or after the message
81     *  is actually enqueued.  It is logical to think afterwards, because
82     *  the message is actually in the queue at this point.
83     */
84    if (
85      the_message_queue->number_of_pending_messages == 1
86        && the_message_queue->notify_handler != NULL
87    ) {
88      ( *the_message_queue->notify_handler )(
89        the_message_queue,
90        queue_context
91      );
92    } else {
93      _CORE_message_queue_Release( the_message_queue, queue_context );
94    }
95#else
96    _CORE_message_queue_Release( the_message_queue, queue_context );
97#endif
98
99    return STATUS_SUCCESSFUL;
100  }
101
102  #if !defined(RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND)
103    _CORE_message_queue_Release( the_message_queue, queue_context );
104    return STATUS_TOO_MANY;
105  #else
106    /*
107     *  No message buffers were available so we may need to return an
108     *  overflow error or block the sender until the message is placed
109     *  on the queue.
110     */
111    if ( !wait ) {
112      _CORE_message_queue_Release( the_message_queue, queue_context );
113      return STATUS_TOO_MANY;
114    }
115
116    /*
117     *  Do NOT block on a send if the caller is in an ISR.  It is
118     *  deadly to block in an ISR.
119     */
120    if ( _ISR_Is_in_progress() ) {
121      _CORE_message_queue_Release( the_message_queue, queue_context );
122      return STATUS_MESSAGE_QUEUE_WAIT_IN_ISR;
123    }
124
125    /*
126     *  WARNING!! executing should NOT be used prior to this point.
127     *  Thus the unusual choice to open a new scope and declare
128     *  it as a variable.  Doing this emphasizes how dangerous it
129     *  would be to use this variable prior to here.
130     */
131    executing->Wait.return_argument_second.immutable_object = buffer;
132    executing->Wait.option = (uint32_t) size;
133    executing->Wait.count = submit_type;
134
135    _Thread_queue_Enqueue_critical(
136      &the_message_queue->Wait_queue.Queue,
137      the_message_queue->operations,
138      executing,
139      STATES_WAITING_FOR_MESSAGE,
140      timeout,
141      &queue_context->Lock_context
142    );
143    return _Thread_Wait_get_status( executing );
144  #endif
145}
Note: See TracBrowser for help on using the repository browser.