source: rtems/cpukit/include/rtems/score/threadimpl.h @ f74e806d

5
Last change on this file since f74e806d was f74e806d, checked in by Sebastian Huber <sebastian.huber@…>, on 01/02/20 at 10:30:33

mpci: Fix blocking proxy status

Remove THREAD_STATUS_PROXY_BLOCKING and replace it with
STATUS_PROXY_BLOCKING.

  • Property mode set to 100644
File size: 68.7 KB
RevLine 
[5618c37a]1/**
2 * @file
3 *
[3657cde]4 * @ingroup RTEMSScoreThread
5 *
[5618c37a]6 * @brief Inlined Routines from the Thread Handler
7 *
8 * This file contains the macro implementation of the inlined
9 * routines from the Thread handler.
10 */
11
12/*
13 *  COPYRIGHT (c) 1989-2008.
14 *  On-Line Applications Research Corporation (OAR).
15 *
[7ced9d9b]16 *  Copyright (c) 2014, 2017 embedded brains GmbH.
[1b1be254]17 *
[5618c37a]18 *  The license and distribution terms for this file may be
19 *  found in the file LICENSE in this distribution or at
[c499856]20 *  http://www.rtems.org/license/LICENSE.
[5618c37a]21 */
22
23#ifndef _RTEMS_SCORE_THREADIMPL_H
24#define _RTEMS_SCORE_THREADIMPL_H
25
26#include <rtems/score/thread.h>
[1041de1]27#include <rtems/score/assert.h>
[0dd732d]28#include <rtems/score/chainimpl.h>
[514705d]29#include <rtems/score/interr.h>
[6c0e43d]30#include <rtems/score/isr.h>
[a2e3f33]31#include <rtems/score/objectimpl.h>
[52a661e8]32#include <rtems/score/schedulernodeimpl.h>
[fe6c170c]33#include <rtems/score/statesimpl.h>
[dce48791]34#include <rtems/score/status.h>
[16a41cc]35#include <rtems/score/sysstate.h>
[ef23838]36#include <rtems/score/timestampimpl.h>
[568af83]37#include <rtems/score/threadqimpl.h>
[f031df0e]38#include <rtems/score/todimpl.h>
[03b900d]39#include <rtems/score/watchdogimpl.h>
[16a41cc]40#include <rtems/config.h>
[5618c37a]41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/**
[4c20da4b]47 * @addtogroup RTEMSScoreThread
[3657cde]48 *
49 * @{
[5618c37a]50 */
51
52/**
53 *  Self for the GNU Ada Run-Time
54 */
[358bd740]55extern void *rtems_ada_self;
[5618c37a]56
[a7dcef97]57/**
58 * @brief Object identifier of the global constructor thread.
59 *
60 * This variable is set by _RTEMS_tasks_Initialize_user_tasks_body() or
61 * _POSIX_Threads_Initialize_user_threads_body().
62 *
63 * It is consumed by _Thread_Handler().
64 */
65extern Objects_Id _Thread_Global_constructor;
66
[5618c37a]67/**
68 *  The following points to the thread whose floating point
69 *  context is currently loaded.
70 */
71#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
[358bd740]72extern Thread_Control *_Thread_Allocated_fp;
[5618c37a]73#endif
74
[40dcafa]75#if defined(RTEMS_SMP)
[351c14d]76#define THREAD_OF_SCHEDULER_HELP_NODE( node ) \
77  RTEMS_CONTAINER_OF( node, Thread_Control, Scheduler.Help_node )
[40dcafa]78#endif
79
[d271c3bb]80typedef bool ( *Thread_Visitor )( Thread_Control *the_thread, void *arg );
81
[3657cde]82/**
83 * @brief Calls the visitor with all threads and the given argument until
84 *      it is done.
85 *
86 * @param visitor Function that gets a thread and @a arg as parameters and
87 *      returns if it is done.
88 * @param arg Parameter for @a visitor
89 */
[d271c3bb]90void _Thread_Iterate(
91  Thread_Visitor  visitor,
92  void           *arg
93);
94
[3657cde]95/**
96 * @brief Initializes the thread information
97 *
98 * @param[out] information Information to initialize.
99 */
[21275b58]100void _Thread_Initialize_information( Thread_Information *information );
[d7665823]101
[5618c37a]102/**
[3657cde]103 * @brief Initializes thread handler.
[5618c37a]104 *
[3657cde]105 * This routine performs the initialization necessary for this handler.
[5618c37a]106 */
107void _Thread_Handler_initialization(void);
108
109/**
[3657cde]110 * @brief Creates idle thread.
[5618c37a]111 *
[3657cde]112 * This routine creates the idle thread.
[5618c37a]113 *
[3657cde]114 * @warning No thread should be created before this one.
[5618c37a]115 */
116void _Thread_Create_idle(void);
117
118/**
[3657cde]119 * @brief Starts thread multitasking.
[5618c37a]120 *
[3657cde]121 * This routine initiates multitasking.  It is invoked only as
122 * part of initialization and its invocation is the last act of
123 * the non-multitasking part of the system initialization.
[5618c37a]124 */
[143696a]125void _Thread_Start_multitasking( void ) RTEMS_NO_RETURN;
[5618c37a]126
127/**
[3657cde]128 * @brief Allocates the requested stack space for the thread.
[5618c37a]129 *
[3657cde]130 * Allocate the requested stack space for the thread.
131 * Set the Start.stack field to the address of the stack.
[5618c37a]132 *
[3657cde]133 * @param[out] the_thread The thread where the stack space is requested.
134 * @param stack_size The stack space that is requested.
[5618c37a]135 *
[3657cde]136 * @retval actual Size allocated after any adjustment.
137 * @retval zero The allocation failed.
[5618c37a]138 */
139size_t _Thread_Stack_Allocate(
140  Thread_Control *the_thread,
141  size_t          stack_size
142);
143
144/**
[3657cde]145 * @brief Deallocates thread stack.
[5618c37a]146 *
[3657cde]147 * Deallocate the Thread's stack.
148 *
149 * @param[out] the_thread The thread to deallocate the stack of.
[5618c37a]150 */
151void _Thread_Stack_Free(
152  Thread_Control *the_thread
153);
154
155/**
[3657cde]156 * @brief Initializes thread.
157 *
158 * This routine initializes the specified the thread.  It allocates
159 * all memory associated with this thread.  It completes by adding
160 * the thread to the local object table so operations on this
161 * thread id are allowed.
[5618c37a]162 *
[3657cde]163 * @note If stack_area is NULL, it is allocated from the workspace.
[5618c37a]164 *
[3657cde]165 * @note If the stack is allocated from the workspace, then it is
166 *       guaranteed to be of at least minimum size.
[5618c37a]167 *
[3657cde]168 * @param information The thread information.
169 * @param[out] the_thread The thread to initialize.
170 * @param scheduler The scheduler control instance for the thread.
171 * @param stack_area The starting address of the thread area.
172 * @param stack_size The size of the thread area in bytes.
173 * @param is_fp Indicates whether the thread needs a floating point area.
174 * @param priority The new thread's priority.
175 * @param is_preemptible Indicates whether the new thread is preemptible.
176 * @param budget_algorithm The thread's budget algorithm.
177 * @param budget_callout The thread's initial budget callout.
178 * @param isr_level The thread's initial isr level.
179 * @param name Name of the object for the thread.
180 *
181 * @retval true The thread initialization was successful.
182 * @retval false The thread initialization failed.
[5618c37a]183 */
184bool _Thread_Initialize(
[d7665823]185  Thread_Information                   *information,
[5618c37a]186  Thread_Control                       *the_thread,
[e460cd00]187  const struct _Scheduler_Control      *scheduler,
[5618c37a]188  void                                 *stack_area,
189  size_t                                stack_size,
190  bool                                  is_fp,
191  Priority_Control                      priority,
192  bool                                  is_preemptible,
193  Thread_CPU_budget_algorithms          budget_algorithm,
194  Thread_CPU_budget_algorithm_callout   budget_callout,
195  uint32_t                              isr_level,
196  Objects_Name                          name
197);
198
199/**
[3657cde]200 * @brief Initializes thread and executes it.
[5618c37a]201 *
[3657cde]202 * This routine initializes the executable information for a thread
203 * and makes it ready to execute.  After this routine executes, the
204 * thread competes with all other threads for CPU time.
[5618c37a]205 *
[3657cde]206 * @param the_thread The thread to be started.
207 * @param entry The thread entry information.
[5618c37a]208 */
209bool _Thread_Start(
[ccd5434]210  Thread_Control                 *the_thread,
[33829ce]211  const Thread_Entry_information *entry,
212  ISR_lock_Context               *lock_context
[5618c37a]213);
214
[3657cde]215/**
216 * @brief Restarts the currently executing thread.
217 *
218 * @param[in, out] executing The currently executing thread.
219 * @param entry The start entry information for @a executing.
220 * @param lock_context The lock context.
221 */
[9388390]222void _Thread_Restart_self(
[ccd5434]223  Thread_Control                 *executing,
[9388390]224  const Thread_Entry_information *entry,
225  ISR_lock_Context               *lock_context
226) RTEMS_NO_RETURN;
227
[3657cde]228/**
229 * @brief Restarts the thread.
230 *
231 * @param[in, out] the_thread The thread to restart.
232 * @param entry The start entry information for @a the_thread.
233 * @param lock_context The lock context.
234 *
235 * @retval true The operation was successful.
236 * @retval false The operation failed.
237 */
[9388390]238bool _Thread_Restart_other(
239  Thread_Control                 *the_thread,
240  const Thread_Entry_information *entry,
241  ISR_lock_Context               *lock_context
[5618c37a]242);
243
[3657cde]244/**
245 * @brief Yields the currently executing thread.
246 *
247 * @param[in, out] executing The thread that performs a yield.
248 */
[701dd96f]249void _Thread_Yield( Thread_Control *executing );
250
[3657cde]251/**
252 * @brief Changes the currently executing thread to a new state with the sets.
253 *
254 * @param clear States to clear.
255 * @param set States to set.
256 * @param ignore States to ignore.
257 *
258 * @return The previous state the thread was in.
259 */
[da826560]260Thread_Life_state _Thread_Change_life(
261  Thread_Life_state clear,
262  Thread_Life_state set,
263  Thread_Life_state ignore
264);
265
[3657cde]266/**
267 * @brief Set the thread to life protected.
268 *
269 * Calls _Thread_Change_life with the given state AND THREAD_LIFE_PROTECTED to
270 * set and THREAD_LIFE_PROTECTED to clear.
271 *
272 * @param state The states to set.
273 *
274 * @return The previous state the thread was in.
275 */
[9949d8a7]276Thread_Life_state _Thread_Set_life_protection( Thread_Life_state state );
[1b1be254]277
[5618c37a]278/**
[1b1be254]279 * @brief Kills all zombie threads in the system.
[5618c37a]280 *
[1b1be254]281 * Threads change into the zombie state as the last step in the thread
282 * termination sequence right before a context switch to the heir thread is
283 * initiated.  Since the thread stack is still in use during this phase we have
284 * to postpone the thread stack reclamation until this point.  On SMP
285 * configurations we may have to busy wait for context switch completion here.
[5618c37a]286 */
[1b1be254]287void _Thread_Kill_zombies( void );
288
[3657cde]289/**
290 * @brief Exits the currently executing thread.
291 *
292 * @param[in, out] executing The currently executing thread.
293 * @param set The states to set.
294 * @param[out] exit_value Contains the exit value of the thread.
295 */
[54550e04]296void _Thread_Exit(
297  Thread_Control    *executing,
298  Thread_Life_state  set,
299  void              *exit_value
300);
[b7f5e391]301
[3657cde]302/**
303 * @brief Joins the currently executing thread with the given thread to wait
304 *      for.
305 *
306 * @param[in, out] the_thread The thread to wait for.
307 * @param waiting_for_join The states control for the join.
308 * @param[in, out] executing The currently executing thread.
309 * @param queue_context The thread queue context.
310 */
[232147dd]311void _Thread_Join(
[93306058]312  Thread_Control       *the_thread,
313  States_Control        waiting_for_join,
314  Thread_Control       *executing,
315  Thread_queue_Context *queue_context
[232147dd]316);
317
[3657cde]318/**
319 * @brief Cancels the thread.
320 *
321 * @param[in, out] the_thread The thread to cancel.
322 * @param executing The currently executing thread.
323 * @param exit_value The exit value for the thread.
324 */
[54550e04]325void _Thread_Cancel(
326  Thread_Control *the_thread,
327  Thread_Control *executing,
328  void           *exit_value
329);
[232147dd]330
[125f248]331typedef struct {
332  Thread_queue_Context  Base;
333  Thread_Control       *cancel;
334} Thread_Close_context;
335
[1b1be254]336/**
337 * @brief Closes the thread.
338 *
339 * Closes the thread object and starts the thread termination sequence.  In
340 * case the executing thread is not terminated, then this function waits until
341 * the terminating thread reached the zombie state.
[3657cde]342 *
343 * @param the_thread The thread to close.
344 * @param executing The currently executing thread.
345 * @param[in, out] context The thread close context.
[1b1be254]346 */
[125f248]347void _Thread_Close(
348  Thread_Control       *the_thread,
349  Thread_Control       *executing,
350  Thread_Close_context *context
351);
[5618c37a]352
[3657cde]353/**
354 * @brief Checks if the thread is ready.
355 *
356 * @param the_thread The thread to check if it is ready.
357 *
358 * @retval true The thread is currently in the ready state.
359 * @retval false The thread is currently not ready.
360 */
[9bfad8c]361RTEMS_INLINE_ROUTINE bool _Thread_Is_ready( const Thread_Control *the_thread )
362{
363  return _States_Is_ready( the_thread->current_state );
364}
365
[3657cde]366/**
367 * @brief Clears the specified thread state without locking the lock context.
368 *
369 * In the case the previous state is a non-ready state and the next state is
370 * the ready state, then the thread is unblocked by the scheduler.
371 *
372 * @param[in, out] the_thread The thread.
373 * @param state The state to clear.  It must not be zero.
374 *
375 * @return The thread's previous state.
376 */
[f410ea82]377States_Control _Thread_Clear_state_locked(
378  Thread_Control *the_thread,
379  States_Control  state
380);
381
[5618c37a]382/**
[342708b9]383 * @brief Clears the specified thread state.
[5618c37a]384 *
[3657cde]385 * In the case the previous state is a non-ready state and the next state is
386 * the ready state, then the thread is unblocked by the scheduler.
[5618c37a]387 *
[3657cde]388 * @param[in, out] the_thread The thread.
389 * @param state The state to clear.  It must not be zero.
[342708b9]390 *
391 * @return The previous state.
[5618c37a]392 */
[342708b9]393States_Control _Thread_Clear_state(
[5618c37a]394  Thread_Control *the_thread,
395  States_Control  state
396);
397
[3657cde]398/**
399 * @brief Sets the specified thread state without locking the lock context.
400 *
401 * In the case the previous state is the ready state, then the thread is blocked
402 * by the scheduler.
403 *
404 * @param[in, out] the_thread The thread.
405 * @param state The state to set.  It must not be zero.
406 *
407 * @return The previous state.
408 */
[9a99ce15]409States_Control _Thread_Set_state_locked(
410  Thread_Control *the_thread,
411  States_Control  state
412);
413
[5618c37a]414/**
[ca10004]415 * @brief Sets the specified thread state.
[5618c37a]416 *
[3657cde]417 * In the case the previous state is the ready state, then the thread is blocked
418 * by the scheduler.
[5618c37a]419 *
[3657cde]420 * @param[in, out] the_thread The thread.
421 * @param state The state to set.  It must not be zero.
[342708b9]422 *
423 * @return The previous state.
[5618c37a]424 */
[342708b9]425States_Control _Thread_Set_state(
[5618c37a]426  Thread_Control *the_thread,
427  States_Control  state
428);
429
430/**
[3657cde]431 * @brief Initializes enviroment for a thread.
[5618c37a]432 *
[3657cde]433 * This routine initializes the context of @a the_thread to its
434 * appropriate starting state.
[5618c37a]435 *
[3657cde]436 * @param[in, out] the_thread The pointer to the thread control block.
[5618c37a]437 */
438void _Thread_Load_environment(
439  Thread_Control *the_thread
440);
441
[3657cde]442/**
443 * @brief Calls the start kinds idle entry of the thread.
444 *
445 * @param executing The currently executing thread.
446 */
[ccd5434]447void _Thread_Entry_adaptor_idle( Thread_Control *executing );
448
[3657cde]449/**
450 * @brief Calls the start kinds numeric entry of the thread.
451 *
452 * @param executing The currently executing thread.
453 */
[ccd5434]454void _Thread_Entry_adaptor_numeric( Thread_Control *executing );
455
[3657cde]456/**
457 * @brief Calls the start kinds pointer entry of the thread.
458 *
459 * Stores the return value in the Wait.return_argument of the thread.
460 *
461 * @param executing The currently executing thread.
462 */
[ccd5434]463void _Thread_Entry_adaptor_pointer( Thread_Control *executing );
464
[5618c37a]465/**
[3657cde]466 * @brief Wrapper function for all threads.
[5618c37a]467 *
[3657cde]468 * This routine is the wrapper function for all threads.  It is
469 * the starting point for all threads.  The user provided thread
470 * entry point is invoked by this routine.  Operations
471 * which must be performed immediately before and after the user's
472 * thread executes are found here.
[5618c37a]473 *
[3657cde]474 * @note On entry, it is assumed all interrupts are blocked and that this
475 * routine needs to set the initial isr level.  This may or may not
476 * actually be needed by the context switch routine and as a result
477 * interrupts may already be at there proper level.  Either way,
478 * setting the initial isr level properly here is safe.
[5618c37a]479 */
480void _Thread_Handler( void );
481
[3657cde]482/**
483 * @brief Acquires the lock context in a critical section.
484 *
485 * @param the_thread The thread to acquire the lock context.
486 * @param lock_context The lock context.
487 */
[6e4f929]488RTEMS_INLINE_ROUTINE void _Thread_State_acquire_critical(
489  Thread_Control   *the_thread,
490  ISR_lock_Context *lock_context
491)
492{
[114e408]493  _Thread_queue_Do_acquire_critical( &the_thread->Join_queue, lock_context );
[6e4f929]494}
495
[3657cde]496/**
497 * @brief Disables interrupts and acquires the lock_context.
498 *
499 * @param the_thread The thread to acquire the lock context.
500 * @param lock_context The lock context.
501 */
[6e4f929]502RTEMS_INLINE_ROUTINE void _Thread_State_acquire(
503  Thread_Control   *the_thread,
504  ISR_lock_Context *lock_context
505)
506{
[114e408]507  _ISR_lock_ISR_disable( lock_context );
508  _Thread_State_acquire_critical( the_thread, lock_context );
[6e4f929]509}
510
[3657cde]511/**
512 * @brief Disables interrupts and acquires the lock context for the currently
513 *      executing thread.
514 *
515 * @param lock_context The lock context.
516 *
517 * @return The currently executing thread.
518 */
[6e4f929]519RTEMS_INLINE_ROUTINE Thread_Control *_Thread_State_acquire_for_executing(
520  ISR_lock_Context *lock_context
521)
522{
523  Thread_Control *executing;
524
525  _ISR_lock_ISR_disable( lock_context );
526  executing = _Thread_Executing;
527  _Thread_State_acquire_critical( executing, lock_context );
528
529  return executing;
530}
531
[3657cde]532/**
533 * @brief Release the lock context in a critical section.
534 *
535 * @param the_thread The thread to release the lock context.
536 * @param lock_context The lock context.
537 */
[ef6f8a83]538RTEMS_INLINE_ROUTINE void _Thread_State_release_critical(
539  Thread_Control   *the_thread,
540  ISR_lock_Context *lock_context
541)
542{
[114e408]543  _Thread_queue_Do_release_critical( &the_thread->Join_queue, lock_context );
[ef6f8a83]544}
545
[3657cde]546/**
547 * @brief Releases the lock context and enables interrupts.
548 *
549 * @param[in, out] the_thread The thread to release the lock context.
550 * @param[out] lock_context The lock context.
551 */
[6e4f929]552RTEMS_INLINE_ROUTINE void _Thread_State_release(
553  Thread_Control   *the_thread,
554  ISR_lock_Context *lock_context
555)
556{
[114e408]557  _Thread_State_release_critical( the_thread, lock_context );
558  _ISR_lock_ISR_enable( lock_context );
[6e4f929]559}
560
[3657cde]561/**
562 * @brief Checks if the thread is owner of the lock of the join queue.
563 *
564 * @param the_thread The thread for the verification.
565 *
566 * @retval true The thread is owner of the lock of the join queue.
567 * @retval false The thread is not owner of the lock of the join queue.
568 */
[6e4f929]569#if defined(RTEMS_DEBUG)
570RTEMS_INLINE_ROUTINE bool _Thread_State_is_owner(
571  const Thread_Control *the_thread
572)
573{
574  return _Thread_queue_Is_lock_owner( &the_thread->Join_queue );
575}
576#endif
577
[5618c37a]578/**
[300f6a48]579 * @brief Performs the priority actions specified by the thread queue context
580 * along the thread queue path.
581 *
582 * The caller must be the owner of the thread wait lock.
583 *
584 * @param start_of_path The start thread of the thread queue path.
585 * @param queue_context The thread queue context specifying the thread queue
586 *   path and initial thread priority actions.
587 *
588 * @see _Thread_queue_Path_acquire_critical().
[900d337f]589 */
[300f6a48]590void _Thread_Priority_perform_actions(
591  Thread_Control       *start_of_path,
592  Thread_queue_Context *queue_context
593);
[900d337f]594
595/**
[300f6a48]596 * @brief Adds the specified thread priority node to the corresponding thread
597 * priority aggregation.
598 *
599 * The caller must be the owner of the thread wait lock.
600 *
601 * @param the_thread The thread.
602 * @param priority_node The thread priority node to add.
603 * @param queue_context The thread queue context to return an updated set of
604 *   threads for _Thread_Priority_update().  The thread queue context must be
605 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
606 *   call of this function.
607 *
608 * @see _Thread_Wait_acquire().
[900d337f]609 */
[300f6a48]610void _Thread_Priority_add(
611  Thread_Control       *the_thread,
612  Priority_Node        *priority_node,
613  Thread_queue_Context *queue_context
614);
[900d337f]615
616/**
[300f6a48]617 * @brief Removes the specified thread priority node from the corresponding
618 * thread priority aggregation.
[900d337f]619 *
[300f6a48]620 * The caller must be the owner of the thread wait lock.
[5618c37a]621 *
[300f6a48]622 * @param the_thread The thread.
623 * @param priority_node The thread priority node to remove.
624 * @param queue_context The thread queue context to return an updated set of
625 *   threads for _Thread_Priority_update().  The thread queue context must be
626 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
627 *   call of this function.
[5618c37a]628 *
[300f6a48]629 * @see _Thread_Wait_acquire().
[5618c37a]630 */
[300f6a48]631void _Thread_Priority_remove(
632  Thread_Control       *the_thread,
633  Priority_Node        *priority_node,
634  Thread_queue_Context *queue_context
[5618c37a]635);
636
[300f6a48]637/**
638 * @brief Propagates a thread priority value change in the specified thread
639 * priority node to the corresponding thread priority aggregation.
640 *
641 * The caller must be the owner of the thread wait lock.
642 *
643 * @param the_thread The thread.
[3657cde]644 * @param[out] priority_node The thread priority node to change.
[300f6a48]645 * @param prepend_it In case this is true, then the thread is prepended to
646 *   its priority group in its home scheduler instance, otherwise it is
647 *   appended.
648 * @param queue_context The thread queue context to return an updated set of
649 *   threads for _Thread_Priority_update().  The thread queue context must be
650 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
651 *   call of this function.
652 *
653 * @see _Thread_Wait_acquire().
654 */
655void _Thread_Priority_changed(
656  Thread_Control       *the_thread,
657  Priority_Node        *priority_node,
658  bool                  prepend_it,
659  Thread_queue_Context *queue_context
[f4d1f30]660);
661
[300f6a48]662/**
663 * @brief Changes the thread priority value of the specified thread priority
664 * node in the corresponding thread priority aggregation.
665 *
666 * The caller must be the owner of the thread wait lock.
667 *
668 * @param the_thread The thread.
[3657cde]669 * @param[out] priority_node The thread priority node to change.
[300f6a48]670 * @param new_priority The new thread priority value of the thread priority
671 *   node to change.
672 * @param prepend_it In case this is true, then the thread is prepended to
673 *   its priority group in its home scheduler instance, otherwise it is
674 *   appended.
675 * @param queue_context The thread queue context to return an updated set of
676 *   threads for _Thread_Priority_update().  The thread queue context must be
677 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
678 *   call of this function.
679 *
680 * @see _Thread_Wait_acquire().
681 */
682RTEMS_INLINE_ROUTINE void _Thread_Priority_change(
683  Thread_Control       *the_thread,
684  Priority_Node        *priority_node,
685  Priority_Control      new_priority,
686  bool                  prepend_it,
687  Thread_queue_Context *queue_context
688)
689{
690  _Priority_Node_set_priority( priority_node, new_priority );
691  _Thread_Priority_changed(
692    the_thread,
693    priority_node,
694    prepend_it,
695    queue_context
696  );
697}
[f4d1f30]698
[5618c37a]699/**
[300f6a48]700 * @brief Replaces the victim priority node with the replacement priority node
701 * in the corresponding thread priority aggregation.
[900d337f]702 *
[300f6a48]703 * The caller must be the owner of the thread wait lock.
[5618c37a]704 *
[300f6a48]705 * @param the_thread The thread.
706 * @param victim_node The victim thread priority node.
707 * @param replacement_node The replacement thread priority node.
708 *
709 * @see _Thread_Wait_acquire().
[5618c37a]710 */
[300f6a48]711void _Thread_Priority_replace(
712  Thread_Control *the_thread,
713  Priority_Node  *victim_node,
714  Priority_Node  *replacement_node
[900d337f]715);
716
717/**
[3657cde]718 * @brief Updates the priority of all threads in the set
[900d337f]719 *
[300f6a48]720 * @param queue_context The thread queue context to return an updated set of
721 *   threads for _Thread_Priority_update().  The thread queue context must be
722 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
723 *   call of this function.
[900d337f]724 *
[300f6a48]725 * @see _Thread_Priority_add(), _Thread_Priority_change(),
726 *   _Thread_Priority_changed() and _Thread_Priority_remove().
[900d337f]727 */
[300f6a48]728void _Thread_Priority_update( Thread_queue_Context *queue_context );
[5618c37a]729
[3657cde]730/**
731 * @brief Updates the priority of the thread and changes it sticky level.
732 *
733 * @param the_thread The thread.
734 * @param sticky_level_change The new value for the sticky level.
735 */
[6771359f]736#if defined(RTEMS_SMP)
737void _Thread_Priority_and_sticky_update(
738  Thread_Control *the_thread,
739  int             sticky_level_change
740);
741#endif
742
[900d337f]743/**
[3657cde]744 * @brief Checks if the left thread priority is less than the right thread
745 *      priority in the intuitive sense of priority.
746 *
747 * @param left The left thread priority.
748 * @param right The right thread priority.
749 *
750 * @retval true The left priority is less in the intuitive sense.
751 * @retval false The left priority is greater or equal in the intuitive sense.
[900d337f]752 */
[300f6a48]753RTEMS_INLINE_ROUTINE bool _Thread_Priority_less_than(
754  Priority_Control left,
755  Priority_Control right
756)
757{
758  return left > right;
759}
[900d337f]760
761/**
[300f6a48]762 * @brief Returns the highest priority of the left and right thread priorities
763 * in the intuitive sense of priority.
[3657cde]764 *
765 * @param left The left thread priority.
766 * @param right The right thread priority.
767 *
768 * @return The highest priority in the intuitive sense of priority.
[900d337f]769 */
[300f6a48]770RTEMS_INLINE_ROUTINE Priority_Control _Thread_Priority_highest(
771  Priority_Control left,
772  Priority_Control right
773)
774{
775  return _Thread_Priority_less_than( left, right ) ? right : left;
776}
[900d337f]777
[3657cde]778/**
779 * @brief Gets object information for the object id.
780 *
781 * @param id The id of the object information.
782 *
783 * @retval pointer The object information for this id.
784 * @retval NULL The object id is not valid.
785 */
[822ec589]786RTEMS_INLINE_ROUTINE Objects_Information *_Thread_Get_objects_information(
787  Objects_Id id
788)
789{
790  uint32_t the_api;
791
792  the_api = _Objects_Get_API( id );
793
794  if ( !_Objects_Is_api_valid( the_api ) ) {
795    return NULL;
796  }
797
798  /*
799   * Threads are always first class :)
800   *
801   * There is no need to validate the object class of the object identifier,
802   * since this will be done by the object get methods.
803   */
804  return _Objects_Information_table[ the_api ][ 1 ];
805}
806
[5b393fa5]807/**
[1041de1]808 * @brief Gets a thread by its identifier.
[5b393fa5]809 *
[582bb23c]810 * @see _Objects_Get().
[3657cde]811 *
812 * @param id The id of the thread.
813 * @param lock_context The lock context.
[5b393fa5]814 */
[e266d13]815Thread_Control *_Thread_Get(
[5b393fa5]816  Objects_Id         id,
817  ISR_lock_Context  *lock_context
818);
819
[3657cde]820/**
821 * @brief Gets the cpu of the thread's scheduler.
822 *
823 * @param thread The thread.
824 *
825 * @return The cpu of the thread's scheduler.
826 */
[a5ac9da]827RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Get_CPU(
828  const Thread_Control *thread
829)
830{
831#if defined(RTEMS_SMP)
[2d36931]832  return thread->Scheduler.cpu;
[a5ac9da]833#else
834  (void) thread;
835
836  return _Per_CPU_Get();
837#endif
838}
839
[3657cde]840/**
841 * @brief Sets the cpu of the thread's scheduler.
842 *
843 * @param[out] thread The thread.
844 * @param cpu The cpu to set.
845 */
[a5ac9da]846RTEMS_INLINE_ROUTINE void _Thread_Set_CPU(
847  Thread_Control *thread,
848  Per_CPU_Control *cpu
849)
850{
851#if defined(RTEMS_SMP)
[2d36931]852  thread->Scheduler.cpu = cpu;
[a5ac9da]853#else
854  (void) thread;
855  (void) cpu;
856#endif
857}
858
[5618c37a]859/**
[3657cde]860 * @brief Checks if the thread is the currently executing thread.
861 *
[5618c37a]862 * This function returns true if the_thread is the currently executing
863 * thread, and false otherwise.
[3657cde]864 *
865 * @param the_thread The thread to verify if it is the currently executing thread.
866 *
867 * @retval true @a the_thread is the currently executing one.
868 * @retval false @a the_thread is not the currently executing one.
[5618c37a]869 */
870RTEMS_INLINE_ROUTINE bool _Thread_Is_executing (
871  const Thread_Control *the_thread
872)
873{
874  return ( the_thread == _Thread_Executing );
875}
876
[38b59a6]877#if defined(RTEMS_SMP)
878/**
[3657cde]879 * @brief Checks if the thread executes currently on some processor in the
880 * system.
[38b59a6]881 *
882 * Do not confuse this with _Thread_Is_executing() which checks only the
883 * current processor.
[3657cde]884 *
885 * @param the_thread The thread for the verification.
886 *
887 * @retval true @a the_thread is the currently executing one.
888 * @retval false @a the_thread is not the currently executing one.
[38b59a6]889 */
890RTEMS_INLINE_ROUTINE bool _Thread_Is_executing_on_a_processor(
891  const Thread_Control *the_thread
892)
893{
894  return _CPU_Context_Get_is_executing( &the_thread->Registers );
895}
896#endif
897
[5618c37a]898/**
[3657cde]899 * @brief Checks if the thread is the heir.
900 *
[5618c37a]901 * This function returns true if the_thread is the heir
902 * thread, and false otherwise.
[3657cde]903 *
904 * @param the_thread The thread for the verification.
905 *
906 * @retval true @a the_thread is the heir.
907 * @retval false @a the_thread is not the heir.
[5618c37a]908 */
909RTEMS_INLINE_ROUTINE bool _Thread_Is_heir (
910  const Thread_Control *the_thread
911)
912{
913  return ( the_thread == _Thread_Heir );
914}
915
916/**
[3657cde]917 * @brief Unblocks the thread.
918 *
[5618c37a]919 * This routine clears any blocking state for the_thread.  It performs
920 * any necessary scheduling operations including the selection of
921 * a new heir thread.
[3657cde]922 *
923 * @param[in, out] the_thread The thread to unblock.
[5618c37a]924 */
925RTEMS_INLINE_ROUTINE void _Thread_Unblock (
926  Thread_Control *the_thread
927)
928{
929  _Thread_Clear_state( the_thread, STATES_BLOCKED );
930}
931
932/**
[3657cde]933 * @brief Checks if the floating point context of the thread is currently
934 *      loaded in the floating point unit.
935 *
[5618c37a]936 * This function returns true if the floating point context of
937 * the_thread is currently loaded in the floating point unit, and
938 * false otherwise.
[3657cde]939 *
940 * @param the_thread The thread for the verification.
941 *
942 * @retval true The floating point context of @a the_thread is currently
943 *      loaded in the floating point unit.
944 * @retval false The floating point context of @a the_thread is currently not
945 *      loaded in the floating point unit.
[5618c37a]946 */
947#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
948RTEMS_INLINE_ROUTINE bool _Thread_Is_allocated_fp (
949  const Thread_Control *the_thread
950)
951{
952  return ( the_thread == _Thread_Allocated_fp );
953}
954#endif
955
[8d6e6eeb]956/*
[3657cde]957 * If the CPU has hardware floating point, then we must address saving
958 * and restoring it as part of the context switch.
[8d6e6eeb]959 *
[3657cde]960 * The second conditional compilation section selects the algorithm used
961 * to context switch between floating point tasks.  The deferred algorithm
962 * can be significantly better in a system with few floating point tasks
963 * because it reduces the total number of save and restore FP context
964 * operations.  However, this algorithm can not be used on all CPUs due
965 * to unpredictable use of FP registers by some compilers for integer
966 * operations.
[8d6e6eeb]967 */
968
[3657cde]969/**
970 * @brief Saves the executing thread's floating point area.
971 *
972 * @param executing The currently executing thread.
973 */
[8d6e6eeb]974RTEMS_INLINE_ROUTINE void _Thread_Save_fp( Thread_Control *executing )
975{
976#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
977#if ( CPU_USE_DEFERRED_FP_SWITCH != TRUE )
978  if ( executing->fp_context != NULL )
979    _Context_Save_fp( &executing->fp_context );
980#endif
981#endif
982}
983
[3657cde]984/**
985 * @brief Restores the executing thread's floating point area.
986 *
987 * @param executing The currently executing thread.
988 */
[8d6e6eeb]989RTEMS_INLINE_ROUTINE void _Thread_Restore_fp( Thread_Control *executing )
990{
991#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
992#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
993  if ( (executing->fp_context != NULL) &&
994       !_Thread_Is_allocated_fp( executing ) ) {
995    if ( _Thread_Allocated_fp != NULL )
996      _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
997    _Context_Restore_fp( &executing->fp_context );
998    _Thread_Allocated_fp = executing;
999  }
1000#else
1001  if ( executing->fp_context != NULL )
1002    _Context_Restore_fp( &executing->fp_context );
1003#endif
1004#endif
1005}
1006
[5618c37a]1007/**
[3657cde]1008 * @brief Deallocates the currently loaded floating point context.
1009 *
[5618c37a]1010 * This routine is invoked when the currently loaded floating
1011 * point context is now longer associated with an active thread.
1012 */
1013#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
1014RTEMS_INLINE_ROUTINE void _Thread_Deallocate_fp( void )
1015{
1016  _Thread_Allocated_fp = NULL;
1017}
1018#endif
1019
1020/**
[3657cde]1021 * @brief Checks if dispatching is disabled.
1022 *
[5618c37a]1023 * This function returns true if dispatching is disabled, and false
1024 * otherwise.
[3657cde]1025 *
1026 * @retval true Dispatching is disabled.
1027 * @retval false Dispatching is enabled.
[5618c37a]1028 */
1029RTEMS_INLINE_ROUTINE bool _Thread_Is_context_switch_necessary( void )
1030{
1031  return ( _Thread_Dispatch_necessary );
1032}
1033
1034/**
[3657cde]1035 * @brief Checks if the thread is NULL.
1036 *
1037 * @param the_thread The thread for the verification.
1038 *
1039 * @retval true The thread is @c NULL.
1040 * @retval false The thread is not @c NULL.
[5618c37a]1041 */
1042RTEMS_INLINE_ROUTINE bool _Thread_Is_null (
1043  const Thread_Control *the_thread
1044)
1045{
1046  return ( the_thread == NULL );
1047}
1048
[3657cde]1049/**
1050 * @brief Gets the maximum number of internal threads.
1051 *
1052 * @return The maximum number of internal threads.
1053 */
[16a41cc]1054RTEMS_INLINE_ROUTINE uint32_t _Thread_Get_maximum_internal_threads(void)
1055{
1056  /* Idle threads */
[01794eb]1057  uint32_t maximum_internal_threads =
1058    rtems_configuration_get_maximum_processors();
[16a41cc]1059
1060  /* MPCI thread */
1061#if defined(RTEMS_MULTIPROCESSING)
1062  if ( _System_state_Is_multiprocessing ) {
1063    ++maximum_internal_threads;
1064  }
1065#endif
1066
1067  return maximum_internal_threads;
1068}
1069
[3657cde]1070/**
1071 * @brief Allocates an internal thread and returns it.
1072 *
1073 * @retval pointer Pointer to the allocated Thread_Control.
1074 * @retval NULL The operation failed.
1075 */
[5618c37a]1076RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Internal_allocate( void )
1077{
[23fec9f0]1078  return (Thread_Control *)
[21275b58]1079    _Objects_Allocate_unprotected( &_Thread_Information.Objects );
[5618c37a]1080}
1081
[38b59a6]1082/**
1083 * @brief Gets the heir of the processor and makes it executing.
1084 *
[258ad71]1085 * Must be called with interrupts disabled.  The thread dispatch necessary
1086 * indicator is cleared as a side-effect.
[38b59a6]1087 *
[3657cde]1088 * @param[in, out] cpu_self The processor to get the heir of.
1089 *
[38b59a6]1090 * @return The heir thread.
1091 *
1092 * @see _Thread_Dispatch(), _Thread_Start_multitasking() and
[835b88b]1093 * _Thread_Dispatch_update_heir().
[38b59a6]1094 */
1095RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Get_heir_and_make_it_executing(
1096  Per_CPU_Control *cpu_self
1097)
1098{
1099  Thread_Control *heir;
1100
1101  heir = cpu_self->heir;
[258ad71]1102  cpu_self->dispatch_necessary = false;
[38b59a6]1103  cpu_self->executing = heir;
1104
1105  return heir;
1106}
1107
[3657cde]1108/**
1109 * @brief Updates the cpu time used of the thread.
1110 *
1111 * @param[in, out] the_thread The thread to add additional cpu time that is
1112 *      used.
1113 * @param cpu The cpu.
1114 */
[d37adfe5]1115RTEMS_INLINE_ROUTINE void _Thread_Update_CPU_time_used(
1116  Thread_Control  *the_thread,
1117  Per_CPU_Control *cpu
1118)
1119{
1120  Timestamp_Control last;
1121  Timestamp_Control ran;
1122
1123  last = cpu->cpu_usage_timestamp;
1124  _TOD_Get_uptime( &cpu->cpu_usage_timestamp );
1125  _Timestamp_Subtract( &last, &cpu->cpu_usage_timestamp, &ran );
1126  _Timestamp_Add_to( &the_thread->cpu_time_used, &ran );
1127}
1128
[3657cde]1129/**
1130 * @brief Updates the used cpu time for the heir and dispatches a new heir.
1131 *
1132 * @param[in, out] cpu_self The current processor.
1133 * @param[in, out] cpu_for_heir The processor to do a dispatch on.
1134 * @param heir The new heir for @a cpu_for_heir.
1135 */
[835b88b]1136#if defined( RTEMS_SMP )
1137RTEMS_INLINE_ROUTINE void _Thread_Dispatch_update_heir(
1138  Per_CPU_Control *cpu_self,
1139  Per_CPU_Control *cpu_for_heir,
1140  Thread_Control  *heir
1141)
1142{
[d37adfe5]1143  _Thread_Update_CPU_time_used( cpu_for_heir->heir, cpu_for_heir );
1144
[835b88b]1145  cpu_for_heir->heir = heir;
1146
[9bb3ce39]1147  _Thread_Dispatch_request( cpu_self, cpu_for_heir );
[835b88b]1148}
1149#endif
1150
[3657cde]1151/**
1152 * @brief Gets the used cpu time of the thread and stores it in the given
1153 *      Timestamp_Control.
1154 *
1155 * @param the_thread The thread to get the used cpu time of.
1156 * @param[out] cpu_time_used Stores the used cpu time of @a the_thread.
1157 */
[d37adfe5]1158void _Thread_Get_CPU_time_used(
1159  Thread_Control    *the_thread,
1160  Timestamp_Control *cpu_time_used
1161);
[1e51fa5]1162
[3657cde]1163/**
1164 * @brief Initializes the control chain of the action control.
1165 *
1166 * @param[out] action_control The action control to initialize.
1167 */
[0dd732d]1168RTEMS_INLINE_ROUTINE void _Thread_Action_control_initialize(
1169  Thread_Action_control *action_control
1170)
1171{
1172  _Chain_Initialize_empty( &action_control->Chain );
1173}
1174
[3657cde]1175/**
1176 * @brief Initializes the Thread action.
1177 *
1178 * @param[out] action The Thread_Action to initialize.
1179 */
[0dd732d]1180RTEMS_INLINE_ROUTINE void _Thread_Action_initialize(
[df55d07f]1181  Thread_Action *action
[0dd732d]1182)
1183{
1184  _Chain_Set_off_chain( &action->Node );
1185}
1186
[3657cde]1187/**
1188 * @brief Adds a post switch action to the thread with the given handler.
1189 *
1190 * @param[in, out] the_thread The thread.
1191 * @param[in,  out] action The action to add.
1192 * @param handler The handler for the action.
1193 */
[0dd732d]1194RTEMS_INLINE_ROUTINE void _Thread_Add_post_switch_action(
[6e4f929]1195  Thread_Control        *the_thread,
[df55d07f]1196  Thread_Action         *action,
1197  Thread_Action_handler  handler
[0dd732d]1198)
1199{
[6157743]1200  Per_CPU_Control *cpu_of_thread;
[0dd732d]1201
[6e4f929]1202  _Assert( _Thread_State_is_owner( the_thread ) );
1203
1204  cpu_of_thread = _Thread_Get_CPU( the_thread );
[6157743]1205
[df55d07f]1206  action->handler = handler;
1207
[9bb3ce39]1208  _Thread_Dispatch_request( _Per_CPU_Get(), cpu_of_thread );
[6157743]1209
[0dd732d]1210  _Chain_Append_if_is_off_chain_unprotected(
[6e4f929]1211    &the_thread->Post_switch_actions.Chain,
[0dd732d]1212    &action->Node
1213  );
1214}
1215
[3657cde]1216/**
1217 * @brief Checks if the thread life state is restarting.
1218 *
1219 * @param life_state The thread life state for the verification.
1220 *
1221 * @retval true @a life_state is restarting.
1222 * @retval false @a life_state is not restarting.
1223 */
[1b1be254]1224RTEMS_INLINE_ROUTINE bool _Thread_Is_life_restarting(
1225  Thread_Life_state life_state
1226)
1227{
1228  return ( life_state & THREAD_LIFE_RESTARTING ) != 0;
1229}
1230
[3657cde]1231/**
1232 * @brief Checks if the thread life state is terminating.
1233 *
1234 * @param life_state The thread life state for the verification.
1235 *
1236 * @retval true @a life_state is terminating.
1237 * @retval false @a life_state is not terminating.
1238 */
[1b1be254]1239RTEMS_INLINE_ROUTINE bool _Thread_Is_life_terminating(
1240  Thread_Life_state life_state
1241)
1242{
1243  return ( life_state & THREAD_LIFE_TERMINATING ) != 0;
1244}
1245
[3657cde]1246/**
1247 * @brief Checks if the thread life state allos life change.
1248 *
1249 * @param life_state The thread life state for the verification.
1250 *
1251 * @retval true @a life_state allows life change.
1252 * @retval false @a life_state does not allow life change.
1253 */
[9949d8a7]1254RTEMS_INLINE_ROUTINE bool _Thread_Is_life_change_allowed(
[1b1be254]1255  Thread_Life_state life_state
1256)
1257{
[da826560]1258  return ( life_state
1259    & ( THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED ) ) == 0;
[1b1be254]1260}
1261
[3657cde]1262/**
1263 * @brief Checks if the thread life state is life changing.
1264 *
1265 * @param life_state The thread life state for the verification.
1266 *
1267 * @retval true @a life_state is life changing.
1268 * @retval false @a life_state is not life changing.
1269 */
[1b1be254]1270RTEMS_INLINE_ROUTINE bool _Thread_Is_life_changing(
1271  Thread_Life_state life_state
1272)
1273{
[e753748]1274  return ( life_state
1275    & ( THREAD_LIFE_RESTARTING | THREAD_LIFE_TERMINATING ) ) != 0;
[1b1be254]1276}
1277
[3657cde]1278/**
1279 * @brief Checks if the thread is joinable.
1280 *
1281 * @param the_thread The thread for the verification.
1282 *
1283 * @retval true @a life_state is joinable.
1284 * @retval false @a life_state is not joinable.
1285 */
[54550e04]1286RTEMS_INLINE_ROUTINE bool _Thread_Is_joinable(
1287  const Thread_Control *the_thread
1288)
1289{
1290  _Assert( _Thread_State_is_owner( the_thread ) );
1291  return ( the_thread->Life.state & THREAD_LIFE_DETACHED ) == 0;
1292}
1293
[3657cde]1294/**
1295 * @brief Increments the thread's resource count.
1296 *
1297 * @param[in, out] the_thread The thread to increase the resource count of.
1298 */
[0dd49d0]1299RTEMS_INLINE_ROUTINE void _Thread_Resource_count_increment(
1300  Thread_Control *the_thread
1301)
1302{
[47d2464]1303#if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT)
[0dd49d0]1304  ++the_thread->resource_count;
[47d2464]1305#else
1306  (void) the_thread;
1307#endif
[0dd49d0]1308}
1309
[3657cde]1310/**
1311 * @brief Decrements the thread's resource count.
1312 *
1313 * @param[in, out] the_thread The thread to decrement the resource count of.
1314 */
[0dd49d0]1315RTEMS_INLINE_ROUTINE void _Thread_Resource_count_decrement(
1316  Thread_Control *the_thread
1317)
1318{
[47d2464]1319#if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT)
[0dd49d0]1320  --the_thread->resource_count;
[47d2464]1321#else
1322  (void) the_thread;
1323#endif
[0dd49d0]1324}
1325
[47d2464]1326#if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT)
[6c7caa1a]1327/**
[3657cde]1328 * @brief Checks if the thread owns resources.
[6c7caa1a]1329 *
1330 * Resources are accounted with the Thread_Control::resource_count resource
[97f7dac]1331 * counter.  This counter is used by mutex objects for example.
[3045738]1332 *
[3657cde]1333 * @param the_thread The thread.
1334 *
1335 * @retval true The thread owns resources.
1336 * @retval false The thread does not own resources.
[6c7caa1a]1337 */
1338RTEMS_INLINE_ROUTINE bool _Thread_Owns_resources(
1339  const Thread_Control *the_thread
1340)
1341{
[97f7dac]1342  return the_thread->resource_count != 0;
[6c7caa1a]1343}
[47d2464]1344#endif
[6c7caa1a]1345
[351c14d]1346#if defined(RTEMS_SMP)
[3657cde]1347/**
1348 * @brief Cancels the thread's need for help.
1349 *
1350 * @param the_thread The thread to cancel the help request of.
1351 * @param cpu The cpu to get the lock context of in order to
1352 *      cancel the help request.
1353 */
[351c14d]1354RTEMS_INLINE_ROUTINE void _Thread_Scheduler_cancel_need_for_help(
1355  Thread_Control  *the_thread,
1356  Per_CPU_Control *cpu
1357)
1358{
[e97b7c9a]1359  ISR_lock_Context lock_context;
1360
1361  _Per_CPU_Acquire( cpu, &lock_context );
[351c14d]1362
1363  if ( !_Chain_Is_node_off_chain( &the_thread->Scheduler.Help_node ) ) {
1364    _Chain_Extract_unprotected( &the_thread->Scheduler.Help_node );
1365    _Chain_Set_off_chain( &the_thread->Scheduler.Help_node );
1366  }
1367
[e97b7c9a]1368  _Per_CPU_Release( cpu, &lock_context );
[351c14d]1369}
1370#endif
1371
[3657cde]1372/**
1373 * @brief Gets the home scheduler of the thread.
1374 *
1375 * @param the_thread The thread to get the home scheduler of.
1376 *
1377 * @return The thread's home scheduler.
1378 */
[2dd098a]1379RTEMS_INLINE_ROUTINE const Scheduler_Control *_Thread_Scheduler_get_home(
1380  const Thread_Control *the_thread
1381)
1382{
1383#if defined(RTEMS_SMP)
[7097962]1384  return the_thread->Scheduler.home_scheduler;
[2dd098a]1385#else
1386  (void) the_thread;
1387  return &_Scheduler_Table[ 0 ];
1388#endif
1389}
1390
[3657cde]1391/**
1392 * @brief Gets the scheduler's home node.
1393 *
1394 * @param the_thread The thread to get the home node of.
1395 *
1396 * @return The thread's home node.
1397 */
[f6142c19]1398RTEMS_INLINE_ROUTINE Scheduler_Node *_Thread_Scheduler_get_home_node(
1399  const Thread_Control *the_thread
1400)
1401{
1402#if defined(RTEMS_SMP)
1403  _Assert( !_Chain_Is_empty( &the_thread->Scheduler.Wait_nodes ) );
1404  return SCHEDULER_NODE_OF_THREAD_WAIT_NODE(
1405    _Chain_First( &the_thread->Scheduler.Wait_nodes )
1406  );
1407#else
1408  return the_thread->Scheduler.nodes;
1409#endif
1410}
1411
[3657cde]1412/**
1413 * @brief Gets the thread's scheduler node by index.
1414 *
1415 * @param the_thread The thread of which to get a scheduler node.
1416 * @param scheduler_index The index of the desired scheduler node.
1417 *
1418 * @return The scheduler node with the specified index.
1419 */
[5d6b211]1420RTEMS_INLINE_ROUTINE Scheduler_Node *_Thread_Scheduler_get_node_by_index(
1421  const Thread_Control *the_thread,
1422  size_t                scheduler_index
1423)
1424{
1425#if defined(RTEMS_SMP)
1426  return (Scheduler_Node *)
1427    ( (uintptr_t) the_thread->Scheduler.nodes
1428      + scheduler_index * _Scheduler_Node_size );
1429#else
1430  _Assert( scheduler_index == 0 );
1431  (void) scheduler_index;
1432  return the_thread->Scheduler.nodes;
[300f6a48]1433#endif
1434}
1435
[36d7aba]1436#if defined(RTEMS_SMP)
[3657cde]1437/**
1438 * @brief Acquires the lock context in a critical section.
1439 *
1440 * @param the_thread The thread to acquire the lock context.
1441 * @param lock_context The lock context.
1442 */
[07a32d19]1443RTEMS_INLINE_ROUTINE void _Thread_Scheduler_acquire_critical(
1444  Thread_Control   *the_thread,
1445  ISR_lock_Context *lock_context
1446)
1447{
1448  _ISR_lock_Acquire( &the_thread->Scheduler.Lock, lock_context );
1449}
1450
[3657cde]1451/**
1452 * @brief Releases the lock context in a critical section.
1453 *
1454 * @param the_thread The thread to release the lock context.
1455 * @param lock_context The lock context.
1456 */
[07a32d19]1457RTEMS_INLINE_ROUTINE void _Thread_Scheduler_release_critical(
1458  Thread_Control   *the_thread,
1459  ISR_lock_Context *lock_context
1460)
1461{
1462  _ISR_lock_Release( &the_thread->Scheduler.Lock, lock_context );
1463}
1464
[3657cde]1465/**
1466 * @brief Process the thread's scheduler requests.
1467 *
1468 * @param[in, out] the_thread The thread for the operation.
1469 */
[2403473]1470void _Thread_Scheduler_process_requests( Thread_Control *the_thread );
1471
[3657cde]1472/**
1473 * @brief Add a scheduler request to the thread.
1474 *
1475 * @param[in, out] the_thread The thread to add a scheduler request to.
1476 * @param[in, out] scheduler_node The scheduler node for the request.
1477 * @param request The request to add.
1478 */
[ebdd2a3]1479RTEMS_INLINE_ROUTINE void _Thread_Scheduler_add_request(
1480  Thread_Control         *the_thread,
1481  Scheduler_Node         *scheduler_node,
1482  Scheduler_Node_request  request
1483)
1484{
1485  ISR_lock_Context       lock_context;
1486  Scheduler_Node_request current_request;
1487
1488  _Thread_Scheduler_acquire_critical( the_thread, &lock_context );
1489
1490  current_request = scheduler_node->Thread.request;
1491
1492  if ( current_request == SCHEDULER_NODE_REQUEST_NOT_PENDING ) {
1493    _Assert(
1494      request == SCHEDULER_NODE_REQUEST_ADD
1495        || request == SCHEDULER_NODE_REQUEST_REMOVE
1496    );
1497    _Assert( scheduler_node->Thread.next_request == NULL );
1498    scheduler_node->Thread.next_request = the_thread->Scheduler.requests;
1499    the_thread->Scheduler.requests = scheduler_node;
1500  } else if ( current_request != SCHEDULER_NODE_REQUEST_NOTHING ) {
1501    _Assert(
1502      ( current_request == SCHEDULER_NODE_REQUEST_ADD
1503        && request == SCHEDULER_NODE_REQUEST_REMOVE )
1504      || ( current_request == SCHEDULER_NODE_REQUEST_REMOVE
1505        && request == SCHEDULER_NODE_REQUEST_ADD )
1506    );
1507    request = SCHEDULER_NODE_REQUEST_NOTHING;
1508  }
1509
1510  scheduler_node->Thread.request = request;
1511
1512  _Thread_Scheduler_release_critical( the_thread, &lock_context );
1513}
1514
[3657cde]1515/**
1516 * @brief Adds a wait node to the thread and adds a corresponding
1517 *      request to the thread.
1518 *
1519 * @param[in, out] the_thread The thread to add the wait node to.
1520 * @param scheduler_node The scheduler node which provides the wait node.
1521 */
[36d7aba]1522RTEMS_INLINE_ROUTINE void _Thread_Scheduler_add_wait_node(
1523  Thread_Control *the_thread,
1524  Scheduler_Node *scheduler_node
1525)
1526{
1527  _Chain_Append_unprotected(
1528    &the_thread->Scheduler.Wait_nodes,
1529    &scheduler_node->Thread.Wait_node
1530  );
[ebdd2a3]1531  _Thread_Scheduler_add_request(
1532    the_thread,
1533    scheduler_node,
1534    SCHEDULER_NODE_REQUEST_ADD
1535  );
[36d7aba]1536}
[70c22d93]1537
[3657cde]1538/**
1539 * @brief Remove a wait node from the thread and add a corresponding request to
1540 *      it.
1541 *
1542 * @param the_thread The thread to add the request to remove a wait node.
1543 * @param scheduler_node The scheduler node to remove a wait node from.
1544 */
[70c22d93]1545RTEMS_INLINE_ROUTINE void _Thread_Scheduler_remove_wait_node(
1546  Thread_Control *the_thread,
1547  Scheduler_Node *scheduler_node
1548)
1549{
1550  _Chain_Extract_unprotected( &scheduler_node->Thread.Wait_node );
[ebdd2a3]1551  _Thread_Scheduler_add_request(
1552    the_thread,
1553    scheduler_node,
1554    SCHEDULER_NODE_REQUEST_REMOVE
1555  );
[70c22d93]1556}
[36d7aba]1557#endif
1558
[b20b736]1559/**
1560 * @brief Returns the priority of the thread.
1561 *
1562 * Returns the user API and thread wait information relevant thread priority.
1563 * This includes temporary thread priority adjustments due to locking
1564 * protocols, a job release or the POSIX sporadic server for example.
1565 *
[3657cde]1566 * @param the_thread The thread of which to get the priority.
1567 *
[b20b736]1568 * @return The priority of the thread.
1569 */
1570RTEMS_INLINE_ROUTINE Priority_Control _Thread_Get_priority(
1571  const Thread_Control *the_thread
1572)
1573{
[300f6a48]1574  Scheduler_Node *scheduler_node;
1575
[7f742432]1576  scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
[300f6a48]1577  return _Priority_Get_priority( &scheduler_node->Wait.Priority );
[b20b736]1578}
1579
[5803f37]1580/**
1581 * @brief Returns the unmapped priority of the thread.
1582 *
1583 * @param the_thread The thread of which to get the unmapped priority.
1584 *
1585 * @return The unmapped priority of the thread.
1586 */
1587RTEMS_INLINE_ROUTINE Priority_Control _Thread_Get_unmapped_priority(
1588  const Thread_Control *the_thread
1589)
1590{
1591  return SCHEDULER_PRIORITY_UNMAP( _Thread_Get_priority( the_thread ) );
1592}
1593
1594/**
1595 * @brief Returns the unmapped real priority of the thread.
1596 *
1597 * @param the_thread The thread of which to get the unmapped real priority.
1598 *
1599 * @return The unmapped real priority of the thread.
1600 */
1601RTEMS_INLINE_ROUTINE Priority_Control _Thread_Get_unmapped_real_priority(
1602  const Thread_Control *the_thread
1603)
1604{
1605  return SCHEDULER_PRIORITY_UNMAP( the_thread->Real_priority.priority );
1606}
1607
[1041de1]1608/**
[1fcac5ad]1609 * @brief Acquires the thread wait default lock inside a critical section
[0e3c59d6]1610 * (interrupts disabled).
[1041de1]1611 *
[3657cde]1612 * @param[in, out] the_thread The thread.
1613 * @param lock_context The lock context used for the corresponding lock
[1fcac5ad]1614 *   release.
[1041de1]1615 *
[1fcac5ad]1616 * @see _Thread_Wait_release_default_critical().
[1041de1]1617 */
[1fcac5ad]1618RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_default_critical(
[0e3c59d6]1619  Thread_Control   *the_thread,
[1041de1]1620  ISR_lock_Context *lock_context
1621)
1622{
[1fcac5ad]1623  _ISR_lock_Acquire( &the_thread->Wait.Lock.Default, lock_context );
[1041de1]1624}
1625
1626/**
[1fcac5ad]1627 * @brief Acquires the thread wait default lock and returns the executing
1628 * thread.
[1041de1]1629 *
[3657cde]1630 * @param lock_context The lock context used for the corresponding lock
[1fcac5ad]1631 *   release.
[1041de1]1632 *
[0e3c59d6]1633 * @return The executing thread.
1634 *
[1fcac5ad]1635 * @see _Thread_Wait_release_default().
[1041de1]1636 */
[1fcac5ad]1637RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Wait_acquire_default_for_executing(
[1041de1]1638  ISR_lock_Context *lock_context
1639)
1640{
[0e3c59d6]1641  Thread_Control *executing;
1642
1643  _ISR_lock_ISR_disable( lock_context );
1644  executing = _Thread_Executing;
[1fcac5ad]1645  _Thread_Wait_acquire_default_critical( executing, lock_context );
[0e3c59d6]1646
1647  return executing;
[1041de1]1648}
1649
1650/**
[1fcac5ad]1651 * @brief Acquires the thread wait default lock and disables interrupts.
[1041de1]1652 *
[3657cde]1653 * @param[in, out] the_thread The thread.
1654 * @param[out] lock_context The lock context used for the corresponding lock
[1fcac5ad]1655 *   release.
[1041de1]1656 *
[1fcac5ad]1657 * @see _Thread_Wait_release_default().
[1041de1]1658 */
[1fcac5ad]1659RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_default(
[1041de1]1660  Thread_Control   *the_thread,
1661  ISR_lock_Context *lock_context
1662)
1663{
[0e3c59d6]1664  _ISR_lock_ISR_disable( lock_context );
[1fcac5ad]1665  _Thread_Wait_acquire_default_critical( the_thread, lock_context );
[1041de1]1666}
1667
1668/**
[1fcac5ad]1669 * @brief Releases the thread wait default lock inside a critical section
1670 * (interrupts disabled).
[1041de1]1671 *
[f5d4570f]1672 * The previous interrupt status is not restored.
1673 *
[3657cde]1674 * @param[in, out] the_thread The thread.
1675 * @param lock_context The lock context used for the corresponding lock
[1fcac5ad]1676 *   acquire.
[1041de1]1677 */
[1fcac5ad]1678RTEMS_INLINE_ROUTINE void _Thread_Wait_release_default_critical(
1679  Thread_Control   *the_thread,
[1041de1]1680  ISR_lock_Context *lock_context
1681)
1682{
[1fcac5ad]1683  _ISR_lock_Release( &the_thread->Wait.Lock.Default, lock_context );
[1041de1]1684}
1685
[57947f1]1686/**
[1fcac5ad]1687 * @brief Releases the thread wait default lock and restores the previous
1688 * interrupt status.
[57947f1]1689 *
[3657cde]1690 * @param[in, out] the_thread The thread.
1691 * @param[out] lock_context The lock context used for the corresponding lock
[1fcac5ad]1692 *   acquire.
[57947f1]1693 */
[1fcac5ad]1694RTEMS_INLINE_ROUTINE void _Thread_Wait_release_default(
1695  Thread_Control   *the_thread,
[57947f1]1696  ISR_lock_Context *lock_context
1697)
1698{
[1fcac5ad]1699  _Thread_Wait_release_default_critical( the_thread, lock_context );
[f5d4570f]1700  _ISR_lock_ISR_enable( lock_context );
1701}
1702
[1fcac5ad]1703#if defined(RTEMS_SMP)
1704#define THREAD_QUEUE_CONTEXT_OF_REQUEST( node ) \
[e41308ea]1705  RTEMS_CONTAINER_OF( node, Thread_queue_Context, Lock_context.Wait.Gate.Node )
[1fcac5ad]1706
[3657cde]1707/**
1708 * @brief Removes the first pending wait lock request.
1709 *
1710 * @param the_thread The thread to remove the request from.
1711 * @param queue_lock_context The queue lock context.
1712 */
[1fcac5ad]1713RTEMS_INLINE_ROUTINE void _Thread_Wait_remove_request_locked(
[e41308ea]1714  Thread_Control            *the_thread,
1715  Thread_queue_Lock_context *queue_lock_context
[1fcac5ad]1716)
1717{
[ff2e6c64]1718  Chain_Node *first;
[1fcac5ad]1719
[e41308ea]1720  _Chain_Extract_unprotected( &queue_lock_context->Wait.Gate.Node );
[ff2e6c64]1721  first = _Chain_First( &the_thread->Wait.Lock.Pending_requests );
[1fcac5ad]1722
[ff2e6c64]1723  if ( first != _Chain_Tail( &the_thread->Wait.Lock.Pending_requests ) ) {
1724    _Thread_queue_Gate_open( (Thread_queue_Gate *) first );
[1fcac5ad]1725  }
1726}
1727
[3657cde]1728/**
1729 * @brief Acquires the wait queue inside a critical section.
1730 *
1731 * @param queue The queue that acquires.
1732 * @param queue_lock_context The queue lock context.
1733 */
[1fcac5ad]1734RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_queue_critical(
[e41308ea]1735  Thread_queue_Queue        *queue,
1736  Thread_queue_Lock_context *queue_lock_context
[1fcac5ad]1737)
1738{
[ff2e6c64]1739  _Thread_queue_Queue_acquire_critical(
1740    queue,
[1fcac5ad]1741    &_Thread_Executing->Potpourri_stats,
[e41308ea]1742    &queue_lock_context->Lock_context
[1fcac5ad]1743  );
1744}
1745
[3657cde]1746/**
1747 * @brief Releases the wait queue inside a critical section.
1748 *
1749 * @param queue The queue that releases.
1750 * @param queue_lock_context The queue lock context.
1751 */
[1fcac5ad]1752RTEMS_INLINE_ROUTINE void _Thread_Wait_release_queue_critical(
[e41308ea]1753  Thread_queue_Queue        *queue,
1754  Thread_queue_Lock_context *queue_lock_context
[1fcac5ad]1755)
1756{
[ff2e6c64]1757  _Thread_queue_Queue_release_critical(
1758    queue,
[e41308ea]1759    &queue_lock_context->Lock_context
[1fcac5ad]1760  );
1761}
1762#endif
1763
[f5d4570f]1764/**
[1fcac5ad]1765 * @brief Acquires the thread wait lock inside a critical section (interrupts
1766 * disabled).
[f5d4570f]1767 *
[3657cde]1768 * @param[in, out] the_thread The thread.
1769 * @param[in, out] queue_context The thread queue context for the corresponding
[1fcac5ad]1770 *   _Thread_Wait_release_critical().
[f5d4570f]1771 */
[1fcac5ad]1772RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_critical(
1773  Thread_Control       *the_thread,
1774  Thread_queue_Context *queue_context
[f5d4570f]1775)
1776{
1777#if defined(RTEMS_SMP)
[1fcac5ad]1778  Thread_queue_Queue *queue;
1779
1780  _Thread_Wait_acquire_default_critical(
1781    the_thread,
[e41308ea]1782    &queue_context->Lock_context.Lock_context
[1fcac5ad]1783  );
1784
1785  queue = the_thread->Wait.queue;
[e41308ea]1786  queue_context->Lock_context.Wait.queue = queue;
[1fcac5ad]1787
1788  if ( queue != NULL ) {
[ff2e6c64]1789    _Thread_queue_Gate_add(
[1fcac5ad]1790      &the_thread->Wait.Lock.Pending_requests,
[e41308ea]1791      &queue_context->Lock_context.Wait.Gate
[1fcac5ad]1792    );
1793    _Thread_Wait_release_default_critical(
1794      the_thread,
[e41308ea]1795      &queue_context->Lock_context.Lock_context
[1fcac5ad]1796    );
[e41308ea]1797    _Thread_Wait_acquire_queue_critical( queue, &queue_context->Lock_context );
[ff2e6c64]1798
[e41308ea]1799    if ( queue_context->Lock_context.Wait.queue == NULL ) {
1800      _Thread_Wait_release_queue_critical(
1801        queue,
1802        &queue_context->Lock_context
1803      );
[ff2e6c64]1804      _Thread_Wait_acquire_default_critical(
[e41308ea]1805        the_thread,
1806        &queue_context->Lock_context.Lock_context
1807      );
1808      _Thread_Wait_remove_request_locked(
[ff2e6c64]1809        the_thread,
1810        &queue_context->Lock_context
1811      );
1812      _Assert( the_thread->Wait.queue == NULL );
1813    }
[1fcac5ad]1814  }
[f5d4570f]1815#else
[1fcac5ad]1816  (void) the_thread;
1817  (void) queue_context;
[f5d4570f]1818#endif
1819}
1820
1821/**
[1fcac5ad]1822 * @brief Acquires the thread wait default lock and disables interrupts.
[f5d4570f]1823 *
[3657cde]1824 * @param[in, out] the_thread The thread.
1825 * @param[in, out] queue_context The thread queue context for the corresponding
[1fcac5ad]1826 *   _Thread_Wait_release().
[f5d4570f]1827 */
[1fcac5ad]1828RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire(
1829  Thread_Control       *the_thread,
1830  Thread_queue_Context *queue_context
[f5d4570f]1831)
1832{
[e41308ea]1833  _ISR_lock_ISR_disable( &queue_context->Lock_context.Lock_context );
[1fcac5ad]1834  _Thread_Wait_acquire_critical( the_thread, queue_context );
[57947f1]1835}
1836
1837/**
[1fcac5ad]1838 * @brief Releases the thread wait lock inside a critical section (interrupts
1839 * disabled).
[57947f1]1840 *
[1fcac5ad]1841 * The previous interrupt status is not restored.
[57947f1]1842 *
[3657cde]1843 * @param[in, out] the_thread The thread.
1844 * @param[in, out] queue_context The thread queue context used for corresponding
[1fcac5ad]1845 *   _Thread_Wait_acquire_critical().
[57947f1]1846 */
[1fcac5ad]1847RTEMS_INLINE_ROUTINE void _Thread_Wait_release_critical(
1848  Thread_Control       *the_thread,
1849  Thread_queue_Context *queue_context
[57947f1]1850)
1851{
1852#if defined(RTEMS_SMP)
[ff2e6c64]1853  Thread_queue_Queue *queue;
[c6556e2e]1854
[e41308ea]1855  queue = queue_context->Lock_context.Wait.queue;
[57947f1]1856
[ff2e6c64]1857  if ( queue != NULL ) {
[e41308ea]1858    _Thread_Wait_release_queue_critical(
1859      queue, &queue_context->Lock_context
1860    );
[1fcac5ad]1861    _Thread_Wait_acquire_default_critical(
[e41308ea]1862      the_thread,
1863      &queue_context->Lock_context.Lock_context
1864    );
1865    _Thread_Wait_remove_request_locked(
[1fcac5ad]1866      the_thread,
1867      &queue_context->Lock_context
[b6b25a9]1868    );
[57947f1]1869  }
1870
[1fcac5ad]1871  _Thread_Wait_release_default_critical(
1872    the_thread,
[e41308ea]1873    &queue_context->Lock_context.Lock_context
[1fcac5ad]1874  );
1875#else
1876  (void) the_thread;
1877  (void) queue_context;
[57947f1]1878#endif
1879}
1880
[1fcac5ad]1881/**
1882 * @brief Releases the thread wait lock and restores the previous interrupt
1883 * status.
1884 *
[3657cde]1885 * @param[in, out] the_thread The thread.
1886 * @param[in, out] queue_context The thread queue context used for corresponding
[1fcac5ad]1887 *   _Thread_Wait_acquire().
[57947f1]1888 */
[1fcac5ad]1889RTEMS_INLINE_ROUTINE void _Thread_Wait_release(
1890  Thread_Control       *the_thread,
1891  Thread_queue_Context *queue_context
[57947f1]1892)
1893{
[1fcac5ad]1894  _Thread_Wait_release_critical( the_thread, queue_context );
[e41308ea]1895  _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
[57947f1]1896}
1897
1898/**
[f6142c19]1899 * @brief Claims the thread wait queue.
[57947f1]1900 *
[1fcac5ad]1901 * The caller must not be the owner of the default thread wait lock.  The
[f6142c19]1902 * caller must be the owner of the corresponding thread queue lock.  The
1903 * registration of the corresponding thread queue operations is deferred and
1904 * done after the deadlock detection.  This is crucial to support timeouts on
1905 * SMP configurations.
[57947f1]1906 *
[3657cde]1907 * @param[in, out] the_thread The thread.
1908 * @param[in, out] queue The new thread queue.
[1fcac5ad]1909 *
[f6142c19]1910 * @see _Thread_Wait_claim_finalize() and _Thread_Wait_restore_default().
[57947f1]1911 */
[1fcac5ad]1912RTEMS_INLINE_ROUTINE void _Thread_Wait_claim(
[f6142c19]1913  Thread_Control     *the_thread,
1914  Thread_queue_Queue *queue
[57947f1]1915)
1916{
[f5d4570f]1917  ISR_lock_Context lock_context;
[57947f1]1918
[1fcac5ad]1919  _Thread_Wait_acquire_default_critical( the_thread, &lock_context );
1920
1921  _Assert( the_thread->Wait.queue == NULL );
[ff2e6c64]1922
1923#if defined(RTEMS_SMP)
1924  _Chain_Initialize_empty( &the_thread->Wait.Lock.Pending_requests );
1925  _Chain_Initialize_node( &the_thread->Wait.Lock.Tranquilizer.Node );
1926  _Thread_queue_Gate_close( &the_thread->Wait.Lock.Tranquilizer );
1927#endif
1928
[1fcac5ad]1929  the_thread->Wait.queue = queue;
1930
1931  _Thread_Wait_release_default_critical( the_thread, &lock_context );
[57947f1]1932}
[1fcac5ad]1933
[f6142c19]1934/**
1935 * @brief Finalizes the thread wait queue claim via registration of the
1936 * corresponding thread queue operations.
1937 *
[3657cde]1938 * @param[in, out] the_thread The thread.
1939 * @param operations The corresponding thread queue operations.
[f6142c19]1940 */
1941RTEMS_INLINE_ROUTINE void _Thread_Wait_claim_finalize(
1942  Thread_Control                *the_thread,
1943  const Thread_queue_Operations *operations
1944)
1945{
1946  the_thread->Wait.operations = operations;
1947}
1948
[1fcac5ad]1949/**
1950 * @brief Removes a thread wait lock request.
1951 *
1952 * On SMP configurations, removes a thread wait lock request.
1953 *
1954 * On other configurations, this function does nothing.
1955 *
[3657cde]1956 * @param[in, out] the_thread The thread.
1957 * @param[in, out] queue_lock_context The thread queue lock context used for
[e41308ea]1958 *   corresponding _Thread_Wait_acquire().
[1fcac5ad]1959 */
1960RTEMS_INLINE_ROUTINE void _Thread_Wait_remove_request(
[e41308ea]1961  Thread_Control            *the_thread,
1962  Thread_queue_Lock_context *queue_lock_context
[1fcac5ad]1963)
1964{
1965#if defined(RTEMS_SMP)
1966  ISR_lock_Context lock_context;
1967
1968  _Thread_Wait_acquire_default( the_thread, &lock_context );
[e41308ea]1969  _Thread_Wait_remove_request_locked( the_thread, queue_lock_context );
[1fcac5ad]1970  _Thread_Wait_release_default( the_thread, &lock_context );
[57947f1]1971#else
[1fcac5ad]1972  (void) the_thread;
[e41308ea]1973  (void) queue_lock_context;
[57947f1]1974#endif
[1fcac5ad]1975}
[57947f1]1976
1977/**
[1fcac5ad]1978 * @brief Restores the default thread wait queue and operations.
1979 *
1980 * The caller must be the owner of the current thread wait queue lock.
[57947f1]1981 *
[1fcac5ad]1982 * On SMP configurations, the pending requests are updated to use the stale
1983 * thread queue operations.
[57947f1]1984 *
[3657cde]1985 * @param[in, out] the_thread The thread.
[1fcac5ad]1986 *
1987 * @see _Thread_Wait_claim().
[57947f1]1988 */
[1fcac5ad]1989RTEMS_INLINE_ROUTINE void _Thread_Wait_restore_default(
[57947f1]1990  Thread_Control *the_thread
1991)
1992{
[1fcac5ad]1993#if defined(RTEMS_SMP)
1994  ISR_lock_Context  lock_context;
1995  Chain_Node       *node;
1996  const Chain_Node *tail;
1997
[ff2e6c64]1998  _Thread_Wait_acquire_default_critical( the_thread, &lock_context );
[1fcac5ad]1999
2000  node = _Chain_First( &the_thread->Wait.Lock.Pending_requests );
2001  tail = _Chain_Immutable_tail( &the_thread->Wait.Lock.Pending_requests );
2002
[ff2e6c64]2003  if ( node != tail ) {
2004    do {
2005      Thread_queue_Context *queue_context;
[1fcac5ad]2006
[ff2e6c64]2007      queue_context = THREAD_QUEUE_CONTEXT_OF_REQUEST( node );
[e41308ea]2008      queue_context->Lock_context.Wait.queue = NULL;
[1fcac5ad]2009
[ff2e6c64]2010      node = _Chain_Next( node );
2011    } while ( node != tail );
2012
2013    _Thread_queue_Gate_add(
2014      &the_thread->Wait.Lock.Pending_requests,
2015      &the_thread->Wait.Lock.Tranquilizer
2016    );
2017  } else {
2018    _Thread_queue_Gate_open( &the_thread->Wait.Lock.Tranquilizer );
[1fcac5ad]2019  }
2020#endif
2021
2022  the_thread->Wait.queue = NULL;
2023  the_thread->Wait.operations = &_Thread_queue_Operations_default;
2024
2025#if defined(RTEMS_SMP)
[ff2e6c64]2026  _Thread_Wait_release_default_critical( the_thread, &lock_context );
[1fcac5ad]2027#endif
[57947f1]2028}
[1fcac5ad]2029
2030/**
[ff2e6c64]2031 * @brief Tranquilizes the thread after a wait on a thread queue.
[1fcac5ad]2032 *
2033 * After the violent blocking procedure this function makes the thread calm and
2034 * peaceful again so that it can carry out its normal work.
2035 *
2036 * On SMP configurations, ensures that all pending thread wait lock requests
2037 * completed before the thread is able to begin a new thread wait procedure.
2038 *
2039 * On other configurations, this function does nothing.
2040 *
[ff2e6c64]2041 * It must be called after a _Thread_Wait_claim() exactly once
2042 *  - after the corresponding thread queue lock was released, and
2043 *  - the default wait state is restored or some other processor is about to do
2044 *    this.
2045 *
[3657cde]2046 * @param the_thread The thread.
[1fcac5ad]2047 */
2048RTEMS_INLINE_ROUTINE void _Thread_Wait_tranquilize(
2049  Thread_Control *the_thread
2050)
2051{
2052#if defined(RTEMS_SMP)
[ff2e6c64]2053  _Thread_queue_Gate_wait( &the_thread->Wait.Lock.Tranquilizer );
[57947f1]2054#else
[1fcac5ad]2055  (void) the_thread;
[57947f1]2056#endif
[1fcac5ad]2057}
2058
2059/**
2060 * @brief Cancels a thread wait on a thread queue.
2061 *
[3657cde]2062 * @param[in, out] the_thread The thread.
2063 * @param queue_context The thread queue context used for corresponding
[1fcac5ad]2064 *   _Thread_Wait_acquire().
2065 */
2066RTEMS_INLINE_ROUTINE void _Thread_Wait_cancel(
2067  Thread_Control       *the_thread,
2068  Thread_queue_Context *queue_context
2069)
2070{
[ff2e6c64]2071  Thread_queue_Queue *queue;
2072
2073  queue = the_thread->Wait.queue;
[1fcac5ad]2074
2075#if defined(RTEMS_SMP)
[ff2e6c64]2076  if ( queue != NULL ) {
[e41308ea]2077    _Assert( queue_context->Lock_context.Wait.queue == queue );
[1fcac5ad]2078#endif
[ff2e6c64]2079
[300f6a48]2080    ( *the_thread->Wait.operations->extract )(
2081      queue,
2082      the_thread,
2083      queue_context
2084    );
[1fcac5ad]2085    _Thread_Wait_restore_default( the_thread );
[ff2e6c64]2086
[1fcac5ad]2087#if defined(RTEMS_SMP)
[e41308ea]2088    _Assert( queue_context->Lock_context.Wait.queue == NULL );
2089    queue_context->Lock_context.Wait.queue = queue;
[1fcac5ad]2090  }
2091#endif
2092}
[57947f1]2093
[4c8a0ac]2094/**
2095 * @brief The initial thread wait flags value set by _Thread_Initialize().
2096 */
2097#define THREAD_WAIT_FLAGS_INITIAL 0x0U
2098
2099/**
2100 * @brief Mask to get the thread wait state flags.
2101 */
2102#define THREAD_WAIT_STATE_MASK 0xffU
2103
2104/**
2105 * @brief Indicates that the thread begins with the blocking operation.
2106 *
2107 * A blocking operation consists of an optional watchdog initialization and the
2108 * setting of the appropriate thread blocking state with the corresponding
2109 * scheduler block operation.
2110 */
2111#define THREAD_WAIT_STATE_INTEND_TO_BLOCK 0x1U
2112
2113/**
2114 * @brief Indicates that the thread completed the blocking operation.
2115 */
2116#define THREAD_WAIT_STATE_BLOCKED 0x2U
2117
2118/**
[b7cff7fe]2119 * @brief Indicates that a condition to end the thread wait occurred.
2120 *
2121 * This could be a timeout, a signal, an event or a resource availability.
[4c8a0ac]2122 */
[b7cff7fe]2123#define THREAD_WAIT_STATE_READY_AGAIN 0x4U
[4c8a0ac]2124
2125/**
2126 * @brief Mask to get the thread wait class flags.
2127 */
2128#define THREAD_WAIT_CLASS_MASK 0xff00U
2129
2130/**
2131 * @brief Indicates that the thread waits for an event.
2132 */
2133#define THREAD_WAIT_CLASS_EVENT 0x100U
2134
2135/**
2136 * @brief Indicates that the thread waits for a system event.
2137 */
2138#define THREAD_WAIT_CLASS_SYSTEM_EVENT 0x200U
2139
2140/**
[90960bd]2141 * @brief Indicates that the thread waits for an object.
[4c8a0ac]2142 */
2143#define THREAD_WAIT_CLASS_OBJECT 0x400U
2144
[90960bd]2145/**
2146 * @brief Indicates that the thread waits for a period.
2147 */
2148#define THREAD_WAIT_CLASS_PERIOD 0x800U
2149
[3657cde]2150/**
2151 * @brief Sets the thread's wait flags.
2152 *
2153 * @param[in, out] the_thread The thread to set the wait flags of.
2154 * @param flags The flags to set.
2155 */
[4c8a0ac]2156RTEMS_INLINE_ROUTINE void _Thread_Wait_flags_set(
2157  Thread_Control    *the_thread,
2158  Thread_Wait_flags  flags
2159)
2160{
2161#if defined(RTEMS_SMP)
2162  _Atomic_Store_uint( &the_thread->Wait.flags, flags, ATOMIC_ORDER_RELAXED );
2163#else
2164  the_thread->Wait.flags = flags;
2165#endif
2166}
2167
[3657cde]2168/**
2169 * @brief Gets the thread's wait flags according to the ATOMIC_ORDER_RELAXED.
2170 *
2171 * @param the_thread The thread to get the wait flags of.
2172 *
2173 * @return The thread's wait flags.
2174 */
[4c8a0ac]2175RTEMS_INLINE_ROUTINE Thread_Wait_flags _Thread_Wait_flags_get(
2176  const Thread_Control *the_thread
2177)
2178{
2179#if defined(RTEMS_SMP)
2180  return _Atomic_Load_uint( &the_thread->Wait.flags, ATOMIC_ORDER_RELAXED );
2181#else
2182  return the_thread->Wait.flags;
2183#endif
2184}
2185
[3657cde]2186/**
2187 * @brief Gets the thread's wait flags according to the ATOMIC_ORDER_ACQUIRE.
2188 *
2189 * @param the_thread The thread to get the wait flags of.
2190 *
2191 * @return The thread's wait flags.
2192 */
[3a27248]2193RTEMS_INLINE_ROUTINE Thread_Wait_flags _Thread_Wait_flags_get_acquire(
2194  const Thread_Control *the_thread
2195)
2196{
2197#if defined(RTEMS_SMP)
2198  return _Atomic_Load_uint( &the_thread->Wait.flags, ATOMIC_ORDER_ACQUIRE );
2199#else
2200  return the_thread->Wait.flags;
2201#endif
2202}
2203
[4c8a0ac]2204/**
[02987728]2205 * @brief Tries to change the thread wait flags with release semantics in case
2206 * of success.
2207 *
2208 * Must be called inside a critical section (interrupts disabled).
[4c8a0ac]2209 *
2210 * In case the wait flags are equal to the expected wait flags, then the wait
2211 * flags are set to the desired wait flags.
2212 *
[3657cde]2213 * @param the_thread The thread.
2214 * @param expected_flags The expected wait flags.
2215 * @param desired_flags The desired wait flags.
[4c8a0ac]2216 *
2217 * @retval true The wait flags were equal to the expected wait flags.
[3657cde]2218 * @retval false The wait flags were not equal to the expected wait flags.
[4c8a0ac]2219 */
[02987728]2220RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change_release(
[4c8a0ac]2221  Thread_Control    *the_thread,
2222  Thread_Wait_flags  expected_flags,
2223  Thread_Wait_flags  desired_flags
2224)
2225{
[02987728]2226  _Assert( _ISR_Get_level() != 0 );
2227
[4c8a0ac]2228#if defined(RTEMS_SMP)
2229  return _Atomic_Compare_exchange_uint(
2230    &the_thread->Wait.flags,
2231    &expected_flags,
2232    desired_flags,
[02987728]2233    ATOMIC_ORDER_RELEASE,
[4c8a0ac]2234    ATOMIC_ORDER_RELAXED
2235  );
2236#else
[02987728]2237  bool success = ( the_thread->Wait.flags == expected_flags );
[4c8a0ac]2238
2239  if ( success ) {
2240    the_thread->Wait.flags = desired_flags;
2241  }
2242
2243  return success;
2244#endif
2245}
2246
2247/**
[02987728]2248 * @brief Tries to change the thread wait flags with acquire semantics.
2249 *
2250 * In case the wait flags are equal to the expected wait flags, then the wait
2251 * flags are set to the desired wait flags.
2252 *
[3657cde]2253 * @param the_thread The thread.
2254 * @param expected_flags The expected wait flags.
2255 * @param desired_flags The desired wait flags.
[4c8a0ac]2256 *
[02987728]2257 * @retval true The wait flags were equal to the expected wait flags.
[3657cde]2258 * @retval false The wait flags were not equal to the expected wait flags.
[4c8a0ac]2259 */
[02987728]2260RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change_acquire(
[4c8a0ac]2261  Thread_Control    *the_thread,
2262  Thread_Wait_flags  expected_flags,
2263  Thread_Wait_flags  desired_flags
2264)
2265{
[02987728]2266#if defined(RTEMS_SMP)
2267  return _Atomic_Compare_exchange_uint(
2268    &the_thread->Wait.flags,
2269    &expected_flags,
2270    desired_flags,
2271    ATOMIC_ORDER_ACQUIRE,
2272    ATOMIC_ORDER_ACQUIRE
2273  );
2274#else
[da0cbef2]2275  bool      success;
[4c8a0ac]2276  ISR_Level level;
2277
[4b04cb61]2278  _ISR_Local_disable( level );
[4c8a0ac]2279
[02987728]2280  success = _Thread_Wait_flags_try_change_release(
[4c8a0ac]2281    the_thread,
2282    expected_flags,
2283    desired_flags
2284  );
2285
[4b04cb61]2286  _ISR_Local_enable( level );
[4c8a0ac]2287  return success;
[da0cbef2]2288#endif
[4c8a0ac]2289}
2290
[97312fcc]2291/**
2292 * @brief Returns the object identifier of the object containing the current
2293 * thread wait queue.
2294 *
2295 * This function may be used for debug and system information purposes.  The
2296 * caller must be the owner of the thread lock.
2297 *
[3657cde]2298 * @param the_thread The thread.
2299 *
[97312fcc]2300 * @retval 0 The thread waits on no thread queue currently, the thread wait
2301 *   queue is not contained in an object, or the current thread state provides
2302 *   insufficient information, e.g. the thread is in the middle of a blocking
2303 *   operation.
2304 * @retval other The object identifier of the object containing the thread wait
2305 *   queue.
2306 */
2307Objects_Id _Thread_Wait_get_id( const Thread_Control *the_thread );
2308
[3657cde]2309/**
2310 * @brief Get the status of the wait return code of the thread.
2311 *
2312 * @param the_thread The thread to get the status of the wait return code of.
2313 */
[dce48791]2314RTEMS_INLINE_ROUTINE Status_Control _Thread_Wait_get_status(
2315  const Thread_Control *the_thread
2316)
2317{
2318  return (Status_Control) the_thread->Wait.return_code;
2319}
2320
[6de1f92]2321/**
2322 * @brief Cancels a blocking operation so that the thread can continue its
2323 * execution.
2324 *
2325 * In case this function actually cancelled the blocking operation, then the
2326 * thread wait return code is set to the specified status.
2327 *
2328 * A specialization of this function is _Thread_Timeout().
2329 *
[3657cde]2330 * @param[in, out] the_thread The thread.
2331 * @param status The thread wait status.
[6de1f92]2332 */
2333void _Thread_Continue( Thread_Control *the_thread, Status_Control status );
2334
[08fe84b]2335/**
2336 * @brief General purpose thread wait timeout.
2337 *
[3657cde]2338 * @param the_watchdog The thread timer watchdog.
[08fe84b]2339 */
[6de1f92]2340void _Thread_Timeout( Watchdog_Control *the_watchdog );
[03b900d]2341
[3657cde]2342/**
2343 * @brief Initializes the thread timer.
2344 *
2345 * @param [in, out] timer The timer to initialize.
2346 * @param cpu The cpu for the operation.
2347 */
[16832b0]2348RTEMS_INLINE_ROUTINE void _Thread_Timer_initialize(
2349  Thread_Timer_information *timer,
2350  Per_CPU_Control          *cpu
2351)
2352{
2353  _ISR_lock_Initialize( &timer->Lock, "Thread Timer" );
[9480815a]2354  timer->header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
[16832b0]2355  _Watchdog_Preinitialize( &timer->Watchdog, cpu );
2356}
2357
[3657cde]2358/**
2359 * @brief Adds timeout ticks to the thread.
2360 *
2361 * @param[in, out] the_thread The thread to add the timeout ticks to.
2362 * @param cpu The cpu for the operation.
2363 * @param ticks The ticks to add to the timeout ticks.
2364 */
[02878626]2365RTEMS_INLINE_ROUTINE void _Thread_Add_timeout_ticks(
2366  Thread_Control    *the_thread,
2367  Per_CPU_Control   *cpu,
2368  Watchdog_Interval  ticks
[03b900d]2369)
2370{
2371  ISR_lock_Context lock_context;
2372
2373  _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
2374
[00c620c]2375  the_thread->Timer.header =
[9480815a]2376    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
[02878626]2377  the_thread->Timer.Watchdog.routine = _Thread_Timeout;
[91ce012c]2378  _Watchdog_Per_CPU_insert_ticks( &the_thread->Timer.Watchdog, cpu, ticks );
[03b900d]2379
2380  _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
2381}
2382
[3657cde]2383/**
2384 * @brief Inserts the cpu's watchdog realtime into the thread's timer.
2385 *
2386 * @param[in, out] the_thread for the operation.
2387 * @param cpu The cpu to get the watchdog header from.
2388 * @param routine The watchdog routine for the thread.
2389 * @param expire Expiration for the watchdog.
2390 */
[bf2a53d2]2391RTEMS_INLINE_ROUTINE void _Thread_Timer_insert_realtime(
[03b900d]2392  Thread_Control                 *the_thread,
2393  Per_CPU_Control                *cpu,
2394  Watchdog_Service_routine_entry  routine,
[00c620c]2395  uint64_t                        expire
[03b900d]2396)
2397{
[9480815a]2398  ISR_lock_Context  lock_context;
2399  Watchdog_Header  *header;
[03b900d]2400
2401  _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
2402
[9480815a]2403  header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ];
2404  the_thread->Timer.header = header;
[03b900d]2405  the_thread->Timer.Watchdog.routine = routine;
[9480815a]2406  _Watchdog_Per_CPU_insert( &the_thread->Timer.Watchdog, cpu, header, expire );
[03b900d]2407
2408  _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
2409}
2410
[3657cde]2411/**
2412 * @brief Remove the watchdog timer from the thread.
2413 *
2414 * @param[in, out] the_thread The thread to remove the watchdog from.
2415 */
[03b900d]2416RTEMS_INLINE_ROUTINE void _Thread_Timer_remove( Thread_Control *the_thread )
2417{
2418  ISR_lock_Context lock_context;
2419
2420  _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
2421
2422  _Watchdog_Per_CPU_remove(
2423    &the_thread->Timer.Watchdog,
2424#if defined(RTEMS_SMP)
2425    the_thread->Timer.Watchdog.cpu,
2426#else
2427    _Per_CPU_Get(),
2428#endif
2429    the_thread->Timer.header
2430  );
2431
2432  _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
2433}
[08fe84b]2434
[3657cde]2435/**
2436 * @brief Remove the watchdog timer from the thread and unblock if necessary.
2437 *
2438 * @param[in, out] the_thread The thread to remove the watchdog from and unblock
2439 *      if necessary.
2440 * @param queue The thread queue.
2441 */
[0e9d5b6]2442RTEMS_INLINE_ROUTINE void _Thread_Remove_timer_and_unblock(
2443  Thread_Control     *the_thread,
2444  Thread_queue_Queue *queue
2445)
2446{
[1fcac5ad]2447  _Thread_Wait_tranquilize( the_thread );
[0e9d5b6]2448  _Thread_Timer_remove( the_thread );
2449
2450#if defined(RTEMS_MULTIPROCESSING)
2451  if ( _Objects_Is_local_id( the_thread->Object.id ) ) {
2452    _Thread_Unblock( the_thread );
2453  } else {
2454    _Thread_queue_Unblock_proxy( queue, the_thread );
2455  }
2456#else
2457  (void) queue;
2458  _Thread_Unblock( the_thread );
2459#endif
2460}
2461
[3657cde]2462/**
2463 * @brief Sets the name of the thread.
2464 *
2465 * @param[out] the_thread  The thread to change the name of.
2466 * @param name The new name for the thread.
2467 *
2468 * @retval STATUS_SUCCESSFUL The operation succeeded.
2469 * @retval STATUS_RESULT_TOO_LARGE The name was too long.
2470 */
[da6ad56]2471Status_Control _Thread_Set_name(
2472  Thread_Control *the_thread,
2473  const char     *name
2474);
2475
[3657cde]2476/**
2477 * @brief Gets the name of the thread.
2478 *
2479 * @param the_thread The thread to get the name of.
2480 * @param[out] buffer Contains the thread's name.
2481 * @param buffer_size The size of @a buffer.
2482 *
2483 * @return The number of bytes copied to @a buffer.
2484 */
[7ced9d9b]2485size_t _Thread_Get_name(
2486  const Thread_Control *the_thread,
2487  char                 *buffer,
2488  size_t                buffer_size
2489);
2490
[7097962]2491#if defined(RTEMS_SMP)
2492#define THREAD_PIN_STEP 2
2493
2494#define THREAD_PIN_PREEMPTION 1
2495
[3657cde]2496/**
2497 * @brief Unpins the thread.
2498 *
2499 * @param executing The currently executing thread.
2500 * @param cpu_self The cpu for the operation.
2501 */
[7097962]2502void _Thread_Do_unpin(
2503  Thread_Control  *executing,
2504  Per_CPU_Control *cpu_self
2505);
2506#endif
2507
[3657cde]2508/**
2509 * @brief Pin the executing thread.
2510 *
2511 * @param executing The currently executing thread.
2512 */
[7097962]2513RTEMS_INLINE_ROUTINE void _Thread_Pin( Thread_Control *executing )
2514{
2515#if defined(RTEMS_SMP)
2516  _Assert( executing == _Thread_Executing );
2517
2518  executing->Scheduler.pin_level += THREAD_PIN_STEP;
2519#else
2520  (void) executing;
2521#endif
2522}
2523
[3657cde]2524/**
2525 * @brief Unpins the thread.
2526 *
2527 * @param executing The currently executing thread.
2528 * @param cpu_self The cpu for the operation.
2529 */
[7097962]2530RTEMS_INLINE_ROUTINE void _Thread_Unpin(
2531  Thread_Control  *executing,
2532  Per_CPU_Control *cpu_self
2533)
2534{
2535#if defined(RTEMS_SMP)
2536  unsigned int pin_level;
2537
2538  _Assert( executing == _Thread_Executing );
2539
2540  pin_level = executing->Scheduler.pin_level;
2541  _Assert( pin_level > 0 );
2542
2543  if (
2544    RTEMS_PREDICT_TRUE(
2545      pin_level != ( THREAD_PIN_STEP | THREAD_PIN_PREEMPTION )
2546    )
2547  ) {
2548    executing->Scheduler.pin_level = pin_level - THREAD_PIN_STEP;
2549  } else {
2550    _Thread_Do_unpin( executing, cpu_self );
2551  }
2552#else
2553  (void) executing;
2554  (void) cpu_self;
2555#endif
2556}
2557
[5618c37a]2558/** @}*/
2559
2560#ifdef __cplusplus
2561}
2562#endif
2563
2564#if defined(RTEMS_MULTIPROCESSING)
2565#include <rtems/score/threadmp.h>
2566#endif
2567
2568#endif
2569/* end of include file */
Note: See TracBrowser for help on using the repository browser.