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

5
Last change on this file since e2735012 was e2735012, checked in by Sebastian Huber <sebastian.huber@…>, on 06/24/15 at 09:05:39

score: Introduce Thread_queue_Queue

Separate the thread queue heads and lock from the operations. This
enables the support for light weight objects which only support one
queuing discipline.

  • Property mode set to 100644
File size: 4.4 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/statesimpl.h>
26#include <rtems/score/wkspace.h>
27
28CORE_message_queue_Status _CORE_message_queue_Submit(
29  CORE_message_queue_Control                *the_message_queue,
30  Thread_Control                            *executing,
31  const void                                *buffer,
32  size_t                                     size,
33  Objects_Id                                 id,
34  #if defined(RTEMS_MULTIPROCESSING)
35    CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
36  #else
37    CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support  __attribute__((unused)),
38  #endif
39  CORE_message_queue_Submit_types            submit_type,
40  bool                                       wait,
41  Watchdog_Interval                          timeout,
42  ISR_lock_Context                          *lock_context
43)
44{
45  CORE_message_queue_Buffer_control *the_message;
46  Thread_Control                    *the_thread;
47
48  if ( size > the_message_queue->maximum_message_size ) {
49    _ISR_lock_ISR_enable( lock_context );
50    return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
51  }
52
53  _CORE_message_queue_Acquire_critical( the_message_queue, lock_context );
54
55  /*
56   *  Is there a thread currently waiting on this message queue?
57   */
58
59  the_thread = _CORE_message_queue_Dequeue_receiver(
60    the_message_queue,
61    buffer,
62    size,
63    submit_type,
64    lock_context
65  );
66  if ( the_thread != NULL ) {
67    #if defined(RTEMS_MULTIPROCESSING)
68      if ( !_Objects_Is_local_id( the_thread->Object.id ) )
69        (*api_message_queue_mp_support) ( the_thread, id );
70
71      _Thread_Dispatch_enable( _Per_CPU_Get() );
72    #endif
73    return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
74  }
75
76  /*
77   *  No one waiting on the message queue at this time, so attempt to
78   *  queue the message up for a future receive.
79   */
80  the_message =
81      _CORE_message_queue_Allocate_message_buffer( the_message_queue );
82  if ( the_message ) {
83    the_message->Contents.size = size;
84    _CORE_message_queue_Set_message_priority( the_message, submit_type );
85    _CORE_message_queue_Copy_buffer(
86      buffer,
87      the_message->Contents.buffer,
88      size
89    );
90
91    _CORE_message_queue_Insert_message(
92       the_message_queue,
93       the_message,
94       submit_type
95    );
96    _CORE_message_queue_Release( the_message_queue, lock_context );
97    return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
98  }
99
100  #if !defined(RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND)
101    _CORE_message_queue_Release( the_message_queue, lock_context );
102    return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
103  #else
104    /*
105     *  No message buffers were available so we may need to return an
106     *  overflow error or block the sender until the message is placed
107     *  on the queue.
108     */
109    if ( !wait ) {
110      _CORE_message_queue_Release( the_message_queue, lock_context );
111      return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
112    }
113
114    /*
115     *  Do NOT block on a send if the caller is in an ISR.  It is
116     *  deadly to block in an ISR.
117     */
118    if ( _ISR_Is_in_progress() ) {
119      _CORE_message_queue_Release( the_message_queue, lock_context );
120      return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
121    }
122
123    /*
124     *  WARNING!! executing should NOT be used prior to this point.
125     *  Thus the unusual choice to open a new scope and declare
126     *  it as a variable.  Doing this emphasizes how dangerous it
127     *  would be to use this variable prior to here.
128     */
129    executing->Wait.id = id;
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_Enqueue_critical(
135      &the_message_queue->Wait_queue.Queue,
136      the_message_queue->Wait_queue.operations,
137      executing,
138      STATES_WAITING_FOR_MESSAGE,
139      timeout,
140      CORE_MESSAGE_QUEUE_STATUS_TIMEOUT,
141      lock_context
142    );
143    #if defined(RTEMS_MULTIPROCESSING)
144      _Thread_Dispatch_enable( _Per_CPU_Get() );
145    #endif
146
147    return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT;
148  #endif
149}
Note: See TracBrowser for help on using the repository browser.