source: rtems/cpukit/score/include/rtems/score/threaddispatch.h @ 222dc775

4.115
Last change on this file since 222dc775 was 222dc775, checked in by Sebastian Huber <sebastian.huber@…>, on 02/26/15 at 09:32:08

score: Add and use _Thread_Do_dispatch()

The _Thread_Dispatch() function is quite complex and the time to set up
and tear down the stack frame is significant. Split this function into
two parts. The complex part is now in _Thread_Do_dispatch(). Call
_Thread_Do_dispatch() in _Thread_Enable_dispatch() only if necessary.
This increases the average case performance.

Simplify _Thread_Handler() for SMP configurations.

Update #2273.

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/**
2 * @brief Constants and Structures Related with Thread Dispatch
3 */
4
5/*
6 * COPYRIGHT (c) 1989-2009.
7 * On-Line Applications Research Corporation (OAR).
8 *
9 * The license and distribution terms for this file may be
10 * found in the file LICENSE in this distribution or at
11 * http://www.rtems.org/license/LICENSE.
12 */
13
14#ifndef _RTEMS_SCORE_THREADDISPATCH_H
15#define _RTEMS_SCORE_THREADDISPATCH_H
16
17#include <rtems/score/percpu.h>
18#include <rtems/score/smplock.h>
19#include <rtems/score/profiling.h>
20
21#ifdef __cplusplus
22extern "C" {
23#endif /* __cplusplus */
24
25#if defined(RTEMS_HEAVY_STACK_DEBUG) || \
26    defined(RTEMS_HEAVY_MALLOC_DEBUG)
27  #define __THREAD_DO_NOT_INLINE_DISABLE_DISPATCH__
28#endif
29
30#if defined(RTEMS_SMP) || \
31   (CPU_INLINE_ENABLE_DISPATCH == FALSE) || \
32   (__RTEMS_DO_NOT_INLINE_THREAD_ENABLE_DISPATCH__ == 1)
33  #define __THREAD_DO_NOT_INLINE_ENABLE_DISPATCH__
34#endif
35
36/**
37 * @addtogroup ScoreThread
38 *
39 * @{
40 */
41
42/**
43 * @brief Indicates if the executing thread is inside a thread dispatch
44 * critical section.
45 *
46 * @retval true Thread dispatching is enabled.
47 * @retval false The executing thread is inside a thread dispatch critical
48 * section and dispatching is not allowed.
49 */
50RTEMS_INLINE_ROUTINE bool _Thread_Dispatch_is_enabled(void)
51{
52  bool enabled;
53
54#if defined(RTEMS_SMP)
55  ISR_Level level;
56
57  _ISR_Disable_without_giant( level );
58#endif
59
60  enabled = _Thread_Dispatch_disable_level == 0;
61
62#if defined(RTEMS_SMP)
63  _ISR_Enable_without_giant( level );
64#endif
65
66  return enabled;
67}
68
69/**
70 * @briefs Gets thread dispatch disable level.
71 *
72 * @return The value of the thread dispatch level.
73 */
74RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_get_disable_level(void)
75{
76  return _Thread_Dispatch_disable_level;
77}
78
79/**
80 * @brief Thread dispatch initialization.
81 *
82 * This routine initializes the thread dispatching subsystem.
83 */
84RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void )
85{
86  _Thread_Dispatch_disable_level = 1;
87}
88
89#if defined(RTEMS_SMP)
90  /**
91   * @brief Acquires the giant lock.
92   *
93   * The giant lock is a recursive SMP lock protecting nearly all operating
94   * system services.
95   *
96   * This lock is implicitly acquired in
97   * _Thread_Dispatch_increment_disable_level().
98   *
99   * Thread dispatching must be disabled before the Giant lock can be acquired
100   * and must no be enabled while owning the Giant lock.  The thread dispatch
101   * disable level is not altered by this function.
102   *
103   * @param[in] cpu_self The current processor.
104   */
105  void _Giant_Acquire( Per_CPU_Control *cpu_self );
106
107  /**
108   * @brief Releases the giant lock.
109   *
110   * This lock is implicitly released in
111   * _Thread_Dispatch_decrement_disable_level().
112   *
113   * The thread dispatch disable level is not altered by this function.
114   *
115   * @param[in] cpu_self The current processor.
116   */
117  void _Giant_Release( Per_CPU_Control *cpu_self );
118
119  /**
120   * @brief Releases the giant lock completely if held by the executing processor.
121   *
122   * The thread dispatch disable level is not altered by this function.
123   *
124   * The only use case for this operation is in _SMP_Request_shutdown().
125   *
126   * @param[in] cpu_self The current processor.
127   */
128  void _Giant_Drop( Per_CPU_Control *cpu_self );
129
130  /**
131   *  @brief Increments the thread dispatch level.
132   *
133   * This rountine increments the thread dispatch level
134   */
135  uint32_t _Thread_Dispatch_increment_disable_level(void);
136
137  /**
138   *  @brief Decrements the thread dispatch level.
139   *
140   * This routine decrements the thread dispatch level.
141   */
142  uint32_t _Thread_Dispatch_decrement_disable_level(void);
143#else /* RTEMS_SMP */
144  /**
145   * @brief Increase thread dispatch disable level.
146   *
147   * This rountine increments the thread dispatch level
148   */
149  RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_increment_disable_level(void)
150  {
151    uint32_t disable_level = _Thread_Dispatch_disable_level;
152#if defined( RTEMS_PROFILING )
153    ISR_Level level;
154
155    _ISR_Disable( level );
156    _Profiling_Thread_dispatch_disable( _Per_CPU_Get(), disable_level );
157#endif
158
159    ++disable_level;
160    _Thread_Dispatch_disable_level = disable_level;
161
162#if defined( RTEMS_PROFILING )
163    _ISR_Enable( level );
164#endif
165
166    return disable_level;
167  }
168
169  /**
170   * @brief Decrease thread dispatch disable level.
171   *
172   * This routine decrements the thread dispatch level.
173   */
174  RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_decrement_disable_level(void)
175  {
176    uint32_t disable_level = _Thread_Dispatch_disable_level;
177#if defined( RTEMS_PROFILING )
178    ISR_Level level;
179
180    _ISR_Disable( level );
181#endif
182
183    --disable_level;
184    _Thread_Dispatch_disable_level = disable_level;
185
186#if defined( RTEMS_PROFILING )
187    _Profiling_Thread_dispatch_enable( _Per_CPU_Get(), disable_level );
188    _ISR_Enable( level );
189#endif
190
191    return disable_level;
192  }
193#endif /* RTEMS_SMP */
194
195/**
196 * @brief Performs a thread dispatch if necessary.
197 *
198 * This routine is responsible for transferring control of the processor from
199 * the executing thread to the heir thread.  Once the heir is running an
200 * attempt is made to run the pending post-switch thread actions.
201 *
202 * As part of this process, it is responsible for the following actions
203 *   - update timing information of the executing thread,
204 *   - save the context of the executing thread,
205 *   - invokation of the thread switch user extensions,
206 *   - restore the context of the heir thread, and
207 *   - run of pending post-switch thread actions of the resulting executing
208 *     thread.
209 *
210 * On entry the thread dispatch level must be equal to zero.
211 */
212void _Thread_Dispatch( void );
213
214/**
215 * @brief Performs a thread dispatch on the current processor.
216 *
217 * On entry the thread dispatch disable level must be equal to one and
218 * interrupts must be disabled.
219 *
220 * This function assumes that a thread dispatch is necessary.
221 *
222 * @param[in] cpu_self The current processor.
223 * @param[in] level The previous interrupt level.
224 *
225 * @see _Thread_Dispatch().
226 */
227void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level );
228
229/**
230 * This routine prevents dispatching.
231 */
232
233#if defined ( __THREAD_DO_NOT_INLINE_DISABLE_DISPATCH__ )
234void _Thread_Disable_dispatch( void );
235#else
236RTEMS_INLINE_ROUTINE void _Thread_Disable_dispatch( void )
237{
238  _Thread_Dispatch_increment_disable_level();
239  RTEMS_COMPILER_MEMORY_BARRIER();
240}
241#endif
242
243RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch_body( void )
244{
245  Per_CPU_Control *cpu_self;
246  uint32_t         disable_level;
247
248  cpu_self = _Per_CPU_Get();
249
250#if defined( RTEMS_SMP )
251  _Giant_Release( cpu_self );
252#endif
253
254  disable_level = cpu_self->thread_dispatch_disable_level;
255
256  if ( disable_level == 1 ) {
257    ISR_Level level;
258
259    _ISR_Disable_without_giant( level );
260
261    if ( cpu_self->dispatch_necessary ) {
262      _Thread_Do_dispatch( cpu_self, level );
263    } else {
264      cpu_self->thread_dispatch_disable_level = 0;
265      _Profiling_Thread_dispatch_enable( cpu_self, 0 );
266    }
267
268    _ISR_Enable_without_giant( level );
269  } else {
270    cpu_self->thread_dispatch_disable_level = disable_level - 1;
271  }
272}
273
274/**
275 * This routine allows dispatching to occur again.  If this is
276 * the outer most dispatching critical section, then a dispatching
277 * operation will be performed and, if necessary, control of the
278 * processor will be transferred to the heir thread.
279 */
280
281#if defined ( __THREAD_DO_NOT_INLINE_ENABLE_DISPATCH__ )
282  void _Thread_Enable_dispatch( void );
283#else
284  /* inlining of enable dispatching must be true */
285  RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch( void )
286  {
287    RTEMS_COMPILER_MEMORY_BARRIER();
288    _Thread_Enable_dispatch_body();
289  }
290#endif
291
292/**
293 * This routine allows dispatching to occur again.  However,
294 * no dispatching operation is performed even if this is the outer
295 * most dispatching critical section.
296 */
297
298RTEMS_INLINE_ROUTINE void _Thread_Unnest_dispatch( void )
299{
300  RTEMS_COMPILER_MEMORY_BARRIER();
301  _Thread_Dispatch_decrement_disable_level();
302}
303
304/** @} */
305
306#ifdef __cplusplus
307}
308#endif /* __cplusplus */
309
310#endif /* _RTEMS_SCORE_THREADDISPATCH_H */
Note: See TracBrowser for help on using the repository browser.