source: rtems/cpukit/score/src/threadmp.c @ 99fc1d1d

5
Last change on this file since 99fc1d1d was dce48791, checked in by Sebastian Huber <sebastian.huber@…>, on 05/23/16 at 11:37:59

score: Add Status_Control for all APIs

Unify the status codes of the Classic and POSIX API to use the new enum
Status_Control. This eliminates the Thread_Control::Wait::timeout_code
field and the timeout parameter of _Thread_queue_Enqueue_critical() and
_MPCI_Send_request_packet(). It gets rid of the status code translation
tables and instead uses simple bit operations to get the status for a
particular API. This enables translation of status code constants at
compile time. Add _Thread_Wait_get_status() to avoid direct access of
thread internal data structures.

  • 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
150    the_proxy->thread_queue_callout = _Thread_queue_MP_callout_do_nothing;
151
152    _RBTree_Insert_inline(
153      &_Thread_MP_Active_proxies,
154      &the_proxy->Active,
155      &source_tid,
156      _Thread_MP_Proxy_less
157    );
158
159    _Thread_MP_Proxies_release( &lock_context );
160
161    return (Thread_Control *) the_proxy;
162  }
163
164  _Thread_MP_Proxies_release( &lock_context );
165
166  _Terminate(
167    INTERNAL_ERROR_CORE,
168    true,
169    INTERNAL_ERROR_OUT_OF_PROXIES
170  );
171
172  /*
173   *  NOTE: The following return ensures that the compiler will
174   *        think that all paths return a value.
175   */
176
177  return NULL;
178}
179
180Thread_Control *_Thread_MP_Find_proxy (
181  Objects_Id  the_id
182)
183{
184  Thread_Proxy_control *the_proxy;
185  ISR_lock_Context      lock_context;
186
187  _Thread_MP_Proxies_acquire( &lock_context );
188
189  the_proxy = _RBTree_Find_inline(
190    &_Thread_MP_Active_proxies,
191    &the_id,
192    _Thread_MP_Proxy_equal,
193    _Thread_MP_Proxy_less,
194    _Thread_MP_Proxy_map
195  );
196
197  _Thread_MP_Proxies_release( &lock_context );
198
199  return (Thread_Control *) the_proxy;
200}
201
202void _Thread_MP_Free_proxy( Thread_Control *the_thread )
203{
204  Thread_Proxy_control *the_proxy;
205  ISR_lock_Context      lock_context;
206
207  the_proxy = (Thread_Proxy_control *) the_thread;
208
209  _Thread_MP_Proxies_acquire( &lock_context );
210
211  _RBTree_Extract( &_Thread_MP_Active_proxies, &the_proxy->Active );
212  _Chain_Append_unprotected(
213    &_Thread_MP_Inactive_proxies,
214    &the_proxy->Object.Node
215  );
216
217  _Thread_MP_Proxies_release( &lock_context );
218}
Note: See TracBrowser for help on using the repository browser.