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 Jan 2, 2020 at 10:30:33 AM

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
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSScoreThread
5 *
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 *
16 *  Copyright (c) 2014, 2017 embedded brains GmbH.
17 *
18 *  The license and distribution terms for this file may be
19 *  found in the file LICENSE in this distribution or at
20 *  http://www.rtems.org/license/LICENSE.
21 */
22
23#ifndef _RTEMS_SCORE_THREADIMPL_H
24#define _RTEMS_SCORE_THREADIMPL_H
25
26#include <rtems/score/thread.h>
27#include <rtems/score/assert.h>
28#include <rtems/score/chainimpl.h>
29#include <rtems/score/interr.h>
30#include <rtems/score/isr.h>
31#include <rtems/score/objectimpl.h>
32#include <rtems/score/schedulernodeimpl.h>
33#include <rtems/score/statesimpl.h>
34#include <rtems/score/status.h>
35#include <rtems/score/sysstate.h>
36#include <rtems/score/timestampimpl.h>
37#include <rtems/score/threadqimpl.h>
38#include <rtems/score/todimpl.h>
39#include <rtems/score/watchdogimpl.h>
40#include <rtems/config.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/**
47 * @addtogroup RTEMSScoreThread
48 *
49 * @{
50 */
51
52/**
53 *  Self for the GNU Ada Run-Time
54 */
55extern void *rtems_ada_self;
56
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
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 )
72extern Thread_Control *_Thread_Allocated_fp;
73#endif
74
75#if defined(RTEMS_SMP)
76#define THREAD_OF_SCHEDULER_HELP_NODE( node ) \
77  RTEMS_CONTAINER_OF( node, Thread_Control, Scheduler.Help_node )
78#endif
79
80typedef bool ( *Thread_Visitor )( Thread_Control *the_thread, void *arg );
81
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 */
90void _Thread_Iterate(
91  Thread_Visitor  visitor,
92  void           *arg
93);
94
95/**
96 * @brief Initializes the thread information
97 *
98 * @param[out] information Information to initialize.
99 */
100void _Thread_Initialize_information( Thread_Information *information );
101
102/**
103 * @brief Initializes thread handler.
104 *
105 * This routine performs the initialization necessary for this handler.
106 */
107void _Thread_Handler_initialization(void);
108
109/**
110 * @brief Creates idle thread.
111 *
112 * This routine creates the idle thread.
113 *
114 * @warning No thread should be created before this one.
115 */
116void _Thread_Create_idle(void);
117
118/**
119 * @brief Starts thread multitasking.
120 *
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.
124 */
125void _Thread_Start_multitasking( void ) RTEMS_NO_RETURN;
126
127/**
128 * @brief Allocates the requested stack space for the thread.
129 *
130 * Allocate the requested stack space for the thread.
131 * Set the Start.stack field to the address of the stack.
132 *
133 * @param[out] the_thread The thread where the stack space is requested.
134 * @param stack_size The stack space that is requested.
135 *
136 * @retval actual Size allocated after any adjustment.
137 * @retval zero The allocation failed.
138 */
139size_t _Thread_Stack_Allocate(
140  Thread_Control *the_thread,
141  size_t          stack_size
142);
143
144/**
145 * @brief Deallocates thread stack.
146 *
147 * Deallocate the Thread's stack.
148 *
149 * @param[out] the_thread The thread to deallocate the stack of.
150 */
151void _Thread_Stack_Free(
152  Thread_Control *the_thread
153);
154
155/**
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.
162 *
163 * @note If stack_area is NULL, it is allocated from the workspace.
164 *
165 * @note If the stack is allocated from the workspace, then it is
166 *       guaranteed to be of at least minimum size.
167 *
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.
183 */
184bool _Thread_Initialize(
185  Thread_Information                   *information,
186  Thread_Control                       *the_thread,
187  const struct _Scheduler_Control      *scheduler,
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/**
200 * @brief Initializes thread and executes it.
201 *
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.
205 *
206 * @param the_thread The thread to be started.
207 * @param entry The thread entry information.
208 */
209bool _Thread_Start(
210  Thread_Control                 *the_thread,
211  const Thread_Entry_information *entry,
212  ISR_lock_Context               *lock_context
213);
214
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 */
222void _Thread_Restart_self(
223  Thread_Control                 *executing,
224  const Thread_Entry_information *entry,
225  ISR_lock_Context               *lock_context
226) RTEMS_NO_RETURN;
227
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 */
238bool _Thread_Restart_other(
239  Thread_Control                 *the_thread,
240  const Thread_Entry_information *entry,
241  ISR_lock_Context               *lock_context
242);
243
244/**
245 * @brief Yields the currently executing thread.
246 *
247 * @param[in, out] executing The thread that performs a yield.
248 */
249void _Thread_Yield( Thread_Control *executing );
250
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 */
260Thread_Life_state _Thread_Change_life(
261  Thread_Life_state clear,
262  Thread_Life_state set,
263  Thread_Life_state ignore
264);
265
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 */
276Thread_Life_state _Thread_Set_life_protection( Thread_Life_state state );
277
278/**
279 * @brief Kills all zombie threads in the system.
280 *
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.
286 */
287void _Thread_Kill_zombies( void );
288
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 */
296void _Thread_Exit(
297  Thread_Control    *executing,
298  Thread_Life_state  set,
299  void              *exit_value
300);
301
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 */
311void _Thread_Join(
312  Thread_Control       *the_thread,
313  States_Control        waiting_for_join,
314  Thread_Control       *executing,
315  Thread_queue_Context *queue_context
316);
317
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 */
325void _Thread_Cancel(
326  Thread_Control *the_thread,
327  Thread_Control *executing,
328  void           *exit_value
329);
330
331typedef struct {
332  Thread_queue_Context  Base;
333  Thread_Control       *cancel;
334} Thread_Close_context;
335
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.
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.
346 */
347void _Thread_Close(
348  Thread_Control       *the_thread,
349  Thread_Control       *executing,
350  Thread_Close_context *context
351);
352
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 */
361RTEMS_INLINE_ROUTINE bool _Thread_Is_ready( const Thread_Control *the_thread )
362{
363  return _States_Is_ready( the_thread->current_state );
364}
365
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 */
377States_Control _Thread_Clear_state_locked(
378  Thread_Control *the_thread,
379  States_Control  state
380);
381
382/**
383 * @brief Clears the specified thread state.
384 *
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.
387 *
388 * @param[in, out] the_thread The thread.
389 * @param state The state to clear.  It must not be zero.
390 *
391 * @return The previous state.
392 */
393States_Control _Thread_Clear_state(
394  Thread_Control *the_thread,
395  States_Control  state
396);
397
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 */
409States_Control _Thread_Set_state_locked(
410  Thread_Control *the_thread,
411  States_Control  state
412);
413
414/**
415 * @brief Sets the specified thread state.
416 *
417 * In the case the previous state is the ready state, then the thread is blocked
418 * by the scheduler.
419 *
420 * @param[in, out] the_thread The thread.
421 * @param state The state to set.  It must not be zero.
422 *
423 * @return The previous state.
424 */
425States_Control _Thread_Set_state(
426  Thread_Control *the_thread,
427  States_Control  state
428);
429
430/**
431 * @brief Initializes enviroment for a thread.
432 *
433 * This routine initializes the context of @a the_thread to its
434 * appropriate starting state.
435 *
436 * @param[in, out] the_thread The pointer to the thread control block.
437 */
438void _Thread_Load_environment(
439  Thread_Control *the_thread
440);
441
442/**
443 * @brief Calls the start kinds idle entry of the thread.
444 *
445 * @param executing The currently executing thread.
446 */
447void _Thread_Entry_adaptor_idle( Thread_Control *executing );
448
449/**
450 * @brief Calls the start kinds numeric entry of the thread.
451 *
452 * @param executing The currently executing thread.
453 */
454void _Thread_Entry_adaptor_numeric( Thread_Control *executing );
455
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 */
463void _Thread_Entry_adaptor_pointer( Thread_Control *executing );
464
465/**
466 * @brief Wrapper function for all threads.
467 *
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.
473 *
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.
479 */
480void _Thread_Handler( void );
481
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 */
488RTEMS_INLINE_ROUTINE void _Thread_State_acquire_critical(
489  Thread_Control   *the_thread,
490  ISR_lock_Context *lock_context
491)
492{
493  _Thread_queue_Do_acquire_critical( &the_thread->Join_queue, lock_context );
494}
495
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 */
502RTEMS_INLINE_ROUTINE void _Thread_State_acquire(
503  Thread_Control   *the_thread,
504  ISR_lock_Context *lock_context
505)
506{
507  _ISR_lock_ISR_disable( lock_context );
508  _Thread_State_acquire_critical( the_thread, lock_context );
509}
510
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 */
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
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 */
538RTEMS_INLINE_ROUTINE void _Thread_State_release_critical(
539  Thread_Control   *the_thread,
540  ISR_lock_Context *lock_context
541)
542{
543  _Thread_queue_Do_release_critical( &the_thread->Join_queue, lock_context );
544}
545
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 */
552RTEMS_INLINE_ROUTINE void _Thread_State_release(
553  Thread_Control   *the_thread,
554  ISR_lock_Context *lock_context
555)
556{
557  _Thread_State_release_critical( the_thread, lock_context );
558  _ISR_lock_ISR_enable( lock_context );
559}
560
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 */
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
578/**
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().
589 */
590void _Thread_Priority_perform_actions(
591  Thread_Control       *start_of_path,
592  Thread_queue_Context *queue_context
593);
594
595/**
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().
609 */
610void _Thread_Priority_add(
611  Thread_Control       *the_thread,
612  Priority_Node        *priority_node,
613  Thread_queue_Context *queue_context
614);
615
616/**
617 * @brief Removes the specified thread priority node from the corresponding
618 * thread priority aggregation.
619 *
620 * The caller must be the owner of the thread wait lock.
621 *
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.
628 *
629 * @see _Thread_Wait_acquire().
630 */
631void _Thread_Priority_remove(
632  Thread_Control       *the_thread,
633  Priority_Node        *priority_node,
634  Thread_queue_Context *queue_context
635);
636
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.
644 * @param[out] priority_node The thread priority node to change.
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
660);
661
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.
669 * @param[out] priority_node The thread priority node to change.
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}
698
699/**
700 * @brief Replaces the victim priority node with the replacement priority node
701 * in the corresponding thread priority aggregation.
702 *
703 * The caller must be the owner of the thread wait lock.
704 *
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().
710 */
711void _Thread_Priority_replace(
712  Thread_Control *the_thread,
713  Priority_Node  *victim_node,
714  Priority_Node  *replacement_node
715);
716
717/**
718 * @brief Updates the priority of all threads in the set
719 *
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.
724 *
725 * @see _Thread_Priority_add(), _Thread_Priority_change(),
726 *   _Thread_Priority_changed() and _Thread_Priority_remove().
727 */
728void _Thread_Priority_update( Thread_queue_Context *queue_context );
729
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 */
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
743/**
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.
752 */
753RTEMS_INLINE_ROUTINE bool _Thread_Priority_less_than(
754  Priority_Control left,
755  Priority_Control right
756)
757{
758  return left > right;
759}
760
761/**
762 * @brief Returns the highest priority of the left and right thread priorities
763 * in the intuitive sense of priority.
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.
769 */
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}
777
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 */
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
807/**
808 * @brief Gets a thread by its identifier.
809 *
810 * @see _Objects_Get().
811 *
812 * @param id The id of the thread.
813 * @param lock_context The lock context.
814 */
815Thread_Control *_Thread_Get(
816  Objects_Id         id,
817  ISR_lock_Context  *lock_context
818);
819
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 */
827RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Get_CPU(
828  const Thread_Control *thread
829)
830{
831#if defined(RTEMS_SMP)
832  return thread->Scheduler.cpu;
833#else
834  (void) thread;
835
836  return _Per_CPU_Get();
837#endif
838}
839
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 */
846RTEMS_INLINE_ROUTINE void _Thread_Set_CPU(
847  Thread_Control *thread,
848  Per_CPU_Control *cpu
849)
850{
851#if defined(RTEMS_SMP)
852  thread->Scheduler.cpu = cpu;
853#else
854  (void) thread;
855  (void) cpu;
856#endif
857}
858
859/**
860 * @brief Checks if the thread is the currently executing thread.
861 *
862 * This function returns true if the_thread is the currently executing
863 * thread, and false otherwise.
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.
869 */
870RTEMS_INLINE_ROUTINE bool _Thread_Is_executing (
871  const Thread_Control *the_thread
872)
873{
874  return ( the_thread == _Thread_Executing );
875}
876
877#if defined(RTEMS_SMP)
878/**
879 * @brief Checks if the thread executes currently on some processor in the
880 * system.
881 *
882 * Do not confuse this with _Thread_Is_executing() which checks only the
883 * current processor.
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.
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
898/**
899 * @brief Checks if the thread is the heir.
900 *
901 * This function returns true if the_thread is the heir
902 * thread, and false otherwise.
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.
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/**
917 * @brief Unblocks the thread.
918 *
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.
922 *
923 * @param[in, out] the_thread The thread to unblock.
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/**
933 * @brief Checks if the floating point context of the thread is currently
934 *      loaded in the floating point unit.
935 *
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.
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.
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
956/*
957 * If the CPU has hardware floating point, then we must address saving
958 * and restoring it as part of the context switch.
959 *
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.
967 */
968
969/**
970 * @brief Saves the executing thread's floating point area.
971 *
972 * @param executing The currently executing thread.
973 */
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
984/**
985 * @brief Restores the executing thread's floating point area.
986 *
987 * @param executing The currently executing thread.
988 */
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
1007/**
1008 * @brief Deallocates the currently loaded floating point context.
1009 *
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/**
1021 * @brief Checks if dispatching is disabled.
1022 *
1023 * This function returns true if dispatching is disabled, and false
1024 * otherwise.
1025 *
1026 * @retval true Dispatching is disabled.
1027 * @retval false Dispatching is enabled.
1028 */
1029RTEMS_INLINE_ROUTINE bool _Thread_Is_context_switch_necessary( void )
1030{
1031  return ( _Thread_Dispatch_necessary );
1032}
1033
1034/**
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.
1041 */
1042RTEMS_INLINE_ROUTINE bool _Thread_Is_null (
1043  const Thread_Control *the_thread
1044)
1045{
1046  return ( the_thread == NULL );
1047}
1048
1049/**
1050 * @brief Gets the maximum number of internal threads.
1051 *
1052 * @return The maximum number of internal threads.
1053 */
1054RTEMS_INLINE_ROUTINE uint32_t _Thread_Get_maximum_internal_threads(void)
1055{
1056  /* Idle threads */
1057  uint32_t maximum_internal_threads =
1058    rtems_configuration_get_maximum_processors();
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
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 */
1076RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Internal_allocate( void )
1077{
1078  return (Thread_Control *)
1079    _Objects_Allocate_unprotected( &_Thread_Information.Objects );
1080}
1081
1082/**
1083 * @brief Gets the heir of the processor and makes it executing.
1084 *
1085 * Must be called with interrupts disabled.  The thread dispatch necessary
1086 * indicator is cleared as a side-effect.
1087 *
1088 * @param[in, out] cpu_self The processor to get the heir of.
1089 *
1090 * @return The heir thread.
1091 *
1092 * @see _Thread_Dispatch(), _Thread_Start_multitasking() and
1093 * _Thread_Dispatch_update_heir().
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;
1102  cpu_self->dispatch_necessary = false;
1103  cpu_self->executing = heir;
1104
1105  return heir;
1106}
1107
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 */
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
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 */
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{
1143  _Thread_Update_CPU_time_used( cpu_for_heir->heir, cpu_for_heir );
1144
1145  cpu_for_heir->heir = heir;
1146
1147  _Thread_Dispatch_request( cpu_self, cpu_for_heir );
1148}
1149#endif
1150
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 */
1158void _Thread_Get_CPU_time_used(
1159  Thread_Control    *the_thread,
1160  Timestamp_Control *cpu_time_used
1161);
1162
1163/**
1164 * @brief Initializes the control chain of the action control.
1165 *
1166 * @param[out] action_control The action control to initialize.
1167 */
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
1175/**
1176 * @brief Initializes the Thread action.
1177 *
1178 * @param[out] action The Thread_Action to initialize.
1179 */
1180RTEMS_INLINE_ROUTINE void _Thread_Action_initialize(
1181  Thread_Action *action
1182)
1183{
1184  _Chain_Set_off_chain( &action->Node );
1185}
1186
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 */
1194RTEMS_INLINE_ROUTINE void _Thread_Add_post_switch_action(
1195  Thread_Control        *the_thread,
1196  Thread_Action         *action,
1197  Thread_Action_handler  handler
1198)
1199{
1200  Per_CPU_Control *cpu_of_thread;
1201
1202  _Assert( _Thread_State_is_owner( the_thread ) );
1203
1204  cpu_of_thread = _Thread_Get_CPU( the_thread );
1205
1206  action->handler = handler;
1207
1208  _Thread_Dispatch_request( _Per_CPU_Get(), cpu_of_thread );
1209
1210  _Chain_Append_if_is_off_chain_unprotected(
1211    &the_thread->Post_switch_actions.Chain,
1212    &action->Node
1213  );
1214}
1215
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 */
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
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 */
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
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 */
1254RTEMS_INLINE_ROUTINE bool _Thread_Is_life_change_allowed(
1255  Thread_Life_state life_state
1256)
1257{
1258  return ( life_state
1259    & ( THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED ) ) == 0;
1260}
1261
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 */
1270RTEMS_INLINE_ROUTINE bool _Thread_Is_life_changing(
1271  Thread_Life_state life_state
1272)
1273{
1274  return ( life_state
1275    & ( THREAD_LIFE_RESTARTING | THREAD_LIFE_TERMINATING ) ) != 0;
1276}
1277
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 */
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
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 */
1299RTEMS_INLINE_ROUTINE void _Thread_Resource_count_increment(
1300  Thread_Control *the_thread
1301)
1302{
1303#if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT)
1304  ++the_thread->resource_count;
1305#else
1306  (void) the_thread;
1307#endif
1308}
1309
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 */
1315RTEMS_INLINE_ROUTINE void _Thread_Resource_count_decrement(
1316  Thread_Control *the_thread
1317)
1318{
1319#if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT)
1320  --the_thread->resource_count;
1321#else
1322  (void) the_thread;
1323#endif
1324}
1325
1326#if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT)
1327/**
1328 * @brief Checks if the thread owns resources.
1329 *
1330 * Resources are accounted with the Thread_Control::resource_count resource
1331 * counter.  This counter is used by mutex objects for example.
1332 *
1333 * @param the_thread The thread.
1334 *
1335 * @retval true The thread owns resources.
1336 * @retval false The thread does not own resources.
1337 */
1338RTEMS_INLINE_ROUTINE bool _Thread_Owns_resources(
1339  const Thread_Control *the_thread
1340)
1341{
1342  return the_thread->resource_count != 0;
1343}
1344#endif
1345
1346#if defined(RTEMS_SMP)
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 */
1354RTEMS_INLINE_ROUTINE void _Thread_Scheduler_cancel_need_for_help(
1355  Thread_Control  *the_thread,
1356  Per_CPU_Control *cpu
1357)
1358{
1359  ISR_lock_Context lock_context;
1360
1361  _Per_CPU_Acquire( cpu, &lock_context );
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
1368  _Per_CPU_Release( cpu, &lock_context );
1369}
1370#endif
1371
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 */
1379RTEMS_INLINE_ROUTINE const Scheduler_Control *_Thread_Scheduler_get_home(
1380  const Thread_Control *the_thread
1381)
1382{
1383#if defined(RTEMS_SMP)
1384  return the_thread->Scheduler.home_scheduler;
1385#else
1386  (void) the_thread;
1387  return &_Scheduler_Table[ 0 ];
1388#endif
1389}
1390
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 */
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
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 */
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;
1433#endif
1434}
1435
1436#if defined(RTEMS_SMP)
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 */
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
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 */
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
1465/**
1466 * @brief Process the thread's scheduler requests.
1467 *
1468 * @param[in, out] the_thread The thread for the operation.
1469 */
1470void _Thread_Scheduler_process_requests( Thread_Control *the_thread );
1471
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 */
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
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 */
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  );
1531  _Thread_Scheduler_add_request(
1532    the_thread,
1533    scheduler_node,
1534    SCHEDULER_NODE_REQUEST_ADD
1535  );
1536}
1537
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 */
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 );
1551  _Thread_Scheduler_add_request(
1552    the_thread,
1553    scheduler_node,
1554    SCHEDULER_NODE_REQUEST_REMOVE
1555  );
1556}
1557#endif
1558
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 *
1566 * @param the_thread The thread of which to get the priority.
1567 *
1568 * @return The priority of the thread.
1569 */
1570RTEMS_INLINE_ROUTINE Priority_Control _Thread_Get_priority(
1571  const Thread_Control *the_thread
1572)
1573{
1574  Scheduler_Node *scheduler_node;
1575
1576  scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
1577  return _Priority_Get_priority( &scheduler_node->Wait.Priority );
1578}
1579
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
1608/**
1609 * @brief Acquires the thread wait default lock inside a critical section
1610 * (interrupts disabled).
1611 *
1612 * @param[in, out] the_thread The thread.
1613 * @param lock_context The lock context used for the corresponding lock
1614 *   release.
1615 *
1616 * @see _Thread_Wait_release_default_critical().
1617 */
1618RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_default_critical(
1619  Thread_Control   *the_thread,
1620  ISR_lock_Context *lock_context
1621)
1622{
1623  _ISR_lock_Acquire( &the_thread->Wait.Lock.Default, lock_context );
1624}
1625
1626/**
1627 * @brief Acquires the thread wait default lock and returns the executing
1628 * thread.
1629 *
1630 * @param lock_context The lock context used for the corresponding lock
1631 *   release.
1632 *
1633 * @return The executing thread.
1634 *
1635 * @see _Thread_Wait_release_default().
1636 */
1637RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Wait_acquire_default_for_executing(
1638  ISR_lock_Context *lock_context
1639)
1640{
1641  Thread_Control *executing;
1642
1643  _ISR_lock_ISR_disable( lock_context );
1644  executing = _Thread_Executing;
1645  _Thread_Wait_acquire_default_critical( executing, lock_context );
1646
1647  return executing;
1648}
1649
1650/**
1651 * @brief Acquires the thread wait default lock and disables interrupts.
1652 *
1653 * @param[in, out] the_thread The thread.
1654 * @param[out] lock_context The lock context used for the corresponding lock
1655 *   release.
1656 *
1657 * @see _Thread_Wait_release_default().
1658 */
1659RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_default(
1660  Thread_Control   *the_thread,
1661  ISR_lock_Context *lock_context
1662)
1663{
1664  _ISR_lock_ISR_disable( lock_context );
1665  _Thread_Wait_acquire_default_critical( the_thread, lock_context );
1666}
1667
1668/**
1669 * @brief Releases the thread wait default lock inside a critical section
1670 * (interrupts disabled).
1671 *
1672 * The previous interrupt status is not restored.
1673 *
1674 * @param[in, out] the_thread The thread.
1675 * @param lock_context The lock context used for the corresponding lock
1676 *   acquire.
1677 */
1678RTEMS_INLINE_ROUTINE void _Thread_Wait_release_default_critical(
1679  Thread_Control   *the_thread,
1680  ISR_lock_Context *lock_context
1681)
1682{
1683  _ISR_lock_Release( &the_thread->Wait.Lock.Default, lock_context );
1684}
1685
1686/**
1687 * @brief Releases the thread wait default lock and restores the previous
1688 * interrupt status.
1689 *
1690 * @param[in, out] the_thread The thread.
1691 * @param[out] lock_context The lock context used for the corresponding lock
1692 *   acquire.
1693 */
1694RTEMS_INLINE_ROUTINE void _Thread_Wait_release_default(
1695  Thread_Control   *the_thread,
1696  ISR_lock_Context *lock_context
1697)
1698{
1699  _Thread_Wait_release_default_critical( the_thread, lock_context );
1700  _ISR_lock_ISR_enable( lock_context );
1701}
1702
1703#if defined(RTEMS_SMP)
1704#define THREAD_QUEUE_CONTEXT_OF_REQUEST( node ) \
1705  RTEMS_CONTAINER_OF( node, Thread_queue_Context, Lock_context.Wait.Gate.Node )
1706
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 */
1713RTEMS_INLINE_ROUTINE void _Thread_Wait_remove_request_locked(
1714  Thread_Control            *the_thread,
1715  Thread_queue_Lock_context *queue_lock_context
1716)
1717{
1718  Chain_Node *first;
1719
1720  _Chain_Extract_unprotected( &queue_lock_context->Wait.Gate.Node );
1721  first = _Chain_First( &the_thread->Wait.Lock.Pending_requests );
1722
1723  if ( first != _Chain_Tail( &the_thread->Wait.Lock.Pending_requests ) ) {
1724    _Thread_queue_Gate_open( (Thread_queue_Gate *) first );
1725  }
1726}
1727
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 */
1734RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_queue_critical(
1735  Thread_queue_Queue        *queue,
1736  Thread_queue_Lock_context *queue_lock_context
1737)
1738{
1739  _Thread_queue_Queue_acquire_critical(
1740    queue,
1741    &_Thread_Executing->Potpourri_stats,
1742    &queue_lock_context->Lock_context
1743  );
1744}
1745
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 */
1752RTEMS_INLINE_ROUTINE void _Thread_Wait_release_queue_critical(
1753  Thread_queue_Queue        *queue,
1754  Thread_queue_Lock_context *queue_lock_context
1755)
1756{
1757  _Thread_queue_Queue_release_critical(
1758    queue,
1759    &queue_lock_context->Lock_context
1760  );
1761}
1762#endif
1763
1764/**
1765 * @brief Acquires the thread wait lock inside a critical section (interrupts
1766 * disabled).
1767 *
1768 * @param[in, out] the_thread The thread.
1769 * @param[in, out] queue_context The thread queue context for the corresponding
1770 *   _Thread_Wait_release_critical().
1771 */
1772RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_critical(
1773  Thread_Control       *the_thread,
1774  Thread_queue_Context *queue_context
1775)
1776{
1777#if defined(RTEMS_SMP)
1778  Thread_queue_Queue *queue;
1779
1780  _Thread_Wait_acquire_default_critical(
1781    the_thread,
1782    &queue_context->Lock_context.Lock_context
1783  );
1784
1785  queue = the_thread->Wait.queue;
1786  queue_context->Lock_context.Wait.queue = queue;
1787
1788  if ( queue != NULL ) {
1789    _Thread_queue_Gate_add(
1790      &the_thread->Wait.Lock.Pending_requests,
1791      &queue_context->Lock_context.Wait.Gate
1792    );
1793    _Thread_Wait_release_default_critical(
1794      the_thread,
1795      &queue_context->Lock_context.Lock_context
1796    );
1797    _Thread_Wait_acquire_queue_critical( queue, &queue_context->Lock_context );
1798
1799    if ( queue_context->Lock_context.Wait.queue == NULL ) {
1800      _Thread_Wait_release_queue_critical(
1801        queue,
1802        &queue_context->Lock_context
1803      );
1804      _Thread_Wait_acquire_default_critical(
1805        the_thread,
1806        &queue_context->Lock_context.Lock_context
1807      );
1808      _Thread_Wait_remove_request_locked(
1809        the_thread,
1810        &queue_context->Lock_context
1811      );
1812      _Assert( the_thread->Wait.queue == NULL );
1813    }
1814  }
1815#else
1816  (void) the_thread;
1817  (void) queue_context;
1818#endif
1819}
1820
1821/**
1822 * @brief Acquires the thread wait default lock and disables interrupts.
1823 *
1824 * @param[in, out] the_thread The thread.
1825 * @param[in, out] queue_context The thread queue context for the corresponding
1826 *   _Thread_Wait_release().
1827 */
1828RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire(
1829  Thread_Control       *the_thread,
1830  Thread_queue_Context *queue_context
1831)
1832{
1833  _ISR_lock_ISR_disable( &queue_context->Lock_context.Lock_context );
1834  _Thread_Wait_acquire_critical( the_thread, queue_context );
1835}
1836
1837/**
1838 * @brief Releases the thread wait lock inside a critical section (interrupts
1839 * disabled).
1840 *
1841 * The previous interrupt status is not restored.
1842 *
1843 * @param[in, out] the_thread The thread.
1844 * @param[in, out] queue_context The thread queue context used for corresponding
1845 *   _Thread_Wait_acquire_critical().
1846 */
1847RTEMS_INLINE_ROUTINE void _Thread_Wait_release_critical(
1848  Thread_Control       *the_thread,
1849  Thread_queue_Context *queue_context
1850)
1851{
1852#if defined(RTEMS_SMP)
1853  Thread_queue_Queue *queue;
1854
1855  queue = queue_context->Lock_context.Wait.queue;
1856
1857  if ( queue != NULL ) {
1858    _Thread_Wait_release_queue_critical(
1859      queue, &queue_context->Lock_context
1860    );
1861    _Thread_Wait_acquire_default_critical(
1862      the_thread,
1863      &queue_context->Lock_context.Lock_context
1864    );
1865    _Thread_Wait_remove_request_locked(
1866      the_thread,
1867      &queue_context->Lock_context
1868    );
1869  }
1870
1871  _Thread_Wait_release_default_critical(
1872    the_thread,
1873    &queue_context->Lock_context.Lock_context
1874  );
1875#else
1876  (void) the_thread;
1877  (void) queue_context;
1878#endif
1879}
1880
1881/**
1882 * @brief Releases the thread wait lock and restores the previous interrupt
1883 * status.
1884 *
1885 * @param[in, out] the_thread The thread.
1886 * @param[in, out] queue_context The thread queue context used for corresponding
1887 *   _Thread_Wait_acquire().
1888 */
1889RTEMS_INLINE_ROUTINE void _Thread_Wait_release(
1890  Thread_Control       *the_thread,
1891  Thread_queue_Context *queue_context
1892)
1893{
1894  _Thread_Wait_release_critical( the_thread, queue_context );
1895  _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
1896}
1897
1898/**
1899 * @brief Claims the thread wait queue.
1900 *
1901 * The caller must not be the owner of the default thread wait lock.  The
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.
1906 *
1907 * @param[in, out] the_thread The thread.
1908 * @param[in, out] queue The new thread queue.
1909 *
1910 * @see _Thread_Wait_claim_finalize() and _Thread_Wait_restore_default().
1911 */
1912RTEMS_INLINE_ROUTINE void _Thread_Wait_claim(
1913  Thread_Control     *the_thread,
1914  Thread_queue_Queue *queue
1915)
1916{
1917  ISR_lock_Context lock_context;
1918
1919  _Thread_Wait_acquire_default_critical( the_thread, &lock_context );
1920
1921  _Assert( the_thread->Wait.queue == NULL );
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
1929  the_thread->Wait.queue = queue;
1930
1931  _Thread_Wait_release_default_critical( the_thread, &lock_context );
1932}
1933
1934/**
1935 * @brief Finalizes the thread wait queue claim via registration of the
1936 * corresponding thread queue operations.
1937 *
1938 * @param[in, out] the_thread The thread.
1939 * @param operations The corresponding thread queue operations.
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
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 *
1956 * @param[in, out] the_thread The thread.
1957 * @param[in, out] queue_lock_context The thread queue lock context used for
1958 *   corresponding _Thread_Wait_acquire().
1959 */
1960RTEMS_INLINE_ROUTINE void _Thread_Wait_remove_request(
1961  Thread_Control            *the_thread,
1962  Thread_queue_Lock_context *queue_lock_context
1963)
1964{
1965#if defined(RTEMS_SMP)
1966  ISR_lock_Context lock_context;
1967
1968  _Thread_Wait_acquire_default( the_thread, &lock_context );
1969  _Thread_Wait_remove_request_locked( the_thread, queue_lock_context );
1970  _Thread_Wait_release_default( the_thread, &lock_context );
1971#else
1972  (void) the_thread;
1973  (void) queue_lock_context;
1974#endif
1975}
1976
1977/**
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.
1981 *
1982 * On SMP configurations, the pending requests are updated to use the stale
1983 * thread queue operations.
1984 *
1985 * @param[in, out] the_thread The thread.
1986 *
1987 * @see _Thread_Wait_claim().
1988 */
1989RTEMS_INLINE_ROUTINE void _Thread_Wait_restore_default(
1990  Thread_Control *the_thread
1991)
1992{
1993#if defined(RTEMS_SMP)
1994  ISR_lock_Context  lock_context;
1995  Chain_Node       *node;
1996  const Chain_Node *tail;
1997
1998  _Thread_Wait_acquire_default_critical( the_thread, &lock_context );
1999
2000  node = _Chain_First( &the_thread->Wait.Lock.Pending_requests );
2001  tail = _Chain_Immutable_tail( &the_thread->Wait.Lock.Pending_requests );
2002
2003  if ( node != tail ) {
2004    do {
2005      Thread_queue_Context *queue_context;
2006
2007      queue_context = THREAD_QUEUE_CONTEXT_OF_REQUEST( node );
2008      queue_context->Lock_context.Wait.queue = NULL;
2009
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 );
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)
2026  _Thread_Wait_release_default_critical( the_thread, &lock_context );
2027#endif
2028}
2029
2030/**
2031 * @brief Tranquilizes the thread after a wait on a thread queue.
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 *
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 *
2046 * @param the_thread The thread.
2047 */
2048RTEMS_INLINE_ROUTINE void _Thread_Wait_tranquilize(
2049  Thread_Control *the_thread
2050)
2051{
2052#if defined(RTEMS_SMP)
2053  _Thread_queue_Gate_wait( &the_thread->Wait.Lock.Tranquilizer );
2054#else
2055  (void) the_thread;
2056#endif
2057}
2058
2059/**
2060 * @brief Cancels a thread wait on a thread queue.
2061 *
2062 * @param[in, out] the_thread The thread.
2063 * @param queue_context The thread queue context used for corresponding
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{
2071  Thread_queue_Queue *queue;
2072
2073  queue = the_thread->Wait.queue;
2074
2075#if defined(RTEMS_SMP)
2076  if ( queue != NULL ) {
2077    _Assert( queue_context->Lock_context.Wait.queue == queue );
2078#endif
2079
2080    ( *the_thread->Wait.operations->extract )(
2081      queue,
2082      the_thread,
2083      queue_context
2084    );
2085    _Thread_Wait_restore_default( the_thread );
2086
2087#if defined(RTEMS_SMP)
2088    _Assert( queue_context->Lock_context.Wait.queue == NULL );
2089    queue_context->Lock_context.Wait.queue = queue;
2090  }
2091#endif
2092}
2093
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/**
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.
2122 */
2123#define THREAD_WAIT_STATE_READY_AGAIN 0x4U
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/**
2141 * @brief Indicates that the thread waits for an object.
2142 */
2143#define THREAD_WAIT_CLASS_OBJECT 0x400U
2144
2145/**
2146 * @brief Indicates that the thread waits for a period.
2147 */
2148#define THREAD_WAIT_CLASS_PERIOD 0x800U
2149
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 */
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
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 */
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
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 */
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
2204/**
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).
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 *
2213 * @param the_thread The thread.
2214 * @param expected_flags The expected wait flags.
2215 * @param desired_flags The desired wait flags.
2216 *
2217 * @retval true The wait flags were equal to the expected wait flags.
2218 * @retval false The wait flags were not equal to the expected wait flags.
2219 */
2220RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change_release(
2221  Thread_Control    *the_thread,
2222  Thread_Wait_flags  expected_flags,
2223  Thread_Wait_flags  desired_flags
2224)
2225{
2226  _Assert( _ISR_Get_level() != 0 );
2227
2228#if defined(RTEMS_SMP)
2229  return _Atomic_Compare_exchange_uint(
2230    &the_thread->Wait.flags,
2231    &expected_flags,
2232    desired_flags,
2233    ATOMIC_ORDER_RELEASE,
2234    ATOMIC_ORDER_RELAXED
2235  );
2236#else
2237  bool success = ( the_thread->Wait.flags == expected_flags );
2238
2239  if ( success ) {
2240    the_thread->Wait.flags = desired_flags;
2241  }
2242
2243  return success;
2244#endif
2245}
2246
2247/**
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 *
2253 * @param the_thread The thread.
2254 * @param expected_flags The expected wait flags.
2255 * @param desired_flags The desired wait flags.
2256 *
2257 * @retval true The wait flags were equal to the expected wait flags.
2258 * @retval false The wait flags were not equal to the expected wait flags.
2259 */
2260RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change_acquire(
2261  Thread_Control    *the_thread,
2262  Thread_Wait_flags  expected_flags,
2263  Thread_Wait_flags  desired_flags
2264)
2265{
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
2275  bool      success;
2276  ISR_Level level;
2277
2278  _ISR_Local_disable( level );
2279
2280  success = _Thread_Wait_flags_try_change_release(
2281    the_thread,
2282    expected_flags,
2283    desired_flags
2284  );
2285
2286  _ISR_Local_enable( level );
2287  return success;
2288#endif
2289}
2290
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 *
2298 * @param the_thread The thread.
2299 *
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
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 */
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
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 *
2330 * @param[in, out] the_thread The thread.
2331 * @param status The thread wait status.
2332 */
2333void _Thread_Continue( Thread_Control *the_thread, Status_Control status );
2334
2335/**
2336 * @brief General purpose thread wait timeout.
2337 *
2338 * @param the_watchdog The thread timer watchdog.
2339 */
2340void _Thread_Timeout( Watchdog_Control *the_watchdog );
2341
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 */
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" );
2354  timer->header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
2355  _Watchdog_Preinitialize( &timer->Watchdog, cpu );
2356}
2357
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 */
2365RTEMS_INLINE_ROUTINE void _Thread_Add_timeout_ticks(
2366  Thread_Control    *the_thread,
2367  Per_CPU_Control   *cpu,
2368  Watchdog_Interval  ticks
2369)
2370{
2371  ISR_lock_Context lock_context;
2372
2373  _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
2374
2375  the_thread->Timer.header =
2376    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
2377  the_thread->Timer.Watchdog.routine = _Thread_Timeout;
2378  _Watchdog_Per_CPU_insert_ticks( &the_thread->Timer.Watchdog, cpu, ticks );
2379
2380  _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
2381}
2382
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 */
2391RTEMS_INLINE_ROUTINE void _Thread_Timer_insert_realtime(
2392  Thread_Control                 *the_thread,
2393  Per_CPU_Control                *cpu,
2394  Watchdog_Service_routine_entry  routine,
2395  uint64_t                        expire
2396)
2397{
2398  ISR_lock_Context  lock_context;
2399  Watchdog_Header  *header;
2400
2401  _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
2402
2403  header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ];
2404  the_thread->Timer.header = header;
2405  the_thread->Timer.Watchdog.routine = routine;
2406  _Watchdog_Per_CPU_insert( &the_thread->Timer.Watchdog, cpu, header, expire );
2407
2408  _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
2409}
2410
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 */
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}
2434
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 */
2442RTEMS_INLINE_ROUTINE void _Thread_Remove_timer_and_unblock(
2443  Thread_Control     *the_thread,
2444  Thread_queue_Queue *queue
2445)
2446{
2447  _Thread_Wait_tranquilize( the_thread );
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
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 */
2471Status_Control _Thread_Set_name(
2472  Thread_Control *the_thread,
2473  const char     *name
2474);
2475
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 */
2485size_t _Thread_Get_name(
2486  const Thread_Control *the_thread,
2487  char                 *buffer,
2488  size_t                buffer_size
2489);
2490
2491#if defined(RTEMS_SMP)
2492#define THREAD_PIN_STEP 2
2493
2494#define THREAD_PIN_PREEMPTION 1
2495
2496/**
2497 * @brief Unpins the thread.
2498 *
2499 * @param executing The currently executing thread.
2500 * @param cpu_self The cpu for the operation.
2501 */
2502void _Thread_Do_unpin(
2503  Thread_Control  *executing,
2504  Per_CPU_Control *cpu_self
2505);
2506#endif
2507
2508/**
2509 * @brief Pin the executing thread.
2510 *
2511 * @param executing The currently executing thread.
2512 */
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
2524/**
2525 * @brief Unpins the thread.
2526 *
2527 * @param executing The currently executing thread.
2528 * @param cpu_self The cpu for the operation.
2529 */
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
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.