source: rtems/cpukit/score/src/threadmp.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: 4.6 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Distributed MP Support
5 *  @ingroup ScoreThreadMP
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2006.
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/score/threadimpl.h>
22#include <rtems/score/isrlevel.h>
23#include <rtems/score/wkspace.h>
24
25#include <string.h>
26
27Chain_Control _Thread_MP_Active_proxies;
28
29Chain_Control _Thread_MP_Inactive_proxies;
30
31void _Thread_MP_Handler_initialization (
32  uint32_t    maximum_proxies
33)
34{
35  size_t    proxy_size;
36  size_t    alloc_size;
37  char     *proxies;
38  uint32_t  i;
39
40  _Chain_Initialize_empty( &_Thread_MP_Active_proxies );
41
42  if ( maximum_proxies == 0 ) {
43    _Chain_Initialize_empty( &_Thread_MP_Inactive_proxies );
44    return;
45  }
46
47  proxy_size = sizeof( Thread_Proxy_control )
48    + THREAD_QUEUE_HEADS_SIZE( _Scheduler_Count );
49  alloc_size = maximum_proxies * proxy_size;
50  proxies = _Workspace_Allocate_or_fatal_error( alloc_size );
51  memset( proxies, 0, alloc_size );
52
53  _Chain_Initialize(
54    &_Thread_MP_Inactive_proxies,
55    proxies,
56    maximum_proxies,
57    proxy_size
58  );
59
60  for ( i = 0 ; i < maximum_proxies ; ++i ) {
61    Thread_Proxy_control *proxy;
62
63    proxy = (Thread_Proxy_control *) ( proxies + i * proxy_size );
64
65    _Thread_Timer_initialize( &proxy->Timer, _Per_CPU_Get_by_index( 0 ) );
66
67    proxy->Wait.spare_heads = &proxy->Thread_queue_heads[ 0 ];
68    _Thread_queue_Heads_initialize( proxy->Wait.spare_heads );
69  }
70}
71
72Thread_Control *_Thread_MP_Allocate_proxy (
73  States_Control  the_state
74)
75{
76  Thread_Control       *the_thread;
77  Thread_Proxy_control *the_proxy;
78
79  the_thread = (Thread_Control *)_Chain_Get( &_Thread_MP_Inactive_proxies );
80
81  if ( !_Thread_Is_null( the_thread ) ) {
82    Thread_Control *executing;
83
84    executing = _Thread_Executing;
85    the_proxy = (Thread_Proxy_control *) the_thread;
86
87    executing->Wait.return_code = THREAD_STATUS_PROXY_BLOCKING;
88
89    the_proxy->receive_packet = _MPCI_Receive_server_tcb->receive_packet;
90
91    the_proxy->Object.id = _MPCI_Receive_server_tcb->receive_packet->source_tid;
92
93    the_proxy->current_priority =
94      _MPCI_Receive_server_tcb->receive_packet->source_priority;
95
96    the_proxy->current_state = _States_Set( STATES_DORMANT, the_state );
97
98    the_proxy->Wait.count                   = executing->Wait.count;
99    the_proxy->Wait.return_argument         = executing->Wait.return_argument;
100    the_proxy->Wait.return_argument_second  = executing->Wait.return_argument_second;
101    the_proxy->Wait.option                  = executing->Wait.option;
102    the_proxy->Wait.return_code             = executing->Wait.return_code;
103    the_proxy->Wait.timeout_code            = executing->Wait.timeout_code;
104
105    the_proxy->thread_queue_callout = _Thread_queue_MP_callout_do_nothing;
106
107    _Chain_Append( &_Thread_MP_Active_proxies, &the_proxy->Active );
108
109    return the_thread;
110  }
111
112  _Terminate(
113    INTERNAL_ERROR_CORE,
114    true,
115    INTERNAL_ERROR_OUT_OF_PROXIES
116  );
117
118  /*
119   *  NOTE: The following return ensures that the compiler will
120   *        think that all paths return a value.
121   */
122
123  return NULL;
124}
125
126/*
127 *  The following macro provides the offset of the Active element
128 *  in the Thread_Proxy_control structure.  This is the logical
129 *  equivalent of the POSITION attribute in Ada.
130 */
131
132#define _Thread_MP_Proxy_Active_offset \
133     ((uint32_t)&(((Thread_Proxy_control *)0))->Active)
134
135Thread_Control *_Thread_MP_Find_proxy (
136  Objects_Id  the_id
137)
138{
139
140  Chain_Node           *proxy_node;
141  Thread_Control       *the_thread;
142  ISR_Level             level;
143
144restart:
145
146  _ISR_Disable( level );
147
148    for (  proxy_node = _Chain_First( &_Thread_MP_Active_proxies );
149           !_Chain_Is_tail( &_Thread_MP_Active_proxies, proxy_node ) ;
150        ) {
151
152      the_thread = (Thread_Control *) _Addresses_Subtract_offset(
153                     proxy_node,
154                     _Thread_MP_Proxy_Active_offset
155                   );
156
157      if ( _Objects_Are_ids_equal( the_thread->Object.id, the_id ) ) {
158        _ISR_Enable( level );
159        return the_thread;
160      }
161
162      _ISR_Flash( level );
163
164      proxy_node = _Chain_Next( proxy_node );
165
166      /*
167       *  A proxy which is only dormant is not in a blocking state.
168       *  Therefore, we are looking at proxy which has been moved from
169       *  active to inactive chain (by an ISR) and need to restart
170       *  the search.
171       */
172
173      if ( _States_Is_only_dormant( the_thread->current_state ) ) {
174        _ISR_Enable( level );
175        goto restart;
176      }
177    }
178
179  _ISR_Enable( level );
180  return NULL;
181}
Note: See TracBrowser for help on using the repository browser.