source: rtems/cpukit/score/src/userextiterate.c @ 2548d14

5
Last change on this file since 2548d14 was 6f6da82c, checked in by Sebastian Huber <sebastian.huber@…>, on 01/26/17 at 10:06:50

score: Fix user extensions order

Use forward and reverse order for initial and dynamic extensions. This
is the behaviour documented in the C Users Guide. Change thread
terminate order to backward to be in line with the thread delete order.
Change fatal error order to forward to ensure that initial extensions
are called first due the peculiar execution context of fatal error
extensions, see _Terminate() documentation.

Update #2692.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/**
2 * @file
3 *
4 * @brief User Extension Iteration Helpers
5 *
6 * @ingroup ScoreUserExt
7 */
8
9/*
10 * Copyright (c) 2012, 2017 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#if HAVE_CONFIG_H
24  #include "config.h"
25#endif
26
27#include <rtems/config.h>
28#include <rtems/score/userextimpl.h>
29
30#include <pthread.h>
31
32User_extensions_List _User_extensions_List = {
33  CHAIN_INITIALIZER_EMPTY( _User_extensions_List.Active ),
34  CHAIN_ITERATOR_REGISTRY_INITIALIZER( _User_extensions_List.Iterators )
35#if defined(RTEMS_SMP)
36  ,
37  ISR_LOCK_INITIALIZER( "User Extensions List" )
38#endif
39};
40
41void _User_extensions_Thread_create_visitor(
42  Thread_Control              *executing,
43  void                        *arg,
44  const User_extensions_Table *callouts
45)
46{
47  User_extensions_thread_create_extension callout = callouts->thread_create;
48
49  if ( callout != NULL ) {
50    User_extensions_Thread_create_context *ctx = arg;
51
52    ctx->ok = ctx->ok && (*callout)( executing, ctx->created );
53  }
54}
55
56void _User_extensions_Thread_delete_visitor(
57  Thread_Control              *executing,
58  void                        *arg,
59  const User_extensions_Table *callouts
60)
61{
62  User_extensions_thread_delete_extension callout = callouts->thread_delete;
63
64  if ( callout != NULL ) {
65    (*callout)( executing, arg );
66  }
67}
68
69void _User_extensions_Thread_start_visitor(
70  Thread_Control              *executing,
71  void                        *arg,
72  const User_extensions_Table *callouts
73)
74{
75  User_extensions_thread_start_extension callout = callouts->thread_start;
76
77  if ( callout != NULL ) {
78    (*callout)( executing, arg );
79  }
80}
81
82void _User_extensions_Thread_restart_visitor(
83  Thread_Control              *executing,
84  void                        *arg,
85  const User_extensions_Table *callouts
86)
87{
88  User_extensions_thread_restart_extension callout = callouts->thread_restart;
89
90  if ( callout != NULL ) {
91    (*callout)( executing, arg );
92  }
93}
94
95void _User_extensions_Thread_begin_visitor(
96  Thread_Control              *executing,
97  void                        *arg,
98  const User_extensions_Table *callouts
99)
100{
101  User_extensions_thread_begin_extension callout = callouts->thread_begin;
102
103  if ( callout != NULL ) {
104    (*callout)( executing );
105  }
106}
107
108void _User_extensions_Thread_exitted_visitor(
109  Thread_Control              *executing,
110  void                        *arg,
111  const User_extensions_Table *callouts
112)
113{
114  User_extensions_thread_exitted_extension callout = callouts->thread_exitted;
115
116  if ( callout != NULL ) {
117    (*callout)( executing );
118  }
119}
120
121void _User_extensions_Fatal_visitor(
122  Thread_Control              *executing,
123  void                        *arg,
124  const User_extensions_Table *callouts
125)
126{
127  User_extensions_fatal_extension callout = callouts->fatal;
128
129  if ( callout != NULL ) {
130    const User_extensions_Fatal_context *ctx = arg;
131
132    (*callout)( ctx->source, false, ctx->error );
133  }
134}
135
136void _User_extensions_Thread_terminate_visitor(
137  Thread_Control              *executing,
138  void                        *arg,
139  const User_extensions_Table *callouts
140)
141{
142  User_extensions_thread_terminate_extension callout =
143    callouts->thread_terminate;
144
145  if ( callout != NULL ) {
146    (*callout)( executing );
147  }
148}
149
150void _User_extensions_Iterate(
151  void                     *arg,
152  User_extensions_Visitor   visitor,
153  Chain_Iterator_direction  direction
154)
155{
156  Thread_Control              *executing;
157  const User_extensions_Table *initial_current;
158  const User_extensions_Table *initial_begin;
159  const User_extensions_Table *initial_end;
160  const Chain_Node            *end;
161  Chain_Node                  *node;
162  User_extensions_Iterator     iter;
163  ISR_lock_Context             lock_context;
164
165  executing = _Thread_Get_executing();
166
167  initial_begin = rtems_configuration_get_user_extension_table();
168  initial_end =
169    initial_begin + rtems_configuration_get_number_of_initial_extensions();
170
171  if ( direction == CHAIN_ITERATOR_FORWARD ) {
172    initial_current = initial_begin;
173
174    while ( initial_current != initial_end ) {
175      (*visitor)( executing, arg, initial_current );
176      ++initial_current;
177    }
178
179    end = _Chain_Immutable_tail( &_User_extensions_List.Active );
180  } else {
181    end = _Chain_Immutable_head( &_User_extensions_List.Active );
182  }
183
184  _User_extensions_Acquire( &lock_context );
185
186  _Chain_Iterator_initialize(
187    &_User_extensions_List.Active,
188    &_User_extensions_List.Iterators,
189    &iter.Iterator,
190    direction
191  );
192
193  if ( executing != NULL ) {
194    iter.previous = executing->last_user_extensions_iterator;
195    executing->last_user_extensions_iterator = &iter;
196  }
197
198  while ( ( node = _Chain_Iterator_next( &iter.Iterator ) ) != end ) {
199    const User_extensions_Control *extension;
200
201    _Chain_Iterator_set_position( &iter.Iterator, node );
202
203    _User_extensions_Release( &lock_context );
204
205    extension = (const User_extensions_Control *) node;
206    ( *visitor )( executing, arg, &extension->Callouts );
207
208    _User_extensions_Acquire( &lock_context );
209  }
210
211  if ( executing != NULL ) {
212    executing->last_user_extensions_iterator = iter.previous;
213  }
214
215  _Chain_Iterator_destroy( &iter.Iterator );
216
217  _User_extensions_Release( &lock_context );
218
219  if ( direction == CHAIN_ITERATOR_BACKWARD ) {
220    initial_current = initial_end;
221
222    while ( initial_current != initial_begin ) {
223      --initial_current;
224      (*visitor)( executing, arg, initial_current );
225    }
226  }
227}
Note: See TracBrowser for help on using the repository browser.