source: rtems/c/src/exec/score/src/coremsgsubmit.c @ 53fb837a

4.104.114.84.95
Last change on this file since 53fb837a was 53fb837a, checked in by Joel Sherrill <joel.sherrill@…>, on 01/13/00 at 19:25:15

POSIX message queues now include complete functionality including
blocking sends when the queue is full. The SuperCore? was enhanced
to support blocking on send. The existing POSIX API was debugged
and numerous test cases were added to psxmsgq01 by Jennifer Averett.
SuperCore? enhancements and resulting modifications to other APIs
were done by Joel.

There is one significant point of interpretation for the POSIX API.
What happens to threads already blocked on a message queue when the
mode of that same message queue is changed from blocking to non-blocking?
We decided to unblock all waiting tasks with an EAGAIN error just
as if a non-blocking version of the same operation had returned
unsatisfied. This case is not discussed in the POSIX standard and
other implementations may have chosen differently.

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/*
2 *  CORE Message Queue Handler
3 *
4 *  DESCRIPTION:
5 *
6 *  This package is the implementation of the CORE Message Queue Handler.
7 *  This core object provides task synchronization and communication functions
8 *  via messages passed to queue objects.
9 *
10 *  COPYRIGHT (c) 1989-1999.
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.OARcorp.com/rtems/license.html.
16 *
17 *  $Id$
18 */
19
20#include <rtems/system.h>
21#include <rtems/score/chain.h>
22#include <rtems/score/isr.h>
23#include <rtems/score/object.h>
24#include <rtems/score/coremsg.h>
25#include <rtems/score/states.h>
26#include <rtems/score/thread.h>
27#include <rtems/score/wkspace.h>
28#if defined(RTEMS_MULTIPROCESSING)
29#include <rtems/score/mpci.h>
30#endif
31
32/*PAGE
33 *
34 *  _CORE_message_queue_Submit
35 *
36 *  This routine implements the send and urgent message functions. It
37 *  processes a message that is to be submitted to the designated
38 *  message queue.  The message will either be processed as a
39 *  send message which it will be inserted at the rear of the queue
40 *  or it will be processed as an urgent message which will be inserted
41 *  at the front of the queue.
42 *
43 *  Input parameters:
44 *    the_message_queue            - message is submitted to this message queue
45 *    buffer                       - pointer to message buffer
46 *    size                         - size in bytes of message to send
47 *    id                           - id of message queue
48 *    api_message_queue_mp_support - api specific mp support callout
49 *    submit_type                  - send or urgent message
50 *
51 *  Output parameters:
52 *    CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
53 *    error code                    - if unsuccessful
54 */
55
56void _CORE_message_queue_Submit(
57  CORE_message_queue_Control                *the_message_queue,
58  void                                      *buffer,
59  unsigned32                                 size,
60  Objects_Id                                 id,
61  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
62  CORE_message_queue_Submit_types            submit_type,
63  boolean                                    wait,
64  Watchdog_Interval                          timeout
65)
66{
67  ISR_Level                            level;
68  CORE_message_queue_Buffer_control   *the_message;
69  Thread_Control                      *the_thread;
70  Thread_Control                      *executing;
71
72  _Thread_Executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
73
74  if ( size > the_message_queue->maximum_message_size ) {
75    _Thread_Executing->Wait.return_code =
76       CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
77    return;
78  }
79
80  /*
81   *  Is there a thread currently waiting on this message queue?
82   */
83     
84  if ( the_message_queue->number_of_pending_messages == 0 ) {
85    the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
86    if ( the_thread ) {
87      _CORE_message_queue_Copy_buffer(
88        buffer,
89        the_thread->Wait.return_argument,
90        size
91      );
92      *(unsigned32 *)the_thread->Wait.return_argument_1 = size;
93      the_thread->Wait.count = submit_type;
94   
95#if defined(RTEMS_MULTIPROCESSING)
96      if ( !_Objects_Is_local_id( the_thread->Object.id ) )
97        (*api_message_queue_mp_support) ( the_thread, id );
98#endif
99      return;
100    }
101  }
102
103  /*
104   *  No one waiting on the message queue at this time, so attempt to
105   *  queue the message up for a future receive.
106   */
107
108  if ( the_message_queue->number_of_pending_messages <
109       the_message_queue->maximum_pending_messages ) {
110
111    the_message =
112        _CORE_message_queue_Allocate_message_buffer( the_message_queue );
113
114    /*
115     *  NOTE: If the system is consistent, this error should never occur.
116     */
117    if ( !the_message ) {
118      _Thread_Executing->Wait.return_code =
119          CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
120      return;
121    }
122
123    _CORE_message_queue_Copy_buffer(
124      buffer,
125      the_message->Contents.buffer,
126      size
127    );
128    the_message->Contents.size = size;
129    the_message->priority  = submit_type;
130
131    _CORE_message_queue_Insert_message(
132       the_message_queue,
133       the_message,
134       submit_type
135    );
136    return;
137  }
138
139  /*
140   *  No message buffers were available so we may need to return an
141   *  overflow error or block the sender until the message is placed
142   *  on the queue.
143   */
144
145  if ( !wait ) {
146    _Thread_Executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
147    return;
148  }
149
150  executing = _Thread_Executing;
151
152  _ISR_Disable( level );
153  _Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
154  executing->Wait.queue              = &the_message_queue->Wait_queue;
155  executing->Wait.id                 = id;
156  executing->Wait.return_argument    = (void *)buffer;
157  executing->Wait.return_argument_1  = (void *)size;
158  executing->Wait.count              = submit_type;
159  _ISR_Enable( level );
160
161  _Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
162}
Note: See TracBrowser for help on using the repository browser.