source: rtems/cpukit/score/src/coremsgseize.c @ bbd6d27a

5
Last change on this file since bbd6d27a 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: 4.1 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Size a Message from the Message Queue
5 *  @ingroup ScoreMessageQueue
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2007.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/system.h>
22#include <rtems/score/chain.h>
23#include <rtems/score/isr.h>
24#include <rtems/score/coremsgimpl.h>
25#include <rtems/score/thread.h>
26#include <rtems/score/statesimpl.h>
27#include <rtems/score/wkspace.h>
28
29void _CORE_message_queue_Seize(
30  CORE_message_queue_Control *the_message_queue,
31  Thread_Control             *executing,
32  Objects_Id                  id,
33  void                       *buffer,
34  size_t                     *size_p,
35  bool                        wait,
36  Watchdog_Interval           timeout,
37  ISR_lock_Context           *lock_context
38)
39{
40  CORE_message_queue_Buffer_control *the_message;
41
42  executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
43  _CORE_message_queue_Acquire_critical( the_message_queue, lock_context );
44  the_message = _CORE_message_queue_Get_pending_message( the_message_queue );
45  if ( the_message != NULL ) {
46    the_message_queue->number_of_pending_messages -= 1;
47
48    *size_p = the_message->Contents.size;
49    executing->Wait.count =
50      _CORE_message_queue_Get_message_priority( the_message );
51    _CORE_message_queue_Copy_buffer(
52      the_message->Contents.buffer,
53      buffer,
54      *size_p
55    );
56
57    #if !defined(RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND)
58      /*
59       *  There is not an API with blocking sends enabled.
60       *  So return immediately.
61       */
62      _CORE_message_queue_Free_message_buffer(the_message_queue, the_message);
63      _CORE_message_queue_Release( the_message_queue, lock_context );
64      return;
65    #else
66    {
67      Thread_Control   *the_thread;
68
69      /*
70       *  There could be a thread waiting to send a message.  If there
71       *  is not, then we can go ahead and free the buffer.
72       *
73       *  NOTE: If we note that the queue was not full before this receive,
74       *  then we can avoid this dequeue.
75       */
76      the_thread = _Thread_queue_First_locked(
77        &the_message_queue->Wait_queue,
78        the_message_queue->operations
79      );
80      if ( the_thread == NULL ) {
81        _CORE_message_queue_Free_message_buffer(
82          the_message_queue,
83          the_message
84        );
85        _CORE_message_queue_Release( the_message_queue, lock_context );
86        return;
87      }
88
89      /*
90       *  There was a thread waiting to send a message.  This code
91       *  puts the messages in the message queue on behalf of the
92       *  waiting task.
93       */
94      _CORE_message_queue_Set_message_priority(
95        the_message,
96        the_thread->Wait.count
97      );
98      the_message->Contents.size = (size_t) the_thread->Wait.option;
99      _CORE_message_queue_Copy_buffer(
100        the_thread->Wait.return_argument_second.immutable_object,
101        the_message->Contents.buffer,
102        the_message->Contents.size
103      );
104
105      _CORE_message_queue_Insert_message(
106         the_message_queue,
107         the_message,
108         _CORE_message_queue_Get_message_priority( the_message )
109      );
110      _Thread_queue_Extract_critical(
111        &the_message_queue->Wait_queue.Queue,
112        the_message_queue->operations,
113        the_thread,
114        NULL,
115        0,
116        lock_context
117      );
118      return;
119    }
120    #endif
121  }
122
123  if ( !wait ) {
124    _CORE_message_queue_Release( the_message_queue, lock_context );
125    executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT;
126    return;
127  }
128
129  executing->Wait.return_argument_second.mutable_object = buffer;
130  executing->Wait.return_argument = size_p;
131  /* Wait.count will be filled in with the message priority */
132
133  _Thread_queue_Enqueue_critical(
134    &the_message_queue->Wait_queue.Queue,
135    the_message_queue->operations,
136    executing,
137    STATES_WAITING_FOR_MESSAGE,
138    timeout,
139    CORE_MESSAGE_QUEUE_STATUS_TIMEOUT,
140    lock_context
141  );
142}
Note: See TracBrowser for help on using the repository browser.