source: rtems/cpukit/score/include/rtems/score/threaddispatch.h @ 1512761

4.115
Last change on this file since 1512761 was 1512761, checked in by Sebastian Huber <sebastian.huber@…>, on 02/28/15 at 16:24:52

score: Thread dispatch dis/enable without Giant

Update #2273.

  • Property mode set to 100644
File size: 9.2 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
194  RTEMS_INLINE_ROUTINE void _Giant_Acquire( Per_CPU_Control *cpu_self )
195  {
196    (void) cpu_self;
197  }
198
199  RTEMS_INLINE_ROUTINE void _Giant_Release( Per_CPU_Control *cpu_self )
200  {
201    (void) cpu_self;
202  }
203#endif /* RTEMS_SMP */
204
205/**
206 * @brief Performs a thread dispatch if necessary.
207 *
208 * This routine is responsible for transferring control of the processor from
209 * the executing thread to the heir thread.  Once the heir is running an
210 * attempt is made to run the pending post-switch thread actions.
211 *
212 * As part of this process, it is responsible for the following actions
213 *   - update timing information of the executing thread,
214 *   - save the context of the executing thread,
215 *   - invokation of the thread switch user extensions,
216 *   - restore the context of the heir thread, and
217 *   - run of pending post-switch thread actions of the resulting executing
218 *     thread.
219 *
220 * On entry the thread dispatch level must be equal to zero.
221 */
222void _Thread_Dispatch( void );
223
224/**
225 * @brief Performs a thread dispatch on the current processor.
226 *
227 * On entry the thread dispatch disable level must be equal to one and
228 * interrupts must be disabled.
229 *
230 * This function assumes that a thread dispatch is necessary.
231 *
232 * @param[in] cpu_self The current processor.
233 * @param[in] level The previous interrupt level.
234 *
235 * @see _Thread_Dispatch().
236 */
237void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level );
238
239/**
240 * @brief Disables thread dispatching inside a critical section (interrupts
241 * disabled).
242 *
243 * This function does not acquire the Giant lock.
244 *
245 * @param[in] cpu_self The current processor.
246 */
247RTEMS_INLINE_ROUTINE void _Thread_Dispatch_disable_critical(
248  Per_CPU_Control *cpu_self
249)
250{
251  uint32_t disable_level = cpu_self->thread_dispatch_disable_level;
252
253  _Profiling_Thread_dispatch_disable( cpu_self, disable_level );
254  cpu_self->thread_dispatch_disable_level = disable_level + 1;
255}
256
257/**
258 * @brief Disables thread dispatching.
259 *
260 * This function does not acquire the Giant lock.
261 *
262 * @return The current processor.
263 */
264RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable( void )
265{
266  Per_CPU_Control *cpu_self;
267
268#if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING )
269  ISR_Level level;
270
271  _ISR_Disable_without_giant( level );
272#endif
273
274  cpu_self = _Per_CPU_Get();
275  _Thread_Dispatch_disable_critical( cpu_self );
276
277#if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING )
278  _ISR_Enable_without_giant( level );
279#endif
280
281  return cpu_self;
282}
283
284/**
285 * @brief Enables thread dispatching.
286 *
287 * May perfrom a thread dispatch if necessary as a side-effect.
288 *
289 * This function does not release the Giant lock.
290 *
291 * @param[in] cpu_self The current processor.
292 */
293RTEMS_INLINE_ROUTINE void _Thread_Dispatch_enable( Per_CPU_Control *cpu_self )
294{
295  uint32_t disable_level = cpu_self->thread_dispatch_disable_level;
296
297  if ( disable_level == 1 ) {
298    ISR_Level level;
299
300    _ISR_Disable_without_giant( level );
301
302    if ( cpu_self->dispatch_necessary ) {
303      _Thread_Do_dispatch( cpu_self, level );
304    } else {
305      cpu_self->thread_dispatch_disable_level = 0;
306      _Profiling_Thread_dispatch_enable( cpu_self, 0 );
307    }
308
309    _ISR_Enable_without_giant( level );
310  } else {
311    cpu_self->thread_dispatch_disable_level = disable_level - 1;
312  }
313}
314
315/**
316 * @brief Disables thread dispatching and acquires the Giant lock.
317 */
318#if defined ( __THREAD_DO_NOT_INLINE_DISABLE_DISPATCH__ )
319void _Thread_Disable_dispatch( void );
320#else
321RTEMS_INLINE_ROUTINE void _Thread_Disable_dispatch( void )
322{
323  _Thread_Dispatch_increment_disable_level();
324  RTEMS_COMPILER_MEMORY_BARRIER();
325}
326#endif
327
328RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch_body( void )
329{
330  Per_CPU_Control *cpu_self = _Per_CPU_Get();
331
332  _Giant_Release( cpu_self );
333  _Thread_Dispatch_enable( cpu_self );
334}
335
336/**
337 * @brief Enables thread dispatching and releases the Giant lock.
338 *
339 * May perfrom a thread dispatch if necessary as a side-effect.
340 */
341#if defined ( __THREAD_DO_NOT_INLINE_ENABLE_DISPATCH__ )
342  void _Thread_Enable_dispatch( void );
343#else
344  /* inlining of enable dispatching must be true */
345  RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch( void )
346  {
347    RTEMS_COMPILER_MEMORY_BARRIER();
348    _Thread_Enable_dispatch_body();
349  }
350#endif
351
352/**
353 * @brief Enables thread dispatching and releases the Giant lock.
354 *
355 * @warning A thread dispatch is not performed as a side-effect.  Use this
356 * function with
357 */
358RTEMS_INLINE_ROUTINE void _Thread_Unnest_dispatch( void )
359{
360  RTEMS_COMPILER_MEMORY_BARRIER();
361  _Thread_Dispatch_decrement_disable_level();
362}
363
364/** @} */
365
366#ifdef __cplusplus
367}
368#endif /* __cplusplus */
369
370#endif /* _RTEMS_SCORE_THREADDISPATCH_H */
Note: See TracBrowser for help on using the repository browser.