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

4.115
Last change on this file since 3045738 was 3045738, checked in by Sebastian Huber <sebastian.huber@…>, on 05/28/14 at 11:38:48

score: Add resource node to thread control block

  • Property mode set to 100644
File size: 21.9 KB
Line 
1/**
2 * @file
3 *
4 * @brief Inlined Routines from the Thread Handler
5 *
6 * This file contains the macro implementation of the inlined
7 * routines from the Thread handler.
8 */
9
10/*
11 *  COPYRIGHT (c) 1989-2008.
12 *  On-Line Applications Research Corporation (OAR).
13 *
14 *  Copyright (c) 2014 embedded brains GmbH.
15 *
16 *  The license and distribution terms for this file may be
17 *  found in the file LICENSE in this distribution or at
18 *  http://www.rtems.org/license/LICENSE.
19 */
20
21#ifndef _RTEMS_SCORE_THREADIMPL_H
22#define _RTEMS_SCORE_THREADIMPL_H
23
24#include <rtems/score/thread.h>
25#include <rtems/score/chainimpl.h>
26#include <rtems/score/interr.h>
27#include <rtems/score/isr.h>
28#include <rtems/score/objectimpl.h>
29#include <rtems/score/resourceimpl.h>
30#include <rtems/score/statesimpl.h>
31#include <rtems/score/sysstate.h>
32#include <rtems/score/todimpl.h>
33#include <rtems/config.h>
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39/**
40 * @addtogroup ScoreThread
41 */
42/**@{**/
43
44/**
45 *  The following structure contains the information necessary to manage
46 *  a thread which it is  waiting for a resource.
47 */
48#define THREAD_STATUS_PROXY_BLOCKING 0x1111111
49
50/**
51 *  Self for the GNU Ada Run-Time
52 */
53SCORE_EXTERN void *rtems_ada_self;
54
55/**
56 *  The following defines the information control block used to
57 *  manage this class of objects.
58 */
59SCORE_EXTERN Objects_Information _Thread_Internal_information;
60
61/**
62 *  The following points to the thread whose floating point
63 *  context is currently loaded.
64 */
65#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
66SCORE_EXTERN Thread_Control *_Thread_Allocated_fp;
67#endif
68
69#if !defined(__DYNAMIC_REENT__)
70/**
71 * The C library re-enter-rant global pointer. Some C library implementations
72 * such as newlib have a single global pointer that changed during a context
73 * switch. The pointer points to that global pointer. The Thread control block
74 * holds a pointer to the task specific data.
75 */
76SCORE_EXTERN struct _reent **_Thread_libc_reent;
77#endif
78
79/**
80 *  @brief Initialize thread handler.
81 *
82 *  This routine performs the initialization necessary for this handler.
83 */
84void _Thread_Handler_initialization(void);
85
86/**
87 *  @brief Create idle thread.
88 *
89 *  This routine creates the idle thread.
90 *
91 *  @warning No thread should be created before this one.
92 */
93void _Thread_Create_idle(void);
94
95/**
96 *  @brief Start thread multitasking.
97 *
98 *  This routine initiates multitasking.  It is invoked only as
99 *  part of initialization and its invocation is the last act of
100 *  the non-multitasking part of the system initialization.
101 */
102void _Thread_Start_multitasking( void ) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
103
104/**
105 *  @brief Allocate the requested stack space for the thread.
106 *
107 *  Allocate the requested stack space for the thread.
108 *  Set the Start.stack field to the address of the stack.
109 *
110 *  @param[in] the_thread is the thread where the stack space is requested
111 *
112 *  @retval actual size allocated after any adjustment
113 *  @retval zero if the allocation failed
114 */
115size_t _Thread_Stack_Allocate(
116  Thread_Control *the_thread,
117  size_t          stack_size
118);
119
120/**
121 *  @brief Deallocate thread stack.
122 *
123 *  Deallocate the Thread's stack.
124 */
125void _Thread_Stack_Free(
126  Thread_Control *the_thread
127);
128
129/**
130 *  @brief Initialize thread.
131 *
132 *  This routine initializes the specified the thread.  It allocates
133 *  all memory associated with this thread.  It completes by adding
134 *  the thread to the local object table so operations on this
135 *  thread id are allowed.
136 *
137 *  @note If stack_area is NULL, it is allocated from the workspace.
138 *
139 *  @note If the stack is allocated from the workspace, then it is
140 *        guaranteed to be of at least minimum size.
141 */
142bool _Thread_Initialize(
143  Objects_Information                  *information,
144  Thread_Control                       *the_thread,
145  const struct Scheduler_Control       *scheduler,
146  void                                 *stack_area,
147  size_t                                stack_size,
148  bool                                  is_fp,
149  Priority_Control                      priority,
150  bool                                  is_preemptible,
151  Thread_CPU_budget_algorithms          budget_algorithm,
152  Thread_CPU_budget_algorithm_callout   budget_callout,
153  uint32_t                              isr_level,
154  Objects_Name                          name
155);
156
157/**
158 *  @brief Initializes thread and executes it.
159 *
160 *  This routine initializes the executable information for a thread
161 *  and makes it ready to execute.  After this routine executes, the
162 *  thread competes with all other threads for CPU time.
163 *
164 *  @param the_thread is the thread to be initialized
165 *  @param the_prototype
166 *  @param entry_point
167 *  @param pointer_argument
168 *  @param numeric_argument
169 *  @param[in,out] cpu The processor if used to start an idle thread
170 *  during system initialization.  Must be set to @c NULL to start a normal
171 *  thread.
172 */
173bool _Thread_Start(
174  Thread_Control            *the_thread,
175  Thread_Start_types         the_prototype,
176  void                      *entry_point,
177  void                      *pointer_argument,
178  Thread_Entry_numeric_type  numeric_argument,
179  Per_CPU_Control           *cpu
180);
181
182bool _Thread_Restart(
183  Thread_Control            *the_thread,
184  Thread_Control            *executing,
185  void                      *pointer_argument,
186  Thread_Entry_numeric_type  numeric_argument
187);
188
189bool _Thread_Set_life_protection( bool protect );
190
191void _Thread_Life_action_handler(
192  Thread_Control  *executing,
193  Thread_Action   *action,
194  Per_CPU_Control *cpu,
195  ISR_Level        level
196);
197
198/**
199 * @brief Kills all zombie threads in the system.
200 *
201 * Threads change into the zombie state as the last step in the thread
202 * termination sequence right before a context switch to the heir thread is
203 * initiated.  Since the thread stack is still in use during this phase we have
204 * to postpone the thread stack reclamation until this point.  On SMP
205 * configurations we may have to busy wait for context switch completion here.
206 */
207void _Thread_Kill_zombies( void );
208
209/**
210 * @brief Closes the thread.
211 *
212 * Closes the thread object and starts the thread termination sequence.  In
213 * case the executing thread is not terminated, then this function waits until
214 * the terminating thread reached the zombie state.
215 */
216void _Thread_Close( Thread_Control *the_thread, Thread_Control *executing );
217
218/**
219 *  @brief Removes any set states for @a the_thread.
220 *
221 *  This routine removes any set states for @a the_thread.  It performs
222 *  any necessary scheduling operations including the selection of
223 *  a new heir thread.
224 *
225 *  - INTERRUPT LATENCY:
226 *    + ready chain
227 *    + select heir
228 */
229void _Thread_Ready(
230  Thread_Control *the_thread
231);
232
233/**
234 *  @brief Clears the indicated STATES for @a the_thread.
235 *
236 *  This routine clears the indicated STATES for @a the_thread.  It performs
237 *  any necessary scheduling operations including the selection of
238 *  a new heir thread.
239 *
240 *  - INTERRUPT LATENCY:
241 *    + priority map
242 *    + select heir
243 */
244void _Thread_Clear_state(
245  Thread_Control *the_thread,
246  States_Control  state
247);
248
249/**
250 *  @brief Sets the indicated @a state for @a the_thread.
251 *
252 *  This routine sets the indicated @a state for @a the_thread.  It performs
253 *  any necessary scheduling operations including the selection of
254 *  a new heir thread.
255 *
256 *  @param[in] the_thread is the thread to set the state for.
257 *  @param[in] state is the state to set the_thread to.
258 *
259 *  - INTERRUPT LATENCY:
260 *   + ready chain
261 *   + select map
262 */
263void _Thread_Set_state(
264  Thread_Control *the_thread,
265  States_Control  state
266);
267
268/**
269 *  @brief Sets the transient state for a thread.
270 *
271 *  This routine sets the Transient state for @a the_thread.  It performs
272 *  any necessary scheduling operations including the selection of
273 *  a new heir thread.
274 *
275 *  @param[in] the_thread is the thread to preform the action upon.
276 *
277 *  - INTERRUPT LATENCY:
278 *    + single case
279 */
280void _Thread_Set_transient(
281  Thread_Control *the_thread
282);
283
284/**
285 *  @brief Initializes enviroment for a thread.
286 *
287 *  This routine initializes the context of @a the_thread to its
288 *  appropriate starting state.
289 *
290 *  @param[in] the_thread is the pointer to the thread control block.
291 */
292void _Thread_Load_environment(
293  Thread_Control *the_thread
294);
295
296/**
297 *  @brief Wrapper function for all threads.
298 *
299 *  This routine is the wrapper function for all threads.  It is
300 *  the starting point for all threads.  The user provided thread
301 *  entry point is invoked by this routine.  Operations
302 *  which must be performed immediately before and after the user's
303 *  thread executes are found here.
304 *
305 *  @note On entry, it is assumed all interrupts are blocked and that this
306 *  routine needs to set the initial isr level.  This may or may not
307 *  actually be needed by the context switch routine and as a result
308 *  interrupts may already be at there proper level.  Either way,
309 *  setting the initial isr level properly here is safe.
310 */
311void _Thread_Handler( void );
312
313/**
314 *  @brief Ended the delay of a thread.
315 *
316 *  This routine is invoked when a thread must be unblocked at the
317 *  end of a time based delay (i.e. wake after or wake when).
318 *  It is called by the watchdog handler.
319 *
320 *  @param[in] id is the thread id
321 */
322void _Thread_Delay_ended(
323  Objects_Id  id,
324  void       *ignored
325);
326
327/**
328 *  @brief Change the priority of a thread.
329 *
330 *  This routine changes the current priority of @a the_thread to
331 *  @a new_priority.  It performs any necessary scheduling operations
332 *  including the selection of a new heir thread.
333 *
334 *  @param[in] the_thread is the thread to change
335 *  @param[in] new_priority is the priority to set @a the_thread to
336 *  @param[in] prepend_it is a switch to prepend the thread
337 */
338void _Thread_Change_priority (
339  Thread_Control   *the_thread,
340  Priority_Control  new_priority,
341  bool              prepend_it
342);
343
344/**
345 *  @brief Set thread priority.
346 *
347 *  This routine updates the priority related fields in the_thread
348 *  control block to indicate the current priority is now new_priority.
349 */
350void _Thread_Set_priority(
351  Thread_Control   *the_thread,
352  Priority_Control  new_priority
353);
354
355/**
356 *  This routine updates the related suspend fields in the_thread
357 *  control block to indicate the current nested level.
358 */
359#define _Thread_Suspend( _the_thread ) \
360        _Thread_Set_state( _the_thread, STATES_SUSPENDED )
361
362/**
363 *  This routine updates the related suspend fields in the_thread
364 *  control block to indicate the current nested level.  A force
365 *  parameter of true will force a resume and clear the suspend count.
366 */
367#define _Thread_Resume( _the_thread ) \
368        _Thread_Clear_state( _the_thread, STATES_SUSPENDED )
369
370/**
371 *  @brief Maps thread Id to a TCB pointer.
372 *
373 *  This function maps thread IDs to thread control
374 *  blocks.  If ID corresponds to a local thread, then it
375 *  returns the_thread control pointer which maps to ID
376 *  and @a location is set to OBJECTS_LOCAL.  If the thread ID is
377 *  global and resides on a remote node, then location is set
378 *  to OBJECTS_REMOTE, and the_thread is undefined.
379 *  Otherwise, location is set to OBJECTS_ERROR and
380 *  the_thread is undefined.
381 *
382 *  @param[in] id is the id of the thread.
383 *  @param[in] location is the location of the block.
384 *
385 *  @note  The performance of many RTEMS services depends upon
386 *         the quick execution of the "good object" path in this
387 *         routine.  If there is a possibility of saving a few
388 *         cycles off the execution time, this routine is worth
389 *         further optimization attention.
390 */
391Thread_Control *_Thread_Get (
392  Objects_Id         id,
393  Objects_Locations *location
394);
395
396/**
397 *  @brief Cancel a blocking operation due to ISR.
398 *
399 *  This method is used to cancel a blocking operation that was
400 *  satisfied from an ISR while the thread executing was in the
401 *  process of blocking.
402 *
403 *  This method will restore the previous ISR disable level during the cancel
404 *  operation.  Thus it is an implicit _ISR_Enable().
405 *
406 *  @param[in] sync_state is the synchronization state
407 *  @param[in] the_thread is the thread whose blocking is canceled
408 *  @param[in] level is the previous ISR disable level
409 *
410 *  @note This is a rare routine in RTEMS.  It is called with
411 *        interrupts disabled and only when an ISR completed
412 *        a blocking condition in process.
413 */
414void _Thread_blocking_operation_Cancel(
415  Thread_blocking_operation_States  sync_state,
416  Thread_Control                   *the_thread,
417  ISR_Level                         level
418);
419
420RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Get_CPU(
421  const Thread_Control *thread
422)
423{
424#if defined(RTEMS_SMP)
425  return thread->cpu;
426#else
427  (void) thread;
428
429  return _Per_CPU_Get();
430#endif
431}
432
433RTEMS_INLINE_ROUTINE void _Thread_Set_CPU(
434  Thread_Control *thread,
435  Per_CPU_Control *cpu
436)
437{
438#if defined(RTEMS_SMP)
439  thread->cpu = cpu;
440#else
441  (void) thread;
442  (void) cpu;
443#endif
444}
445
446/**
447 * This function returns true if the_thread is the currently executing
448 * thread, and false otherwise.
449 */
450
451RTEMS_INLINE_ROUTINE bool _Thread_Is_executing (
452  const Thread_Control *the_thread
453)
454{
455  return ( the_thread == _Thread_Executing );
456}
457
458#if defined(RTEMS_SMP)
459/**
460 * @brief Returns @true in case the thread executes currently on some processor
461 * in the system, otherwise @a false.
462 *
463 * Do not confuse this with _Thread_Is_executing() which checks only the
464 * current processor.
465 */
466RTEMS_INLINE_ROUTINE bool _Thread_Is_executing_on_a_processor(
467  const Thread_Control *the_thread
468)
469{
470  return _CPU_Context_Get_is_executing( &the_thread->Registers );
471}
472#endif
473
474/**
475 * This function returns true if the_thread is the heir
476 * thread, and false otherwise.
477 */
478
479RTEMS_INLINE_ROUTINE bool _Thread_Is_heir (
480  const Thread_Control *the_thread
481)
482{
483  return ( the_thread == _Thread_Heir );
484}
485
486/**
487 * This routine clears any blocking state for the_thread.  It performs
488 * any necessary scheduling operations including the selection of
489 * a new heir thread.
490 */
491
492RTEMS_INLINE_ROUTINE void _Thread_Unblock (
493  Thread_Control *the_thread
494)
495{
496  _Thread_Clear_state( the_thread, STATES_BLOCKED );
497}
498
499/**
500 * This routine resets the current context of the calling thread
501 * to that of its initial state.
502 */
503
504RTEMS_INLINE_ROUTINE void _Thread_Restart_self( Thread_Control *executing )
505{
506#if defined(RTEMS_SMP)
507  ISR_Level level;
508
509  _Giant_Release();
510
511  _ISR_Disable_without_giant( level );
512  ( void ) level;
513#endif
514
515#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
516  if ( executing->fp_context != NULL )
517    _Context_Restore_fp( &executing->fp_context );
518#endif
519
520  _CPU_Context_Restart_self( &executing->Registers );
521}
522
523/**
524 * This function returns true if the floating point context of
525 * the_thread is currently loaded in the floating point unit, and
526 * false otherwise.
527 */
528
529#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
530RTEMS_INLINE_ROUTINE bool _Thread_Is_allocated_fp (
531  const Thread_Control *the_thread
532)
533{
534  return ( the_thread == _Thread_Allocated_fp );
535}
536#endif
537
538/**
539 * This routine is invoked when the currently loaded floating
540 * point context is now longer associated with an active thread.
541 */
542
543#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
544RTEMS_INLINE_ROUTINE void _Thread_Deallocate_fp( void )
545{
546  _Thread_Allocated_fp = NULL;
547}
548#endif
549
550/**
551 * This function returns true if dispatching is disabled, and false
552 * otherwise.
553 */
554
555RTEMS_INLINE_ROUTINE bool _Thread_Is_context_switch_necessary( void )
556{
557  return ( _Thread_Dispatch_necessary );
558}
559
560/**
561 * This function returns true if the_thread is NULL and false otherwise.
562 */
563
564RTEMS_INLINE_ROUTINE bool _Thread_Is_null (
565  const Thread_Control *the_thread
566)
567{
568  return ( the_thread == NULL );
569}
570
571/**
572 * @brief Is proxy blocking.
573 *
574 * status which indicates that a proxy is blocking, and false otherwise.
575 */
576RTEMS_INLINE_ROUTINE bool _Thread_Is_proxy_blocking (
577  uint32_t   code
578)
579{
580  return (code == THREAD_STATUS_PROXY_BLOCKING);
581}
582
583RTEMS_INLINE_ROUTINE uint32_t _Thread_Get_maximum_internal_threads(void)
584{
585  /* Idle threads */
586  uint32_t maximum_internal_threads =
587    rtems_configuration_get_maximum_processors();
588
589  /* MPCI thread */
590#if defined(RTEMS_MULTIPROCESSING)
591  if ( _System_state_Is_multiprocessing ) {
592    ++maximum_internal_threads;
593  }
594#endif
595
596  return maximum_internal_threads;
597}
598
599RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Internal_allocate( void )
600{
601  return (Thread_Control *)
602    _Objects_Allocate_unprotected( &_Thread_Internal_information );
603}
604
605RTEMS_INLINE_ROUTINE void _Thread_Request_dispatch_if_executing(
606  Thread_Control *thread
607)
608{
609#if defined(RTEMS_SMP)
610  if ( _Thread_Is_executing_on_a_processor( thread ) ) {
611    const Per_CPU_Control *cpu_of_executing = _Per_CPU_Get();
612    Per_CPU_Control *cpu_of_thread = _Thread_Get_CPU( thread );
613
614    cpu_of_thread->dispatch_necessary = true;
615
616    if ( cpu_of_executing != cpu_of_thread ) {
617      _Per_CPU_Send_interrupt( cpu_of_thread );
618    }
619  }
620#else
621  (void) thread;
622#endif
623}
624
625RTEMS_INLINE_ROUTINE void _Thread_Signal_notification( Thread_Control *thread )
626{
627  if ( _ISR_Is_in_progress() && _Thread_Is_executing( thread ) ) {
628    _Thread_Dispatch_necessary = true;
629  } else {
630#if defined(RTEMS_SMP)
631    if ( _Thread_Is_executing_on_a_processor( thread ) ) {
632      const Per_CPU_Control *cpu_of_executing = _Per_CPU_Get();
633      Per_CPU_Control *cpu_of_thread = _Thread_Get_CPU( thread );
634
635      if ( cpu_of_executing != cpu_of_thread ) {
636        cpu_of_thread->dispatch_necessary = true;
637        _Per_CPU_Send_interrupt( cpu_of_thread );
638      }
639    }
640#endif
641  }
642}
643
644/**
645 * @brief Gets the heir of the processor and makes it executing.
646 *
647 * The thread dispatch necessary indicator is cleared as a side-effect.
648 *
649 * @return The heir thread.
650 *
651 * @see _Thread_Dispatch(), _Thread_Start_multitasking() and
652 * _Scheduler_SMP_Update_heir().
653 */
654RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Get_heir_and_make_it_executing(
655  Per_CPU_Control *cpu_self
656)
657{
658  Thread_Control *heir;
659
660  cpu_self->dispatch_necessary = false;
661
662#if defined( RTEMS_SMP )
663  /*
664   * It is critical that we first update the dispatch necessary and then the
665   * read the heir so that we don't miss an update by
666   * _Scheduler_SMP_Update_heir().
667   */
668  _Atomic_Fence( ATOMIC_ORDER_SEQ_CST );
669#endif
670
671  heir = cpu_self->heir;
672  cpu_self->executing = heir;
673
674  return heir;
675}
676
677RTEMS_INLINE_ROUTINE void _Thread_Update_cpu_time_used(
678  Thread_Control *executing,
679  Timestamp_Control *time_of_last_context_switch
680)
681{
682  Timestamp_Control uptime;
683  Timestamp_Control ran;
684
685  _TOD_Get_uptime( &uptime );
686  _Timestamp_Subtract(
687    time_of_last_context_switch,
688    &uptime,
689    &ran
690  );
691  *time_of_last_context_switch = uptime;
692  _Timestamp_Add_to( &executing->cpu_time_used, &ran );
693}
694
695RTEMS_INLINE_ROUTINE void _Thread_Action_control_initialize(
696  Thread_Action_control *action_control
697)
698{
699  _Chain_Initialize_empty( &action_control->Chain );
700}
701
702RTEMS_INLINE_ROUTINE void _Thread_Action_initialize(
703  Thread_Action         *action,
704  Thread_Action_handler  handler
705)
706{
707  action->handler = handler;
708  _Chain_Set_off_chain( &action->Node );
709}
710
711RTEMS_INLINE_ROUTINE Per_CPU_Control *
712  _Thread_Action_ISR_disable_and_acquire_for_executing( ISR_Level *level )
713{
714  Per_CPU_Control *cpu;
715
716  _ISR_Disable_without_giant( *level );
717  cpu = _Per_CPU_Get();
718  _Per_CPU_Acquire( cpu );
719
720  return cpu;
721}
722
723RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Action_ISR_disable_and_acquire(
724  Thread_Control *thread,
725  ISR_Level      *level
726)
727{
728  Per_CPU_Control *cpu;
729
730  _ISR_Disable_without_giant( *level );
731  cpu = _Thread_Get_CPU( thread );
732  _Per_CPU_Acquire( cpu );
733
734  return cpu;
735}
736
737RTEMS_INLINE_ROUTINE void _Thread_Action_release_and_ISR_enable(
738  Per_CPU_Control *cpu,
739  ISR_Level level
740)
741{
742  _Per_CPU_Release_and_ISR_enable( cpu, level );
743}
744
745RTEMS_INLINE_ROUTINE void _Thread_Add_post_switch_action(
746  Thread_Control *thread,
747  Thread_Action  *action
748)
749{
750  Per_CPU_Control *cpu;
751  ISR_Level        level;
752
753  cpu = _Thread_Action_ISR_disable_and_acquire( thread, &level );
754  _Chain_Append_if_is_off_chain_unprotected(
755    &thread->Post_switch_actions.Chain,
756    &action->Node
757  );
758  _Thread_Action_release_and_ISR_enable( cpu, level );
759}
760
761RTEMS_INLINE_ROUTINE bool _Thread_Is_life_restarting(
762  Thread_Life_state life_state
763)
764{
765  return ( life_state & THREAD_LIFE_RESTARTING ) != 0;
766}
767
768RTEMS_INLINE_ROUTINE bool _Thread_Is_life_terminating(
769  Thread_Life_state life_state
770)
771{
772  return ( life_state & THREAD_LIFE_TERMINATING ) != 0;
773}
774
775RTEMS_INLINE_ROUTINE bool _Thread_Is_life_protected(
776  Thread_Life_state life_state
777)
778{
779  return ( life_state & THREAD_LIFE_PROTECTED ) != 0;
780}
781
782RTEMS_INLINE_ROUTINE bool _Thread_Is_life_changing(
783  Thread_Life_state life_state
784)
785{
786  return ( life_state & THREAD_LIFE_RESTARTING_TERMINATING ) != 0;
787}
788
789/**
790 * @brief Returns true if the thread owns resources, and false otherwise.
791 *
792 * Resources are accounted with the Thread_Control::resource_count resource
793 * counter.  This counter is used by semaphore objects for example.
794 *
795 * In addition to the resource counter there is a resource dependency tree
796 * available on SMP configurations.  In case this tree is non-empty, then the
797 * thread owns resources.
798 *
799 * @param[in] the_thread The thread.
800 */
801RTEMS_INLINE_ROUTINE bool _Thread_Owns_resources(
802  const Thread_Control *the_thread
803)
804{
805  bool owns_resources = the_thread->resource_count != 0;
806
807#if defined(RTEMS_SMP)
808  owns_resources = owns_resources
809    || _Resource_Node_owns_resources( &the_thread->Resource_node );
810#endif
811
812  return owns_resources;
813}
814
815RTEMS_INLINE_ROUTINE void _Thread_Debug_set_real_processor(
816  Thread_Control  *the_thread,
817  Per_CPU_Control *cpu
818)
819{
820#if defined(RTEMS_SMP) && defined(RTEMS_DEBUG)
821  the_thread->debug_real_cpu = cpu;
822#else
823  (void) the_thread;
824  (void) cpu;
825#endif
826}
827
828#if !defined(__DYNAMIC_REENT__)
829/**
830 * This routine returns the C library re-enterant pointer.
831 */
832
833RTEMS_INLINE_ROUTINE struct _reent **_Thread_Get_libc_reent( void )
834{
835  return _Thread_libc_reent;
836}
837
838/**
839 * This routine set the C library re-enterant pointer.
840 */
841
842RTEMS_INLINE_ROUTINE void _Thread_Set_libc_reent (
843  struct _reent **libc_reent
844)
845{
846  _Thread_libc_reent = libc_reent;
847}
848#endif
849
850/** @}*/
851
852#ifdef __cplusplus
853}
854#endif
855
856#if defined(RTEMS_MULTIPROCESSING)
857#include <rtems/score/threadmp.h>
858#endif
859
860#endif
861/* end of include file */
Note: See TracBrowser for help on using the repository browser.