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

4.11
Last change on this file since dc6bd8bb was dc6bd8bb, checked in by Sebastian Huber <sebastian.huber@…>, on 08/20/18 at 06:40:24

score: Fix ISR enable in _Thread_Dispatch_enable()

This bug had probably no effect since the interrupt enable is idempotent
on all CPU ports.

Close #3497.

  • Property mode set to 100644
File size: 9.5 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/isrlock.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 * @brief 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] lock_context The lock context of the corresponding
246 * _ISR_lock_ISR_disable() that started the critical section.
247 *
248 * @return The current processor.
249 */
250RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable_critical(
251  const ISR_lock_Context *lock_context
252)
253{
254  Per_CPU_Control *cpu_self;
255  uint32_t         disable_level;
256
257  cpu_self = _Per_CPU_Get();
258  disable_level = cpu_self->thread_dispatch_disable_level;
259  _Profiling_Thread_dispatch_disable_critical(
260    cpu_self,
261    disable_level,
262    lock_context
263  );
264  cpu_self->thread_dispatch_disable_level = disable_level + 1;
265
266  return cpu_self;
267}
268
269/**
270 * @brief Disables thread dispatching.
271 *
272 * This function does not acquire the Giant lock.
273 *
274 * @return The current processor.
275 */
276RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable( void )
277{
278  Per_CPU_Control  *cpu_self;
279  ISR_lock_Context  lock_context;
280
281#if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING )
282  _ISR_lock_ISR_disable( &lock_context );
283#endif
284
285  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
286
287#if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING )
288  _ISR_lock_ISR_enable( &lock_context );
289#endif
290
291  return cpu_self;
292}
293
294/**
295 * @brief Enables thread dispatching.
296 *
297 * May perfrom a thread dispatch if necessary as a side-effect.
298 *
299 * This function does not release the Giant lock.
300 *
301 * @param[in] cpu_self The current processor.
302 */
303RTEMS_INLINE_ROUTINE void _Thread_Dispatch_enable( Per_CPU_Control *cpu_self )
304{
305  uint32_t disable_level = cpu_self->thread_dispatch_disable_level;
306
307  if ( disable_level == 1 ) {
308    ISR_Level level;
309
310    _ISR_Disable_without_giant( level );
311
312    if ( cpu_self->dispatch_necessary ) {
313      _Thread_Do_dispatch( cpu_self, level );
314    } else {
315      cpu_self->thread_dispatch_disable_level = 0;
316      _Profiling_Thread_dispatch_enable( cpu_self, 0 );
317      _ISR_Enable_without_giant( level );
318    }
319  } else {
320    cpu_self->thread_dispatch_disable_level = disable_level - 1;
321  }
322}
323
324/**
325 * @brief Disables thread dispatching and acquires the Giant lock.
326 */
327#if defined ( __THREAD_DO_NOT_INLINE_DISABLE_DISPATCH__ )
328void _Thread_Disable_dispatch( void );
329#else
330RTEMS_INLINE_ROUTINE void _Thread_Disable_dispatch( void )
331{
332  _Thread_Dispatch_increment_disable_level();
333  RTEMS_COMPILER_MEMORY_BARRIER();
334}
335#endif
336
337RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch_body( void )
338{
339  Per_CPU_Control *cpu_self = _Per_CPU_Get();
340
341  _Giant_Release( cpu_self );
342  _Thread_Dispatch_enable( cpu_self );
343}
344
345/**
346 * @brief Enables thread dispatching and releases the Giant lock.
347 *
348 * May perfrom a thread dispatch if necessary as a side-effect.
349 */
350#if defined ( __THREAD_DO_NOT_INLINE_ENABLE_DISPATCH__ )
351  void _Thread_Enable_dispatch( void );
352#else
353  /* inlining of enable dispatching must be true */
354  RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch( void )
355  {
356    RTEMS_COMPILER_MEMORY_BARRIER();
357    _Thread_Enable_dispatch_body();
358  }
359#endif
360
361/**
362 * @brief Enables thread dispatching and releases the Giant lock.
363 *
364 * @warning A thread dispatch is not performed as a side-effect.  Use this
365 * function with
366 */
367RTEMS_INLINE_ROUTINE void _Thread_Unnest_dispatch( void )
368{
369  RTEMS_COMPILER_MEMORY_BARRIER();
370  _Thread_Dispatch_decrement_disable_level();
371}
372
373/** @} */
374
375#ifdef __cplusplus
376}
377#endif /* __cplusplus */
378
379#endif /* _RTEMS_SCORE_THREADDISPATCH_H */
Note: See TracBrowser for help on using the repository browser.