source: rtems/cpukit/include/rtems/score/userextimpl.h @ e97b7c9a

5
Last change on this file since e97b7c9a was e97b7c9a, checked in by Sebastian Huber <sebastian.huber@…>, on 04/11/19 at 11:47:50

score: Use an ISR lock for Per_CPU_Control::Lock

The use of a hand crafted lock for Per_CPU_Control::Lock was necessary
at some point in the SMP support development, but it is no longer
justified.

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