source: rtems/cpukit/include/rtems/score/userextimpl.h @ 21275b58

Last change on this file since 21275b58 was 963c6c2, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 12, 2018 at 8:28:49 AM

score: Move internal structures to userextdata.h

Update #3598.

  • Property mode set to 100644
File size: 8.2 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/userextdata.h>
22#include <rtems/score/chainimpl.h>
23#include <rtems/score/isrlock.h>
24#include <rtems/score/thread.h>
25#include <rtems/score/percpu.h>
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31/**
32 * @defgroup ScoreUserExt User Extension Handler
33 *
34 * @ingroup Score
35 *
36 * @addtogroup ScoreUserExt
37 */
38/**@{**/
39
40/**
41 * @brief Chain iterator for dynamic user extensions.
42 *
43 * Since user extensions may delete or restart the executing thread, we must
44 * clean up registered iterators.
45 *
46 * @see _User_extensions_Iterate(), _User_extensions_Destroy_iterators() and
47 *   Thread_Control::last_user_extensions_iterator.
48 */
49typedef struct User_extensions_Iterator {
50  Chain_Iterator                   Iterator;
51  struct User_extensions_Iterator *previous;
52} User_extensions_Iterator;
53
54typedef struct {
55  /**
56   * @brief Active dynamically added user extensions.
57   */
58  Chain_Control Active;
59
60  /**
61   * @brief Chain iterator registration.
62   */
63  Chain_Iterator_registry Iterators;
64
65  /**
66   * @brief Lock to protect User_extensions_List::Active and
67   * User_extensions_List::Iterators.
68   */
69  ISR_LOCK_MEMBER( Lock )
70} User_extensions_List;
71
72/**
73 * @brief List of active extensions.
74 */
75extern User_extensions_List _User_extensions_List;
76
77/**
78 * @brief List of active task switch extensions.
79 */
80extern Chain_Control _User_extensions_Switches_list;
81
82/**
83 * @name Extension Maintainance
84 */
85/**@{**/
86
87void _User_extensions_Handler_initialization( void );
88
89void _User_extensions_Add_set(
90  User_extensions_Control *extension
91);
92
93RTEMS_INLINE_ROUTINE void _User_extensions_Add_API_set(
94  User_extensions_Control *extension
95)
96{
97  _User_extensions_Add_set( extension );
98}
99
100RTEMS_INLINE_ROUTINE void _User_extensions_Add_set_with_table(
101  User_extensions_Control     *extension,
102  const User_extensions_Table *extension_table
103)
104{
105  extension->Callouts = *extension_table;
106
107  _User_extensions_Add_set( extension );
108}
109
110void _User_extensions_Remove_set(
111  User_extensions_Control *extension
112);
113
114/**
115 * @brief User extension visitor.
116 *
117 * @param[in, out] executing The currently executing thread.
118 * @param[in, out] arg The argument passed to _User_extensions_Iterate().
119 * @param[in] callouts The current callouts.
120 */
121typedef void (*User_extensions_Visitor)(
122  Thread_Control              *executing,
123  void                        *arg,
124  const User_extensions_Table *callouts
125);
126
127typedef struct {
128  Thread_Control *created;
129  bool            ok;
130} User_extensions_Thread_create_context;
131
132void _User_extensions_Thread_create_visitor(
133  Thread_Control              *executing,
134  void                        *arg,
135  const User_extensions_Table *callouts
136);
137
138void _User_extensions_Thread_delete_visitor(
139  Thread_Control              *executing,
140  void                        *arg,
141  const User_extensions_Table *callouts
142);
143
144void _User_extensions_Thread_start_visitor(
145  Thread_Control              *executing,
146  void                        *arg,
147  const User_extensions_Table *callouts
148);
149
150void _User_extensions_Thread_restart_visitor(
151  Thread_Control              *executing,
152  void                        *arg,
153  const User_extensions_Table *callouts
154);
155
156void _User_extensions_Thread_begin_visitor(
157  Thread_Control              *executing,
158  void                        *arg,
159  const User_extensions_Table *callouts
160);
161
162void _User_extensions_Thread_exitted_visitor(
163  Thread_Control              *executing,
164  void                        *arg,
165  const User_extensions_Table *callouts
166);
167
168typedef struct {
169  Internal_errors_Source source;
170  Internal_errors_t      error;
171} User_extensions_Fatal_context;
172
173void _User_extensions_Fatal_visitor(
174  Thread_Control              *executing,
175  void                        *arg,
176  const User_extensions_Table *callouts
177);
178
179void _User_extensions_Thread_terminate_visitor(
180  Thread_Control              *executing,
181  void                        *arg,
182  const User_extensions_Table *callouts
183);
184
185/**
186 * @brief Iterates through all user extensions and calls the visitor for each.
187 *
188 * @param[in, out] arg The argument passed to the visitor.
189 * @param[in] visitor The visitor for each extension.
190 * @param[in] direction The iteration direction for dynamic extensions.
191 */
192void _User_extensions_Iterate(
193  void                     *arg,
194  User_extensions_Visitor   visitor,
195  Chain_Iterator_direction  direction
196);
197
198/** @} */
199
200/**
201 * @name Extension Callout Dispatcher
202 */
203/**@{**/
204
205static inline bool _User_extensions_Thread_create( Thread_Control *created )
206{
207  User_extensions_Thread_create_context ctx = { created, true };
208
209  _User_extensions_Iterate(
210    &ctx,
211    _User_extensions_Thread_create_visitor,
212    CHAIN_ITERATOR_FORWARD
213  );
214
215  return ctx.ok;
216}
217
218static inline void _User_extensions_Thread_delete( Thread_Control *deleted )
219{
220  _User_extensions_Iterate(
221    deleted,
222    _User_extensions_Thread_delete_visitor,
223    CHAIN_ITERATOR_BACKWARD
224  );
225}
226
227static inline void _User_extensions_Thread_start( Thread_Control *started )
228{
229  _User_extensions_Iterate(
230    started,
231    _User_extensions_Thread_start_visitor,
232    CHAIN_ITERATOR_FORWARD
233  );
234}
235
236static inline void _User_extensions_Thread_restart( Thread_Control *restarted )
237{
238  _User_extensions_Iterate(
239    restarted,
240    _User_extensions_Thread_restart_visitor,
241    CHAIN_ITERATOR_FORWARD
242  );
243}
244
245static inline void _User_extensions_Thread_begin( Thread_Control *executing )
246{
247  _User_extensions_Iterate(
248    executing,
249    _User_extensions_Thread_begin_visitor,
250    CHAIN_ITERATOR_FORWARD
251  );
252}
253
254static inline void _User_extensions_Thread_switch(
255  Thread_Control *executing,
256  Thread_Control *heir
257)
258{
259  const Chain_Control *chain = &_User_extensions_Switches_list;
260  const Chain_Node    *tail = _Chain_Immutable_tail( chain );
261  const Chain_Node    *node = _Chain_Immutable_first( chain );
262
263  if ( node != tail ) {
264    Per_CPU_Control *cpu_self;
265#if defined(RTEMS_SMP)
266    ISR_Level        level;
267#endif
268
269    cpu_self = _Per_CPU_Get();
270
271#if defined(RTEMS_SMP)
272    _ISR_Local_disable( level );
273#endif
274    _Per_CPU_Acquire( cpu_self );
275
276    while ( node != tail ) {
277      const User_extensions_Switch_control *extension =
278        (const User_extensions_Switch_control *) node;
279
280      (*extension->thread_switch)( executing, heir );
281
282      node = _Chain_Immutable_next( node );
283    }
284
285    _Per_CPU_Release( cpu_self );
286#if defined(RTEMS_SMP)
287    _ISR_Local_enable( level );
288#endif
289  }
290}
291
292static inline void _User_extensions_Thread_exitted( Thread_Control *executing )
293{
294  _User_extensions_Iterate(
295    executing,
296    _User_extensions_Thread_exitted_visitor,
297    CHAIN_ITERATOR_FORWARD
298  );
299}
300
301static inline void _User_extensions_Fatal(
302  Internal_errors_Source source,
303  Internal_errors_t      error
304)
305{
306  User_extensions_Fatal_context ctx = { source, error };
307
308  _User_extensions_Iterate(
309    &ctx,
310    _User_extensions_Fatal_visitor,
311    CHAIN_ITERATOR_FORWARD
312  );
313}
314
315static inline void _User_extensions_Thread_terminate(
316  Thread_Control *executing
317)
318{
319  _User_extensions_Iterate(
320    executing,
321    _User_extensions_Thread_terminate_visitor,
322    CHAIN_ITERATOR_BACKWARD
323  );
324}
325
326static inline void _User_extensions_Acquire( ISR_lock_Context *lock_context )
327{
328  _ISR_lock_ISR_disable_and_acquire(
329    &_User_extensions_List.Lock,
330    lock_context
331  );
332}
333
334static inline void _User_extensions_Release( ISR_lock_Context *lock_context )
335{
336  _ISR_lock_Release_and_ISR_enable(
337    &_User_extensions_List.Lock,
338    lock_context
339  );
340}
341
342static inline void _User_extensions_Destroy_iterators(
343  Thread_Control *the_thread
344)
345{
346  ISR_lock_Context          lock_context;
347  User_extensions_Iterator *iter;
348
349  _User_extensions_Acquire( &lock_context );
350
351  iter = the_thread->last_user_extensions_iterator;
352
353  while ( iter != NULL ) {
354    _Chain_Iterator_destroy( &iter->Iterator );
355    iter = iter->previous;
356  }
357
358  _User_extensions_Release( &lock_context );
359}
360
361/** @} */
362
363/** @} */
364
365#ifdef __cplusplus
366}
367#endif
368
369#endif
370/* end of include file */
Note: See TracBrowser for help on using the repository browser.