source: rtems/cpukit/score/src/threadmp.c @ 2afb22b

5
Last change on this file since 2afb22b was 3a659b04, checked in by Sebastian Huber <sebastian.huber@…>, on 12/09/16 at 06:19:22

score: Introduce _Internal_error()

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