source: rtems/cpukit/score/include/rtems/score/userextimpl.h @ 89f8eab5

4.115
Last change on this file since 89f8eab5 was 38b59a6, checked in by Sebastian Huber <sebastian.huber@…>, on 05/02/14 at 08:31:09

score: Implement forced thread migration

The current implementation of task migration in RTEMS has some
implications with respect to the interrupt latency. It is crucial to
preserve the system invariant that a task can execute on at most one
processor in the system at a time. This is accomplished with a boolean
indicator in the task context. The processor architecture specific
low-level task context switch code will mark that a task context is no
longer executing and waits that the heir context stopped execution
before it restores the heir context and resumes execution of the heir
task. So there is one point in time in which a processor is without a
task. This is essential to avoid cyclic dependencies in case multiple
tasks migrate at once. Otherwise some supervising entity is necessary to
prevent life-locks. Such a global supervisor would lead to scalability
problems so this approach is not used. Currently the thread dispatch is
performed with interrupts disabled. So in case the heir task is
currently executing on another processor then this prolongs the time of
disabled interrupts since one processor has to wait for another
processor to make progress.

It is difficult to avoid this issue with the interrupt latency since
interrupts normally store the context of the interrupted task on its
stack. In case a task is marked as not executing we must not use its
task stack to store such an interrupt context. We cannot use the heir
stack before it stopped execution on another processor. So if we enable
interrupts during this transition we have to provide an alternative task
independent stack for this time frame. This issue needs further
investigation.

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreUserExt
5 *
6 * @brief User Extension Handler API
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2009.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#ifndef _RTEMS_SCORE_USEREXTIMPL_H
19#define _RTEMS_SCORE_USEREXTIMPL_H
20
21#include <rtems/score/userext.h>
22#include <rtems/score/chainimpl.h>
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28/**
29 * @defgroup ScoreUserExt User Extension Handler
30 *
31 * @ingroup Score
32 *
33 * @addtogroup ScoreUserExt
34 */
35/**@{**/
36
37/**
38 * @brief List of active extensions.
39 */
40extern Chain_Control _User_extensions_List;
41
42/**
43 * @brief List of active task switch extensions.
44 */
45extern Chain_Control _User_extensions_Switches_list;
46
47/**
48 * @name Extension Maintainance
49 */
50/**@{**/
51
52void _User_extensions_Handler_initialization( void );
53
54void _User_extensions_Add_set(
55  User_extensions_Control *extension
56);
57
58RTEMS_INLINE_ROUTINE void _User_extensions_Add_API_set(
59  User_extensions_Control *extension
60)
61{
62  _User_extensions_Add_set( extension );
63}
64
65RTEMS_INLINE_ROUTINE void _User_extensions_Add_set_with_table(
66  User_extensions_Control     *extension,
67  const User_extensions_Table *extension_table
68)
69{
70  extension->Callouts = *extension_table;
71
72  _User_extensions_Add_set( extension );
73}
74
75void _User_extensions_Remove_set(
76  User_extensions_Control *extension
77);
78
79/**
80 * @brief User extension visitor.
81 *
82 * @param[in, out] executing The currently executing thread.
83 * @param[in, out] arg The argument passed to _User_extensions_Iterate().
84 * @param[in] callouts The current callouts.
85 */
86typedef void (*User_extensions_Visitor)(
87  Thread_Control              *executing,
88  void                        *arg,
89  const User_extensions_Table *callouts
90);
91
92typedef struct {
93  Thread_Control *created;
94  bool            ok;
95} User_extensions_Thread_create_context;
96
97void _User_extensions_Thread_create_visitor(
98  Thread_Control              *executing,
99  void                        *arg,
100  const User_extensions_Table *callouts
101);
102
103void _User_extensions_Thread_delete_visitor(
104  Thread_Control              *executing,
105  void                        *arg,
106  const User_extensions_Table *callouts
107);
108
109void _User_extensions_Thread_start_visitor(
110  Thread_Control              *executing,
111  void                        *arg,
112  const User_extensions_Table *callouts
113);
114
115void _User_extensions_Thread_restart_visitor(
116  Thread_Control              *executing,
117  void                        *arg,
118  const User_extensions_Table *callouts
119);
120
121void _User_extensions_Thread_begin_visitor(
122  Thread_Control              *executing,
123  void                        *arg,
124  const User_extensions_Table *callouts
125);
126
127void _User_extensions_Thread_exitted_visitor(
128  Thread_Control              *executing,
129  void                        *arg,
130  const User_extensions_Table *callouts
131);
132
133typedef struct {
134  Internal_errors_Source source;
135  bool                   is_internal;
136  Internal_errors_t      error;
137} User_extensions_Fatal_context;
138
139void _User_extensions_Fatal_visitor(
140  Thread_Control              *executing,
141  void                        *arg,
142  const User_extensions_Table *callouts
143);
144
145void _User_extensions_Thread_terminate_visitor(
146  Thread_Control              *executing,
147  void                        *arg,
148  const User_extensions_Table *callouts
149);
150
151/**
152 * @brief Iterates through all user extensions and calls the visitor for each.
153 *
154 * @param[in, out] arg The argument passed to the visitor.
155 * @param[in] visitor is the visitor for each extension.
156 */
157void _User_extensions_Iterate(
158  void                    *arg,
159  User_extensions_Visitor  visitor
160);
161
162/** @} */
163
164/**
165 * @name Extension Callout Dispatcher
166 */
167/**@{**/
168
169static inline bool _User_extensions_Thread_create( Thread_Control *created )
170{
171  User_extensions_Thread_create_context ctx = { created, true };
172
173  _User_extensions_Iterate( &ctx, _User_extensions_Thread_create_visitor );
174
175  return ctx.ok;
176}
177
178static inline void _User_extensions_Thread_delete( Thread_Control *deleted )
179{
180  _User_extensions_Iterate(
181    deleted,
182    _User_extensions_Thread_delete_visitor
183  );
184}
185
186static inline void _User_extensions_Thread_start( Thread_Control *started )
187{
188  _User_extensions_Iterate(
189    started,
190    _User_extensions_Thread_start_visitor
191  );
192}
193
194static inline void _User_extensions_Thread_restart( Thread_Control *restarted )
195{
196  _User_extensions_Iterate(
197    restarted,
198    _User_extensions_Thread_restart_visitor
199  );
200}
201
202static inline void _User_extensions_Thread_begin( Thread_Control *executing )
203{
204  _User_extensions_Iterate(
205    executing,
206    _User_extensions_Thread_begin_visitor
207  );
208}
209
210static inline void _User_extensions_Thread_switch(
211  Thread_Control *executing,
212  Thread_Control *heir
213)
214{
215  const Chain_Control *chain = &_User_extensions_Switches_list;
216  const Chain_Node    *tail = _Chain_Immutable_tail( chain );
217  const Chain_Node    *node = _Chain_Immutable_first( chain );
218
219  if ( node != tail ) {
220    Per_CPU_Control *cpu_self = _Per_CPU_Get();
221
222    _Per_CPU_Acquire( cpu_self );
223
224    while ( node != tail ) {
225      const User_extensions_Switch_control *extension =
226        (const User_extensions_Switch_control *) node;
227
228      (*extension->thread_switch)( executing, heir );
229
230      node = _Chain_Immutable_next( node );
231    }
232
233    _Per_CPU_Release( cpu_self );
234  }
235}
236
237static inline void _User_extensions_Thread_exitted( Thread_Control *executing )
238{
239  _User_extensions_Iterate(
240    executing,
241    _User_extensions_Thread_exitted_visitor
242  );
243}
244
245static inline void _User_extensions_Fatal(
246  Internal_errors_Source source,
247  bool                   is_internal,
248  Internal_errors_t      error
249)
250{
251  User_extensions_Fatal_context ctx = { source, is_internal, error };
252
253  _User_extensions_Iterate( &ctx, _User_extensions_Fatal_visitor );
254}
255
256static inline void _User_extensions_Thread_terminate(
257  Thread_Control *executing
258)
259{
260  _User_extensions_Iterate(
261    executing,
262    _User_extensions_Thread_terminate_visitor
263  );
264}
265
266/** @} */
267
268/** @} */
269
270#ifdef __cplusplus
271}
272#endif
273
274#endif
275/* end of include file */
Note: See TracBrowser for help on using the repository browser.