source: rtems/cpukit/score/src/userextiterate.c @ 25f5730f

4.115
Last change on this file since 25f5730f was 1b1be254, checked in by Sebastian Huber <sebastian.huber@…>, on 03/25/14 at 09:54:49

score: Thread life cycle re-implementation

The thread deletion is now supported on SMP.

This change fixes the following PRs:

PR1814: SMP race condition between stack free and dispatch

PR2035: psxcancel reveals NULL pointer access in _Thread_queue_Extract()

The POSIX cleanup handler are now called in the right context (should be
called in the context of the terminating thread).

http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html

Add a user extension the reflects a thread termination event. This is
used to reclaim the Newlib reentrancy structure (may use file
operations), the POSIX cleanup handlers and the POSIX key destructors.

  • Property mode set to 100644
File size: 4.1 KB
Line 
1/**
2 * @file
3 *
4 * @brief User Extension Iteration Helpers
5 *
6 * @ingroup ScoreUserExt
7 */
8
9/*
10 * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
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
30CHAIN_DEFINE_EMPTY( _User_extensions_List );
31
32void _User_extensions_Thread_create_visitor(
33  Thread_Control              *executing,
34  void                        *arg,
35  const User_extensions_Table *callouts
36)
37{
38  User_extensions_thread_create_extension callout = callouts->thread_create;
39
40  if ( callout != NULL ) {
41    User_extensions_Thread_create_context *ctx = arg;
42
43    ctx->ok = ctx->ok && (*callout)( executing, ctx->created );
44  }
45}
46
47void _User_extensions_Thread_delete_visitor(
48  Thread_Control              *executing,
49  void                        *arg,
50  const User_extensions_Table *callouts
51)
52{
53  User_extensions_thread_delete_extension callout = callouts->thread_delete;
54
55  if ( callout != NULL ) {
56    (*callout)( executing, arg );
57  }
58}
59
60void _User_extensions_Thread_start_visitor(
61  Thread_Control              *executing,
62  void                        *arg,
63  const User_extensions_Table *callouts
64)
65{
66  User_extensions_thread_start_extension callout = callouts->thread_start;
67
68  if ( callout != NULL ) {
69    (*callout)( executing, arg );
70  }
71}
72
73void _User_extensions_Thread_restart_visitor(
74  Thread_Control              *executing,
75  void                        *arg,
76  const User_extensions_Table *callouts
77)
78{
79  User_extensions_thread_restart_extension callout = callouts->thread_restart;
80
81  if ( callout != NULL ) {
82    (*callout)( executing, arg );
83  }
84}
85
86void _User_extensions_Thread_begin_visitor(
87  Thread_Control              *executing,
88  void                        *arg,
89  const User_extensions_Table *callouts
90)
91{
92  User_extensions_thread_begin_extension callout = callouts->thread_begin;
93
94  if ( callout != NULL ) {
95    (*callout)( executing );
96  }
97}
98
99void _User_extensions_Thread_exitted_visitor(
100  Thread_Control              *executing,
101  void                        *arg,
102  const User_extensions_Table *callouts
103)
104{
105  User_extensions_thread_exitted_extension callout = callouts->thread_exitted;
106
107  if ( callout != NULL ) {
108    (*callout)( executing );
109  }
110}
111
112void _User_extensions_Fatal_visitor(
113  Thread_Control              *executing,
114  void                        *arg,
115  const User_extensions_Table *callouts
116)
117{
118  User_extensions_fatal_extension callout = callouts->fatal;
119
120  if ( callout != NULL ) {
121    const User_extensions_Fatal_context *ctx = arg;
122
123    (*callout)( ctx->source, ctx->is_internal, ctx->error );
124  }
125}
126
127void _User_extensions_Thread_terminate_visitor(
128  Thread_Control              *executing,
129  void                        *arg,
130  const User_extensions_Table *callouts
131)
132{
133  User_extensions_thread_terminate_extension callout =
134    callouts->thread_terminate;
135
136  if ( callout != NULL ) {
137    (*callout)( executing );
138  }
139}
140
141void _User_extensions_Iterate(
142  void                    *arg,
143  User_extensions_Visitor  visitor
144)
145{
146  Thread_Control *executing = _Thread_Get_executing();
147  const User_extensions_Table *callouts_current =
148    rtems_configuration_get_user_extension_table();
149  const User_extensions_Table *callouts_end =
150    callouts_current + rtems_configuration_get_number_of_initial_extensions();
151  const Chain_Node *node;
152  const Chain_Node *tail;
153
154  while ( callouts_current != callouts_end ) {
155    (*visitor)( executing, arg, callouts_current );
156
157    ++callouts_current;
158  }
159
160  node = _Chain_Immutable_first( &_User_extensions_List );
161  tail = _Chain_Immutable_tail( &_User_extensions_List );
162  while ( node != tail ) {
163    const User_extensions_Control *extension =
164      (const User_extensions_Control *) node;
165
166    (*visitor)( executing, arg, &extension->Callouts );
167
168    node = _Chain_Immutable_next( node );
169  }
170}
Note: See TracBrowser for help on using the repository browser.