source: rtems/cpukit/posix/src/mqueuesendsupp.c @ 8f96581

5
Last change on this file since 8f96581 was 8f96581, checked in by Sebastian Huber <sebastian.huber@…>, on 04/01/16 at 09:38:47

score: Rework MP thread queue callout support

The thread queue implementation was heavily reworked to support SMP.
This broke the multiprocessing support of the thread queues. This is
fixed by this patch.

A thread proxy is unblocked due to three reasons

1) timeout,
2) request satisfaction, and
3) extraction.

In case 1) no MPCI message must be sent. This is ensured via the
_Thread_queue_MP_callout_do_nothing() callout set during
_Thread_MP_Allocate_proxy().

In case 2) and 3) an MPCI message must be sent. In case we interrupt
the blocking operation during _Thread_queue_Enqueue_critical(), then
this message must be sent by the blocking thread. For this the new
fields Thread_Proxy_control::thread_queue_callout and
Thread_Proxy_control::thread_queue_id are used.

Delete the individual API MP callout types and use
Thread_queue_MP_callout throughout. This type is only defined in
multiprocessing configurations. Prefix the multiprocessing parameters
with mp_ to ease code review. Multiprocessing specific parameters are
optional due to use of a similar macro pattern. There is no overhead
for non-multiprocessing configurations.

  • Property mode set to 100644
File size: 3.7 KB
Line 
1/**
2 * @file
3 *
4 * @brief POSIX Message Queue and Send Support
5 * @ingroup POSIXAPI
6 */
7
8/*
9 *  NOTE:  The structure of the routines is identical to that of POSIX
10 *         Message_queues to leave the option of having unnamed message
11 *         queues at a future date.  They are currently not part of the
12 *         POSIX standard but unnamed message_queues are.  This is also
13 *         the reason for the apparently unnecessary tracking of
14 *         the process_shared attribute.  [In addition to the fact that
15 *         it would be trivial to add pshared to the mq_attr structure
16 *         and have process private message queues.]
17 *
18 *         This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
19 *         time.
20 *
21 *  COPYRIGHT (c) 1989-2008.
22 *  On-Line Applications Research Corporation (OAR).
23 *
24 *  The license and distribution terms for this file may be
25 *  found in the file LICENSE in this distribution or at
26 *  http://www.rtems.org/license/LICENSE.
27 */
28
29#if HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <stdarg.h>
34
35#include <pthread.h>
36#include <limits.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <mqueue.h>
40
41#include <rtems/system.h>
42#include <rtems/score/watchdog.h>
43#include <rtems/seterr.h>
44#include <rtems/posix/mqueueimpl.h>
45
46
47/*
48 *  _POSIX_Message_queue_Send_support
49 */
50
51int _POSIX_Message_queue_Send_support(
52  mqd_t               mqdes,
53  const char         *msg_ptr,
54  size_t              msg_len,
55  unsigned int        msg_prio,
56  bool                wait,
57  Watchdog_Interval   timeout
58)
59{
60  POSIX_Message_queue_Control    *the_mq;
61  POSIX_Message_queue_Control_fd *the_mq_fd;
62  Objects_Locations               location;
63  CORE_message_queue_Status       msg_status;
64  bool                            do_wait;
65  Thread_Control                 *executing;
66  ISR_lock_Context                lock_context;
67
68  /*
69   * Validate the priority.
70   * XXX - Do not validate msg_prio is not less than 0.
71   */
72
73  if ( msg_prio > MQ_PRIO_MAX )
74    rtems_set_errno_and_return_minus_one( EINVAL );
75
76  the_mq_fd = _POSIX_Message_queue_Get_fd_interrupt_disable(
77    mqdes,
78    &location,
79    &lock_context
80  );
81  switch ( location ) {
82
83    case OBJECTS_LOCAL:
84      if ( (the_mq_fd->oflag & O_ACCMODE) == O_RDONLY ) {
85        _ISR_lock_ISR_enable( &lock_context );
86        rtems_set_errno_and_return_minus_one( EBADF );
87      }
88
89      the_mq = the_mq_fd->Queue;
90
91      /*
92       *  A timed receive with a bad time will do a poll regardless.
93       */
94      if ( wait )
95        do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? false : true;
96      else
97        do_wait = wait;
98
99      /*
100       *  Now perform the actual message receive
101       */
102      executing = _Thread_Executing;
103      msg_status = _CORE_message_queue_Submit(
104        &the_mq->Message_queue,
105        executing,
106        msg_ptr,
107        msg_len,
108        NULL,
109        0,
110        _POSIX_Message_queue_Priority_to_core( msg_prio ),
111        do_wait,
112        timeout,   /* no timeout */
113        &lock_context
114      );
115
116      /*
117       *  If we had to block, then this is where the task returns
118       *  after it wakes up.  The returned status is correct for
119       *  non-blocking operations but if we blocked, then we need
120       *  to look at the status in our TCB.
121       */
122
123      if ( msg_status == CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT )
124        msg_status = executing->Wait.return_code;
125
126      if ( !msg_status )
127        return msg_status;
128
129      rtems_set_errno_and_return_minus_one(
130        _POSIX_Message_queue_Translate_core_message_queue_return_code(
131          msg_status
132        )
133      );
134
135#if defined(RTEMS_MULTIPROCESSING)
136    case OBJECTS_REMOTE:
137#endif
138    case OBJECTS_ERROR:
139      break;
140  }
141
142  rtems_set_errno_and_return_minus_one( EBADF );
143}
Note: See TracBrowser for help on using the repository browser.