source: rtems/cpukit/score/src/threadmp.c @ 84dc9df

5
Last change on this file since 84dc9df was 84dc9df, checked in by Sebastian Huber <sebastian.huber@…>, on 04/04/16 at 04:17:36

score: Use red-black tree for active MP proxies

Update #2555.

  • Property mode set to 100644
File size: 5.4 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/isrlock.h>
23#include <rtems/score/wkspace.h>
24
25#include <string.h>
26
27static RBTREE_DEFINE_EMPTY( _Thread_MP_Active_proxies );
28
29static CHAIN_DEFINE_EMPTY( _Thread_MP_Inactive_proxies );
30
31ISR_LOCK_DEFINE( static, _Thread_MP_Proxies_lock, "Thread MP Proxies" )
32
33static void _Thread_MP_Proxies_acquire( ISR_lock_Context *lock_context )
34{
35  _ISR_lock_ISR_disable_and_acquire( &_Thread_MP_Proxies_lock, lock_context );
36}
37
38static void _Thread_MP_Proxies_release( ISR_lock_Context *lock_context )
39{
40  _ISR_lock_Release_and_ISR_enable( &_Thread_MP_Proxies_lock, lock_context );
41}
42
43void _Thread_MP_Handler_initialization (
44  uint32_t    maximum_proxies
45)
46{
47  size_t    proxy_size;
48  size_t    alloc_size;
49  char     *proxies;
50  uint32_t  i;
51
52  if ( maximum_proxies == 0 ) {
53    return;
54  }
55
56  proxy_size = sizeof( Thread_Proxy_control )
57    + THREAD_QUEUE_HEADS_SIZE( _Scheduler_Count );
58  alloc_size = maximum_proxies * proxy_size;
59  proxies = _Workspace_Allocate_or_fatal_error( alloc_size );
60  memset( proxies, 0, alloc_size );
61
62  _Chain_Initialize(
63    &_Thread_MP_Inactive_proxies,
64    proxies,
65    maximum_proxies,
66    proxy_size
67  );
68
69  for ( i = 0 ; i < maximum_proxies ; ++i ) {
70    Thread_Proxy_control *proxy;
71
72    proxy = (Thread_Proxy_control *) ( proxies + i * proxy_size );
73
74    _Thread_Timer_initialize( &proxy->Timer, _Per_CPU_Get_by_index( 0 ) );
75
76    proxy->Wait.spare_heads = &proxy->Thread_queue_heads[ 0 ];
77    _Thread_queue_Heads_initialize( proxy->Wait.spare_heads );
78  }
79}
80
81#define THREAD_MP_PROXY_OF_ACTIVE_NODE( the_node ) \
82  RTEMS_CONTAINER_OF( the_node, Thread_Proxy_control, Active )
83
84static bool _Thread_MP_Proxy_equal(
85  const void        *left,
86  const RBTree_Node *right
87)
88{
89  const Objects_Id           *the_left;
90  const Thread_Proxy_control *the_right;
91
92  the_left = left;
93  the_right = THREAD_MP_PROXY_OF_ACTIVE_NODE( right );
94
95  return *the_left == the_right->Object.id;
96}
97
98static bool _Thread_MP_Proxy_less(
99  const void        *left,
100  const RBTree_Node *right
101)
102{
103  const Objects_Id           *the_left;
104  const Thread_Proxy_control *the_right;
105
106  the_left = left;
107  the_right = THREAD_MP_PROXY_OF_ACTIVE_NODE( right );
108
109  return *the_left < the_right->Object.id;
110}
111
112static void *_Thread_MP_Proxy_map( RBTree_Node *node )
113{
114  return THREAD_MP_PROXY_OF_ACTIVE_NODE( node );
115}
116
117Thread_Control *_Thread_MP_Allocate_proxy (
118  States_Control  the_state
119)
120{
121  Thread_Proxy_control *the_proxy;
122  ISR_lock_Context      lock_context;
123
124  _Thread_MP_Proxies_acquire( &lock_context );
125
126  the_proxy = (Thread_Proxy_control *)
127    _Chain_Get_unprotected( &_Thread_MP_Inactive_proxies );
128  if ( the_proxy != NULL ) {
129    Thread_Control   *executing;
130    MP_packet_Prefix *receive_packet;
131    Objects_Id        source_tid;
132
133    executing = _Thread_Executing;
134    receive_packet = _MPCI_Receive_server_tcb->receive_packet;
135    source_tid = receive_packet->source_tid;
136
137    executing->Wait.return_code = THREAD_STATUS_PROXY_BLOCKING;
138
139    the_proxy->receive_packet = receive_packet;
140    the_proxy->Object.id = source_tid;
141    the_proxy->current_priority = receive_packet->source_priority;
142    the_proxy->current_state = _States_Set( STATES_DORMANT, the_state );
143
144    the_proxy->Wait.count                   = executing->Wait.count;
145    the_proxy->Wait.return_argument         = executing->Wait.return_argument;
146    the_proxy->Wait.return_argument_second  = executing->Wait.return_argument_second;
147    the_proxy->Wait.option                  = executing->Wait.option;
148    the_proxy->Wait.return_code             = executing->Wait.return_code;
149    the_proxy->Wait.timeout_code            = executing->Wait.timeout_code;
150
151    the_proxy->thread_queue_callout = _Thread_queue_MP_callout_do_nothing;
152
153    _RBTree_Insert_inline(
154      &_Thread_MP_Active_proxies,
155      &the_proxy->Active,
156      &source_tid,
157      _Thread_MP_Proxy_less
158    );
159
160    _Thread_MP_Proxies_release( &lock_context );
161
162    return (Thread_Control *) the_proxy;
163  }
164
165  _Thread_MP_Proxies_release( &lock_context );
166
167  _Terminate(
168    INTERNAL_ERROR_CORE,
169    true,
170    INTERNAL_ERROR_OUT_OF_PROXIES
171  );
172
173  /*
174   *  NOTE: The following return ensures that the compiler will
175   *        think that all paths return a value.
176   */
177
178  return NULL;
179}
180
181Thread_Control *_Thread_MP_Find_proxy (
182  Objects_Id  the_id
183)
184{
185  Thread_Proxy_control *the_proxy;
186  ISR_lock_Context      lock_context;
187
188  _Thread_MP_Proxies_acquire( &lock_context );
189
190  the_proxy = _RBTree_Find_inline(
191    &_Thread_MP_Active_proxies,
192    &the_id,
193    _Thread_MP_Proxy_equal,
194    _Thread_MP_Proxy_less,
195    _Thread_MP_Proxy_map
196  );
197
198  _Thread_MP_Proxies_release( &lock_context );
199
200  return (Thread_Control *) the_proxy;
201}
202
203void _Thread_MP_Free_proxy( Thread_Control *the_thread )
204{
205  Thread_Proxy_control *the_proxy;
206  ISR_lock_Context      lock_context;
207
208  the_proxy = (Thread_Proxy_control *) the_thread;
209
210  _Thread_MP_Proxies_acquire( &lock_context );
211
212  _RBTree_Extract( &_Thread_MP_Active_proxies, &the_proxy->Active );
213  _Chain_Append_unprotected(
214    &_Thread_MP_Inactive_proxies,
215    &the_proxy->Object.Node
216  );
217
218  _Thread_MP_Proxies_release( &lock_context );
219}
Note: See TracBrowser for help on using the repository browser.