source: rtems/cpukit/score/include/rtems/score/threadimpl.h @ 3d1becf

5
Last change on this file since 3d1becf was 44e9871, checked in by Sebastian Huber <sebastian.huber@…>, on 12/22/15 at 08:40:48

score: Avoid dead code in global construction

Update #2514.

  • Property mode set to 100644
File size: 38.4 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-2015 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/assert.h>
26#include <rtems/score/chainimpl.h>
27#include <rtems/score/interr.h>
28#include <rtems/score/isr.h>
29#include <rtems/score/objectimpl.h>
30#include <rtems/score/resourceimpl.h>
31#include <rtems/score/statesimpl.h>
32#include <rtems/score/sysstate.h>
33#include <rtems/score/threadqimpl.h>
34#include <rtems/score/todimpl.h>
35#include <rtems/score/freechain.h>
36#include <rtems/config.h>
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42/**
43 * @addtogroup ScoreThread
44 */
45/**@{**/
46
47/**
48 *  The following structure contains the information necessary to manage
49 *  a thread which it is  waiting for a resource.
50 */
51#define THREAD_STATUS_PROXY_BLOCKING 0x1111111
52
53/**
54 *  Self for the GNU Ada Run-Time
55 */
56SCORE_EXTERN void *rtems_ada_self;
57
58typedef struct {
59  Objects_Information Objects;
60
61  Freechain_Control Free_thread_queue_heads;
62} Thread_Information;
63
64/**
65 *  The following defines the information control block used to
66 *  manage this class of objects.
67 */
68SCORE_EXTERN Thread_Information _Thread_Internal_information;
69
70/**
71 *  The following points to the thread whose floating point
72 *  context is currently loaded.
73 */
74#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
75SCORE_EXTERN Thread_Control *_Thread_Allocated_fp;
76#endif
77
78#define THREAD_CHAIN_NODE_TO_THREAD( node ) \
79  RTEMS_CONTAINER_OF( node, Thread_Control, Wait.Node.Chain )
80
81#define THREAD_RBTREE_NODE_TO_THREAD( node ) \
82  RTEMS_CONTAINER_OF( node, Thread_Control, Wait.Node.RBTree )
83
84#if defined(RTEMS_SMP)
85#define THREAD_RESOURCE_NODE_TO_THREAD( node ) \
86  RTEMS_CONTAINER_OF( node, Thread_Control, Resource_node )
87#endif
88
89void _Thread_Initialize_information(
90  Thread_Information  *information,
91  Objects_APIs         the_api,
92  uint16_t             the_class,
93  uint32_t             maximum,
94  bool                 is_string,
95  uint32_t             maximum_name_length
96#if defined(RTEMS_MULTIPROCESSING)
97  ,
98  bool                 supports_global
99#endif
100);
101
102/**
103 *  @brief Initialize thread handler.
104 *
105 *  This routine performs the initialization necessary for this handler.
106 */
107void _Thread_Handler_initialization(void);
108
109/**
110 *  @brief Create 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 Start 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 Allocate 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[in] the_thread is the thread where the stack space is requested
134 *  @param[in] stack_size is the stack space is requested
135 *
136 *  @retval actual size allocated after any adjustment
137 *  @retval zero if the allocation failed
138 */
139size_t _Thread_Stack_Allocate(
140  Thread_Control *the_thread,
141  size_t          stack_size
142);
143
144/**
145 *  @brief Deallocate thread stack.
146 *
147 *  Deallocate the Thread's stack.
148 */
149void _Thread_Stack_Free(
150  Thread_Control *the_thread
151);
152
153/**
154 *  @brief Initialize thread.
155 *
156 *  This routine initializes the specified the thread.  It allocates
157 *  all memory associated with this thread.  It completes by adding
158 *  the thread to the local object table so operations on this
159 *  thread id are allowed.
160 *
161 *  @note If stack_area is NULL, it is allocated from the workspace.
162 *
163 *  @note If the stack is allocated from the workspace, then it is
164 *        guaranteed to be of at least minimum size.
165 */
166bool _Thread_Initialize(
167  Thread_Information                   *information,
168  Thread_Control                       *the_thread,
169  const struct Scheduler_Control       *scheduler,
170  void                                 *stack_area,
171  size_t                                stack_size,
172  bool                                  is_fp,
173  Priority_Control                      priority,
174  bool                                  is_preemptible,
175  Thread_CPU_budget_algorithms          budget_algorithm,
176  Thread_CPU_budget_algorithm_callout   budget_callout,
177  uint32_t                              isr_level,
178  Objects_Name                          name
179);
180
181/**
182 *  @brief Initializes thread and executes it.
183 *
184 *  This routine initializes the executable information for a thread
185 *  and makes it ready to execute.  After this routine executes, the
186 *  thread competes with all other threads for CPU time.
187 *
188 *  @param the_thread is the thread to be initialized
189 *  @param the_prototype
190 *  @param entry_point
191 *  @param pointer_argument
192 *  @param numeric_argument
193 *  @param[in,out] cpu The processor if used to start an idle thread
194 *  during system initialization.  Must be set to @c NULL to start a normal
195 *  thread.
196 */
197bool _Thread_Start(
198  Thread_Control            *the_thread,
199  Thread_Start_types         the_prototype,
200  void                      *entry_point,
201  void                      *pointer_argument,
202  Thread_Entry_numeric_type  numeric_argument,
203  Per_CPU_Control           *cpu
204);
205
206bool _Thread_Restart(
207  Thread_Control            *the_thread,
208  Thread_Control            *executing,
209  void                      *pointer_argument,
210  Thread_Entry_numeric_type  numeric_argument
211);
212
213void _Thread_Yield( Thread_Control *executing );
214
215bool _Thread_Set_life_protection( bool protect );
216
217void _Thread_Life_action_handler(
218  Thread_Control  *executing,
219  Thread_Action   *action,
220  Per_CPU_Control *cpu,
221  ISR_Level        level
222);
223
224/**
225 * @brief Kills all zombie threads in the system.
226 *
227 * Threads change into the zombie state as the last step in the thread
228 * termination sequence right before a context switch to the heir thread is
229 * initiated.  Since the thread stack is still in use during this phase we have
230 * to postpone the thread stack reclamation until this point.  On SMP
231 * configurations we may have to busy wait for context switch completion here.
232 */
233void _Thread_Kill_zombies( void );
234
235/**
236 * @brief Closes the thread.
237 *
238 * Closes the thread object and starts the thread termination sequence.  In
239 * case the executing thread is not terminated, then this function waits until
240 * the terminating thread reached the zombie state.
241 */
242void _Thread_Close( Thread_Control *the_thread, Thread_Control *executing );
243
244/**
245 * @brief Clears the specified thread state.
246 *
247 * In case the previous state is a non-ready state and the next state is the
248 * ready state, then the thread is unblocked by the scheduler.
249 *
250 * @param[in] the_thread The thread.
251 * @param[in] state The state to clear.  It must not be zero.
252 *
253 * @return The previous state.
254 */
255States_Control _Thread_Clear_state(
256  Thread_Control *the_thread,
257  States_Control  state
258);
259
260/**
261 * @brief Sets the specified thread state.
262 *
263 * In case the previous state is the ready state, then the thread is blocked by
264 * the scheduler.
265 *
266 * @param[in] the_thread The thread.
267 * @param[in] state The state to set.  It must not be zero.
268 *
269 * @return The previous state.
270 */
271States_Control _Thread_Set_state(
272  Thread_Control *the_thread,
273  States_Control  state
274);
275
276/**
277 * @brief Clears all thread states.
278 *
279 * In case the previous state is a non-ready state, then the thread is
280 * unblocked by the scheduler.
281 *
282 * @param[in] the_thread The thread.
283 */
284RTEMS_INLINE_ROUTINE void _Thread_Ready(
285  Thread_Control *the_thread
286)
287{
288  _Thread_Clear_state( the_thread, STATES_ALL_SET );
289}
290
291/**
292 *  @brief Initializes enviroment for a thread.
293 *
294 *  This routine initializes the context of @a the_thread to its
295 *  appropriate starting state.
296 *
297 *  @param[in] the_thread is the pointer to the thread control block.
298 */
299void _Thread_Load_environment(
300  Thread_Control *the_thread
301);
302
303/**
304 *  @brief Wrapper function for all threads.
305 *
306 *  This routine is the wrapper function for all threads.  It is
307 *  the starting point for all threads.  The user provided thread
308 *  entry point is invoked by this routine.  Operations
309 *  which must be performed immediately before and after the user's
310 *  thread executes are found here.
311 *
312 *  @note On entry, it is assumed all interrupts are blocked and that this
313 *  routine needs to set the initial isr level.  This may or may not
314 *  actually be needed by the context switch routine and as a result
315 *  interrupts may already be at there proper level.  Either way,
316 *  setting the initial isr level properly here is safe.
317 */
318void _Thread_Handler( void );
319
320/**
321 * @brief Executes the global constructors and then restarts itself as the
322 * first initialization thread.
323 *
324 * The first initialization thread is the first RTEMS initialization task or
325 * the first POSIX initialization thread in case no RTEMS initialization tasks
326 * are present.
327 */
328void _Thread_Global_construction( Thread_Entry entry_point ) RTEMS_NO_RETURN;
329
330/**
331 *  @brief Ended the delay of a thread.
332 *
333 *  This routine is invoked when a thread must be unblocked at the
334 *  end of a time based delay (i.e. wake after or wake when).
335 *  It is called by the watchdog handler.
336 *
337 *  @param[in] id is the thread id
338 *  @param[in] ignored is not used
339 */
340void _Thread_Delay_ended(
341  Objects_Id  id,
342  void       *ignored
343);
344
345/**
346 * @brief Returns true if the left thread priority is less than the right
347 * thread priority in the intuitive sense of priority and false otherwise.
348 */
349RTEMS_INLINE_ROUTINE bool _Thread_Priority_less_than(
350  Priority_Control left,
351  Priority_Control right
352)
353{
354  return left > right;
355}
356
357/**
358 * @brief Returns the highest priority of the left and right thread priorities
359 * in the intuitive sense of priority.
360 */
361RTEMS_INLINE_ROUTINE Priority_Control _Thread_Priority_highest(
362  Priority_Control left,
363  Priority_Control right
364)
365{
366  return _Thread_Priority_less_than( left, right ) ? right : left;
367}
368
369/**
370 * @brief Filters a thread priority change.
371 *
372 * Called by _Thread_Change_priority() under the protection of the thread lock.
373 *
374 * @param[in] the_thread The thread.
375 * @param[in, out] new_priority The new priority of the thread.  The filter may
376 * alter this value.
377 * @param[in] arg The argument passed to _Thread_Change_priority().
378 *
379 * @retval true Change the current priority.
380 * @retval false Otherwise.
381 */
382typedef bool ( *Thread_Change_priority_filter )(
383  Thread_Control   *the_thread,
384  Priority_Control *new_priority,
385  void             *arg
386);
387
388/**
389 * @brief Changes the priority of a thread if allowed by the filter function.
390 *
391 * It changes current priority of the thread to the new priority in case the
392 * filter function returns true.  In this case the scheduler is notified of the
393 * priority change as well.
394 *
395 * @param[in] the_thread The thread.
396 * @param[in] new_priority The new priority of the thread.
397 * @param[in] arg The argument for the filter function.
398 * @param[in] filter The filter function to determine if a priority change is
399 * allowed and optionally perform other actions under the protection of the
400 * thread lock simultaneously with the update of the current priority.
401 * @param[in] prepend_it In case this is true, then the thread is prepended to
402 * its priority group in its scheduler instance, otherwise it is appended.
403 */
404void _Thread_Change_priority(
405  Thread_Control                *the_thread,
406  Priority_Control               new_priority,
407  void                          *arg,
408  Thread_Change_priority_filter  filter,
409  bool                           prepend_it
410);
411
412/**
413 * @brief Raises the priority of a thread.
414 *
415 * It changes the current priority of the thread to the new priority if the new
416 * priority is higher than the current priority.  In this case the thread is
417 * appended to its new priority group in its scheduler instance.
418 *
419 * @param[in] the_thread The thread.
420 * @param[in] new_priority The new priority of the thread.
421 *
422 * @see _Thread_Change_priority().
423 */
424void _Thread_Raise_priority(
425  Thread_Control   *the_thread,
426  Priority_Control  new_priority
427);
428
429/**
430 * @brief Inherit the priority of a thread.
431 *
432 * It changes the current priority of the inheritor thread to the current priority
433 * of the ancestor thread if it is higher than the current priority of the inheritor
434 * thread.  In this case the inheritor thread is appended to its new priority group
435 * in its scheduler instance.
436 *
437 * On SMP configurations, the priority is changed to PRIORITY_PSEUDO_ISR in
438 * case the own schedulers of the inheritor and ancestor thread differ (priority
439 * boosting).
440 *
441 * @param[in] inheritor The thread to inherit the priority.
442 * @param[in] ancestor The thread to bequeath its priority to the inheritor
443 *   thread.
444 */
445#if defined(RTEMS_SMP)
446void _Thread_Inherit_priority(
447  Thread_Control *inheritor,
448  Thread_Control *ancestor
449);
450#else
451RTEMS_INLINE_ROUTINE void _Thread_Inherit_priority(
452  Thread_Control *inheritor,
453  Thread_Control *ancestor
454)
455{
456  _Thread_Raise_priority( inheritor, ancestor->current_priority );
457}
458#endif
459
460/**
461 * @brief Sets the current to the real priority of a thread.
462 *
463 * Sets the priority restore hint to false.
464 */
465void _Thread_Restore_priority( Thread_Control *the_thread );
466
467/**
468 * @brief Sets the priority of a thread.
469 *
470 * It sets the real priority of the thread.  In addition it changes the current
471 * priority of the thread if the new priority is higher than the current
472 * priority or the thread owns no resources.
473 *
474 * @param[in] the_thread The thread.
475 * @param[in] new_priority The new priority of the thread.
476 * @param[out] old_priority The old real priority of the thread.  This pointer
477 * must not be @c NULL.
478 * @param[in] prepend_it In case this is true, then the thread is prepended to
479 * its priority group in its scheduler instance, otherwise it is appended.
480 *
481 * @see _Thread_Change_priority().
482 */
483void _Thread_Set_priority(
484  Thread_Control   *the_thread,
485  Priority_Control  new_priority,
486  Priority_Control *old_priority,
487  bool              prepend_it
488);
489
490/**
491 *  @brief Maps thread Id to a TCB pointer.
492 *
493 *  This function maps thread IDs to thread control
494 *  blocks.  If ID corresponds to a local thread, then it
495 *  returns the_thread control pointer which maps to ID
496 *  and @a location is set to OBJECTS_LOCAL.  If the thread ID is
497 *  global and resides on a remote node, then location is set
498 *  to OBJECTS_REMOTE, and the_thread is undefined.
499 *  Otherwise, location is set to OBJECTS_ERROR and
500 *  the_thread is undefined.
501 *
502 *  @param[in] id is the id of the thread.
503 *  @param[in] location is the location of the block.
504 *
505 *  @note  The performance of many RTEMS services depends upon
506 *         the quick execution of the "good object" path in this
507 *         routine.  If there is a possibility of saving a few
508 *         cycles off the execution time, this routine is worth
509 *         further optimization attention.
510 */
511Thread_Control *_Thread_Get (
512  Objects_Id         id,
513  Objects_Locations *location
514);
515
516/**
517 * @brief Gets a thread by its identifier.
518 *
519 * @see _Objects_Get_isr_disable().
520 */
521Thread_Control *_Thread_Get_interrupt_disable(
522  Objects_Id         id,
523  Objects_Locations *location,
524  ISR_lock_Context  *lock_context
525);
526
527RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Get_CPU(
528  const Thread_Control *thread
529)
530{
531#if defined(RTEMS_SMP)
532  return thread->Scheduler.cpu;
533#else
534  (void) thread;
535
536  return _Per_CPU_Get();
537#endif
538}
539
540RTEMS_INLINE_ROUTINE void _Thread_Set_CPU(
541  Thread_Control *thread,
542  Per_CPU_Control *cpu
543)
544{
545#if defined(RTEMS_SMP)
546  thread->Scheduler.cpu = cpu;
547#else
548  (void) thread;
549  (void) cpu;
550#endif
551}
552
553/**
554 * This function returns true if the_thread is the currently executing
555 * thread, and false otherwise.
556 */
557
558RTEMS_INLINE_ROUTINE bool _Thread_Is_executing (
559  const Thread_Control *the_thread
560)
561{
562  return ( the_thread == _Thread_Executing );
563}
564
565#if defined(RTEMS_SMP)
566/**
567 * @brief Returns @a true in case the thread executes currently on some
568 * processor in the system, otherwise @a false.
569 *
570 * Do not confuse this with _Thread_Is_executing() which checks only the
571 * current processor.
572 */
573RTEMS_INLINE_ROUTINE bool _Thread_Is_executing_on_a_processor(
574  const Thread_Control *the_thread
575)
576{
577  return _CPU_Context_Get_is_executing( &the_thread->Registers );
578}
579#endif
580
581/**
582 * @brief Returns @a true and sets time_of_context_switch to the
583 * time of the last context switch when the thread is currently executing
584 * in the system, otherwise @a false.
585 */
586RTEMS_INLINE_ROUTINE bool _Thread_Get_time_of_last_context_switch(
587  Thread_Control    *the_thread,
588  Timestamp_Control *time_of_context_switch
589)
590{
591  bool retval = false;
592
593  _Thread_Disable_dispatch();
594  #ifndef RTEMS_SMP
595    if ( _Thread_Executing->Object.id == the_thread->Object.id ) {
596      *time_of_context_switch = _Thread_Time_of_last_context_switch;
597      retval = true;
598    }
599  #else
600    if ( _Thread_Is_executing_on_a_processor( the_thread ) ) {
601      *time_of_context_switch =
602        _Thread_Get_CPU( the_thread )->time_of_last_context_switch;
603      retval = true;
604    }
605  #endif
606  _Thread_Enable_dispatch();
607  return retval;
608}
609
610
611/**
612 * This function returns true if the_thread is the heir
613 * thread, and false otherwise.
614 */
615
616RTEMS_INLINE_ROUTINE bool _Thread_Is_heir (
617  const Thread_Control *the_thread
618)
619{
620  return ( the_thread == _Thread_Heir );
621}
622
623/**
624 * This routine clears any blocking state for the_thread.  It performs
625 * any necessary scheduling operations including the selection of
626 * a new heir thread.
627 */
628
629RTEMS_INLINE_ROUTINE void _Thread_Unblock (
630  Thread_Control *the_thread
631)
632{
633  _Thread_Clear_state( the_thread, STATES_BLOCKED );
634}
635
636/**
637 * This routine resets the current context of the calling thread
638 * to that of its initial state.
639 */
640
641RTEMS_INLINE_ROUTINE void _Thread_Restart_self( Thread_Control *executing )
642{
643#if defined(RTEMS_SMP)
644  ISR_Level level;
645
646  _Giant_Release( _Per_CPU_Get() );
647
648  _ISR_Disable_without_giant( level );
649  ( void ) level;
650#endif
651
652#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
653  if ( executing->fp_context != NULL )
654    _Context_Restore_fp( &executing->fp_context );
655#endif
656
657  _CPU_Context_Restart_self( &executing->Registers );
658}
659
660/**
661 * This function returns true if the floating point context of
662 * the_thread is currently loaded in the floating point unit, and
663 * false otherwise.
664 */
665
666#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
667RTEMS_INLINE_ROUTINE bool _Thread_Is_allocated_fp (
668  const Thread_Control *the_thread
669)
670{
671  return ( the_thread == _Thread_Allocated_fp );
672}
673#endif
674
675/*
676 *  If the CPU has hardware floating point, then we must address saving
677 *  and restoring it as part of the context switch.
678 *
679 *  The second conditional compilation section selects the algorithm used
680 *  to context switch between floating point tasks.  The deferred algorithm
681 *  can be significantly better in a system with few floating point tasks
682 *  because it reduces the total number of save and restore FP context
683 *  operations.  However, this algorithm can not be used on all CPUs due
684 *  to unpredictable use of FP registers by some compilers for integer
685 *  operations.
686 */
687
688RTEMS_INLINE_ROUTINE void _Thread_Save_fp( Thread_Control *executing )
689{
690#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
691#if ( CPU_USE_DEFERRED_FP_SWITCH != TRUE )
692  if ( executing->fp_context != NULL )
693    _Context_Save_fp( &executing->fp_context );
694#endif
695#endif
696}
697
698RTEMS_INLINE_ROUTINE void _Thread_Restore_fp( Thread_Control *executing )
699{
700#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
701#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
702  if ( (executing->fp_context != NULL) &&
703       !_Thread_Is_allocated_fp( executing ) ) {
704    if ( _Thread_Allocated_fp != NULL )
705      _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
706    _Context_Restore_fp( &executing->fp_context );
707    _Thread_Allocated_fp = executing;
708  }
709#else
710  if ( executing->fp_context != NULL )
711    _Context_Restore_fp( &executing->fp_context );
712#endif
713#endif
714}
715
716/**
717 * This routine is invoked when the currently loaded floating
718 * point context is now longer associated with an active thread.
719 */
720
721#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
722RTEMS_INLINE_ROUTINE void _Thread_Deallocate_fp( void )
723{
724  _Thread_Allocated_fp = NULL;
725}
726#endif
727
728/**
729 * This function returns true if dispatching is disabled, and false
730 * otherwise.
731 */
732
733RTEMS_INLINE_ROUTINE bool _Thread_Is_context_switch_necessary( void )
734{
735  return ( _Thread_Dispatch_necessary );
736}
737
738/**
739 * This function returns true if the_thread is NULL and false otherwise.
740 */
741
742RTEMS_INLINE_ROUTINE bool _Thread_Is_null (
743  const Thread_Control *the_thread
744)
745{
746  return ( the_thread == NULL );
747}
748
749/**
750 * @brief Is proxy blocking.
751 *
752 * status which indicates that a proxy is blocking, and false otherwise.
753 */
754RTEMS_INLINE_ROUTINE bool _Thread_Is_proxy_blocking (
755  uint32_t   code
756)
757{
758  return (code == THREAD_STATUS_PROXY_BLOCKING);
759}
760
761RTEMS_INLINE_ROUTINE uint32_t _Thread_Get_maximum_internal_threads(void)
762{
763  /* Idle threads */
764  uint32_t maximum_internal_threads =
765    rtems_configuration_get_maximum_processors();
766
767  /* MPCI thread */
768#if defined(RTEMS_MULTIPROCESSING)
769  if ( _System_state_Is_multiprocessing ) {
770    ++maximum_internal_threads;
771  }
772#endif
773
774  return maximum_internal_threads;
775}
776
777RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Internal_allocate( void )
778{
779  return (Thread_Control *)
780    _Objects_Allocate_unprotected( &_Thread_Internal_information.Objects );
781}
782
783/**
784 * @brief Gets the heir of the processor and makes it executing.
785 *
786 * Must be called with interrupts disabled.  The thread dispatch necessary
787 * indicator is cleared as a side-effect.
788 *
789 * @return The heir thread.
790 *
791 * @see _Thread_Dispatch(), _Thread_Start_multitasking() and
792 * _Thread_Dispatch_update_heir().
793 */
794RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Get_heir_and_make_it_executing(
795  Per_CPU_Control *cpu_self
796)
797{
798  Thread_Control *heir;
799
800  heir = cpu_self->heir;
801  cpu_self->dispatch_necessary = false;
802  cpu_self->executing = heir;
803
804  return heir;
805}
806
807#if defined( RTEMS_SMP )
808RTEMS_INLINE_ROUTINE void _Thread_Dispatch_update_heir(
809  Per_CPU_Control *cpu_self,
810  Per_CPU_Control *cpu_for_heir,
811  Thread_Control  *heir
812)
813{
814  cpu_for_heir->heir = heir;
815
816  if ( cpu_for_heir == cpu_self ) {
817    cpu_self->dispatch_necessary = true;
818  } else {
819    _Per_CPU_Send_interrupt( cpu_for_heir );
820  }
821}
822#endif
823
824RTEMS_INLINE_ROUTINE void _Thread_Update_cpu_time_used(
825  Thread_Control *executing,
826  Timestamp_Control *time_of_last_context_switch
827)
828{
829  Timestamp_Control uptime;
830  Timestamp_Control ran;
831
832  _TOD_Get_uptime( &uptime );
833  _Timestamp_Subtract(
834    time_of_last_context_switch,
835    &uptime,
836    &ran
837  );
838  *time_of_last_context_switch = uptime;
839  _Timestamp_Add_to( &executing->cpu_time_used, &ran );
840}
841
842RTEMS_INLINE_ROUTINE void _Thread_Action_control_initialize(
843  Thread_Action_control *action_control
844)
845{
846  _Chain_Initialize_empty( &action_control->Chain );
847}
848
849RTEMS_INLINE_ROUTINE void _Thread_Action_initialize(
850  Thread_Action *action
851)
852{
853  _Chain_Set_off_chain( &action->Node );
854}
855
856RTEMS_INLINE_ROUTINE Per_CPU_Control *
857  _Thread_Action_ISR_disable_and_acquire_for_executing( ISR_Level *level )
858{
859  Per_CPU_Control *cpu;
860
861  _ISR_Disable_without_giant( *level );
862  cpu = _Per_CPU_Get();
863  _Per_CPU_Acquire( cpu );
864
865  return cpu;
866}
867
868RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Action_ISR_disable_and_acquire(
869  Thread_Control *thread,
870  ISR_Level      *level
871)
872{
873  Per_CPU_Control *cpu;
874
875  _ISR_Disable_without_giant( *level );
876  cpu = _Thread_Get_CPU( thread );
877  _Per_CPU_Acquire( cpu );
878
879  return cpu;
880}
881
882RTEMS_INLINE_ROUTINE void _Thread_Action_release_and_ISR_enable(
883  Per_CPU_Control *cpu,
884  ISR_Level level
885)
886{
887  _Per_CPU_Release_and_ISR_enable( cpu, level );
888}
889
890RTEMS_INLINE_ROUTINE void _Thread_Add_post_switch_action(
891  Thread_Control        *thread,
892  Thread_Action         *action,
893  Thread_Action_handler  handler
894)
895{
896  Per_CPU_Control *cpu_of_thread;
897  ISR_Level        level;
898
899  cpu_of_thread = _Thread_Action_ISR_disable_and_acquire( thread, &level );
900
901  action->handler = handler;
902
903#if defined(RTEMS_SMP)
904  if ( _Per_CPU_Get() == cpu_of_thread ) {
905    cpu_of_thread->dispatch_necessary = true;
906  } else {
907    _Per_CPU_Send_interrupt( cpu_of_thread );
908  }
909#else
910  cpu_of_thread->dispatch_necessary = true;
911#endif
912
913  _Chain_Append_if_is_off_chain_unprotected(
914    &thread->Post_switch_actions.Chain,
915    &action->Node
916  );
917
918  _Thread_Action_release_and_ISR_enable( cpu_of_thread, level );
919}
920
921RTEMS_INLINE_ROUTINE bool _Thread_Is_life_restarting(
922  Thread_Life_state life_state
923)
924{
925  return ( life_state & THREAD_LIFE_RESTARTING ) != 0;
926}
927
928RTEMS_INLINE_ROUTINE bool _Thread_Is_life_terminating(
929  Thread_Life_state life_state
930)
931{
932  return ( life_state & THREAD_LIFE_TERMINATING ) != 0;
933}
934
935RTEMS_INLINE_ROUTINE bool _Thread_Is_life_protected(
936  Thread_Life_state life_state
937)
938{
939  return ( life_state & THREAD_LIFE_PROTECTED ) != 0;
940}
941
942RTEMS_INLINE_ROUTINE bool _Thread_Is_life_changing(
943  Thread_Life_state life_state
944)
945{
946  return ( life_state & THREAD_LIFE_RESTARTING_TERMINATING ) != 0;
947}
948
949/**
950 * @brief Returns true if the thread owns resources, and false otherwise.
951 *
952 * Resources are accounted with the Thread_Control::resource_count resource
953 * counter.  This counter is used by semaphore objects for example.
954 *
955 * In addition to the resource counter there is a resource dependency tree
956 * available on SMP configurations.  In case this tree is non-empty, then the
957 * thread owns resources.
958 *
959 * @param[in] the_thread The thread.
960 */
961RTEMS_INLINE_ROUTINE bool _Thread_Owns_resources(
962  const Thread_Control *the_thread
963)
964{
965  bool owns_resources = the_thread->resource_count != 0;
966
967#if defined(RTEMS_SMP)
968  owns_resources = owns_resources
969    || _Resource_Node_owns_resources( &the_thread->Resource_node );
970#endif
971
972  return owns_resources;
973}
974
975/**
976 * @brief Acquires the default thread lock inside a critical section
977 * (interrupts disabled).
978 *
979 * @param[in] the_thread The thread.
980 * @param[in] lock_context The lock context used for the corresponding lock
981 * release.
982 *
983 * @see _Thread_Lock_release_default().
984 */
985RTEMS_INLINE_ROUTINE void _Thread_Lock_acquire_default_critical(
986  Thread_Control   *the_thread,
987  ISR_lock_Context *lock_context
988)
989{
990  _Assert( _ISR_Get_level() != 0 );
991#if defined(RTEMS_SMP)
992  _SMP_ticket_lock_Acquire(
993    &the_thread->Lock.Default,
994    &_Thread_Executing->Lock.Stats,
995    &lock_context->Lock_context.Stats_context
996  );
997#else
998  (void) the_thread;
999  (void) lock_context;
1000#endif
1001}
1002
1003/**
1004 * @brief Acquires the default thread lock and returns the executing thread.
1005 *
1006 * @param[in] lock_context The lock context used for the corresponding lock
1007 * release.
1008 *
1009 * @return The executing thread.
1010 *
1011 * @see _Thread_Lock_release_default().
1012 */
1013RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Lock_acquire_default_for_executing(
1014  ISR_lock_Context *lock_context
1015)
1016{
1017  Thread_Control *executing;
1018
1019  _ISR_lock_ISR_disable( lock_context );
1020  executing = _Thread_Executing;
1021  _Thread_Lock_acquire_default_critical( executing, lock_context );
1022
1023  return executing;
1024}
1025
1026/**
1027 * @brief Acquires the default thread lock.
1028 *
1029 * @param[in] the_thread The thread.
1030 * @param[in] lock_context The lock context used for the corresponding lock
1031 * release.
1032 *
1033 * @see _Thread_Lock_release_default().
1034 */
1035RTEMS_INLINE_ROUTINE void _Thread_Lock_acquire_default(
1036  Thread_Control   *the_thread,
1037  ISR_lock_Context *lock_context
1038)
1039{
1040  _ISR_lock_ISR_disable( lock_context );
1041  _Thread_Lock_acquire_default_critical( the_thread, lock_context );
1042}
1043
1044/**
1045 * @brief Releases the thread lock inside a critical section (interrupts
1046 * disabled).
1047 *
1048 * The previous interrupt status is not restored.
1049 *
1050 * @param[in] lock The lock.
1051 * @param[in] lock_context The lock context used for the corresponding lock
1052 * acquire.
1053 */
1054RTEMS_INLINE_ROUTINE void _Thread_Lock_release_critical(
1055  void             *lock,
1056  ISR_lock_Context *lock_context
1057)
1058{
1059#if defined(RTEMS_SMP)
1060  _SMP_ticket_lock_Release(
1061    lock,
1062    &lock_context->Lock_context.Stats_context
1063  );
1064#else
1065  (void) lock;
1066  (void) lock_context;
1067#endif
1068}
1069
1070/**
1071 * @brief Releases the thread lock.
1072 *
1073 * @param[in] lock The lock returned by _Thread_Lock_acquire().
1074 * @param[in] lock_context The lock context used for _Thread_Lock_acquire().
1075 */
1076RTEMS_INLINE_ROUTINE void _Thread_Lock_release(
1077  void             *lock,
1078  ISR_lock_Context *lock_context
1079)
1080{
1081  _Thread_Lock_release_critical( lock, lock_context );
1082  _ISR_lock_ISR_enable( lock_context );
1083}
1084
1085/**
1086 * @brief Releases the default thread lock inside a critical section
1087 * (interrupts disabled).
1088 *
1089 * The previous interrupt status is not restored.
1090 *
1091 * @param[in] the_thread The thread.
1092 * @param[in] lock_context The lock context used for the corresponding lock
1093 * acquire.
1094 */
1095RTEMS_INLINE_ROUTINE void _Thread_Lock_release_default_critical(
1096  Thread_Control   *the_thread,
1097  ISR_lock_Context *lock_context
1098)
1099{
1100  _Thread_Lock_release_critical(
1101#if defined(RTEMS_SMP)
1102    &the_thread->Lock.Default,
1103#else
1104    NULL,
1105#endif
1106    lock_context
1107  );
1108}
1109
1110/**
1111 * @brief Releases the default thread lock.
1112 *
1113 * @param[in] the_thread The thread.
1114 * @param[in] lock_context The lock context used for the corresponding lock
1115 * acquire.
1116 */
1117RTEMS_INLINE_ROUTINE void _Thread_Lock_release_default(
1118  Thread_Control   *the_thread,
1119  ISR_lock_Context *lock_context
1120)
1121{
1122  _Thread_Lock_release_default_critical( the_thread, lock_context );
1123  _ISR_lock_ISR_enable( lock_context );
1124}
1125
1126/**
1127 * @brief Acquires the thread lock.
1128 *
1129 * @param[in] the_thread The thread.
1130 * @param[in] lock_context The lock context for _Thread_Lock_release().
1131 *
1132 * @return The lock required by _Thread_Lock_release().
1133 */
1134RTEMS_INLINE_ROUTINE void *_Thread_Lock_acquire(
1135  Thread_Control   *the_thread,
1136  ISR_lock_Context *lock_context
1137)
1138{
1139#if defined(RTEMS_SMP)
1140  SMP_ticket_lock_Control *lock;
1141
1142  while ( true ) {
1143    unsigned int first_generation;
1144    unsigned int second_generation;
1145
1146    _ISR_lock_ISR_disable( lock_context );
1147
1148    /*
1149     * Ensure that we read our first lock generation before we obtain our
1150     * current lock.  See _Thread_Lock_set_unprotected().
1151     */
1152    first_generation = _Atomic_Load_uint(
1153      &the_thread->Lock.generation,
1154      ATOMIC_ORDER_ACQUIRE
1155    );
1156
1157    lock = the_thread->Lock.current;
1158    _SMP_ticket_lock_Acquire(
1159      lock,
1160      &_Thread_Executing->Lock.Stats,
1161      &lock_context->Lock_context.Stats_context
1162    );
1163
1164    /*
1165     * The C11 memory model doesn't guarantee that we read the latest
1166     * generation here.  For this a read-modify-write operation would be
1167     * necessary.  We read at least the new generation set up by the owner of
1168     * our current thread lock, and so on.
1169     */
1170    second_generation = _Atomic_Load_uint(
1171      &the_thread->Lock.generation,
1172      ATOMIC_ORDER_ACQUIRE
1173    );
1174
1175    if ( first_generation == second_generation ) {
1176      return lock;
1177    }
1178
1179    _Thread_Lock_release( lock, lock_context );
1180  }
1181#else
1182  _ISR_Disable( lock_context->isr_level );
1183
1184  return NULL;
1185#endif
1186}
1187
1188#if defined(RTEMS_SMP)
1189/*
1190 * Internal function, use _Thread_Lock_set() or _Thread_Lock_restore_default()
1191 * instead.
1192 */
1193RTEMS_INLINE_ROUTINE void _Thread_Lock_set_unprotected(
1194  Thread_Control          *the_thread,
1195  SMP_ticket_lock_Control *new_lock
1196)
1197{
1198  the_thread->Lock.current = new_lock;
1199
1200  /*
1201   * The generation release corresponds to the generation acquire in
1202   * _Thread_Lock_acquire() and ensures that the new lock and other fields are
1203   * visible to the next thread lock owner.  Otherwise someone would be able to
1204   * read an up to date generation number and an old lock.  See
1205   * _Thread_Wait_set_queue() and _Thread_Wait_restore_default_operations().
1206   *
1207   * Since we set a new lock right before, this increment is not protected by a
1208   * lock and thus must be an atomic operation.
1209   */
1210  _Atomic_Fetch_add_uint(
1211    &the_thread->Lock.generation,
1212    1,
1213    ATOMIC_ORDER_RELEASE
1214  );
1215}
1216#endif
1217
1218/**
1219 * @brief Sets a new thread lock.
1220 *
1221 * The caller must not be the owner of the default thread lock.  The caller
1222 * must be the owner of the new lock.
1223 *
1224 * @param[in] the_thread The thread.
1225 * @param[in] new_lock The new thread lock.
1226 */
1227#if defined(RTEMS_SMP)
1228RTEMS_INLINE_ROUTINE void _Thread_Lock_set(
1229  Thread_Control          *the_thread,
1230  SMP_ticket_lock_Control *new_lock
1231)
1232{
1233  ISR_lock_Context lock_context;
1234
1235  _Thread_Lock_acquire_default_critical( the_thread, &lock_context );
1236  _Assert( the_thread->Lock.current == &the_thread->Lock.Default );
1237  _Thread_Lock_set_unprotected( the_thread, new_lock );
1238  _Thread_Lock_release_default_critical( the_thread, &lock_context );
1239}
1240#else
1241#define _Thread_Lock_set( the_thread, new_lock ) \
1242  do { } while ( 0 )
1243#endif
1244
1245/**
1246 * @brief Restores the default thread lock.
1247 *
1248 * The caller must be the owner of the current thread lock.
1249 *
1250 * @param[in] the_thread The thread.
1251 */
1252#if defined(RTEMS_SMP)
1253RTEMS_INLINE_ROUTINE void _Thread_Lock_restore_default(
1254  Thread_Control *the_thread
1255)
1256{
1257  _Thread_Lock_set_unprotected( the_thread, &the_thread->Lock.Default );
1258}
1259#else
1260#define _Thread_Lock_restore_default( the_thread ) \
1261  do { } while ( 0 )
1262#endif
1263
1264/**
1265 * @brief The initial thread wait flags value set by _Thread_Initialize().
1266 */
1267#define THREAD_WAIT_FLAGS_INITIAL 0x0U
1268
1269/**
1270 * @brief Mask to get the thread wait state flags.
1271 */
1272#define THREAD_WAIT_STATE_MASK 0xffU
1273
1274/**
1275 * @brief Indicates that the thread begins with the blocking operation.
1276 *
1277 * A blocking operation consists of an optional watchdog initialization and the
1278 * setting of the appropriate thread blocking state with the corresponding
1279 * scheduler block operation.
1280 */
1281#define THREAD_WAIT_STATE_INTEND_TO_BLOCK 0x1U
1282
1283/**
1284 * @brief Indicates that the thread completed the blocking operation.
1285 */
1286#define THREAD_WAIT_STATE_BLOCKED 0x2U
1287
1288/**
1289 * @brief Indicates that a condition to end the thread wait occurred.
1290 *
1291 * This could be a timeout, a signal, an event or a resource availability.
1292 */
1293#define THREAD_WAIT_STATE_READY_AGAIN 0x4U
1294
1295/**
1296 * @brief Mask to get the thread wait class flags.
1297 */
1298#define THREAD_WAIT_CLASS_MASK 0xff00U
1299
1300/**
1301 * @brief Indicates that the thread waits for an event.
1302 */
1303#define THREAD_WAIT_CLASS_EVENT 0x100U
1304
1305/**
1306 * @brief Indicates that the thread waits for a system event.
1307 */
1308#define THREAD_WAIT_CLASS_SYSTEM_EVENT 0x200U
1309
1310/**
1311 * @brief Indicates that the thread waits for a object.
1312 */
1313#define THREAD_WAIT_CLASS_OBJECT 0x400U
1314
1315RTEMS_INLINE_ROUTINE void _Thread_Wait_flags_set(
1316  Thread_Control    *the_thread,
1317  Thread_Wait_flags  flags
1318)
1319{
1320#if defined(RTEMS_SMP)
1321  _Atomic_Store_uint( &the_thread->Wait.flags, flags, ATOMIC_ORDER_RELAXED );
1322#else
1323  the_thread->Wait.flags = flags;
1324#endif
1325}
1326
1327RTEMS_INLINE_ROUTINE Thread_Wait_flags _Thread_Wait_flags_get(
1328  const Thread_Control *the_thread
1329)
1330{
1331#if defined(RTEMS_SMP)
1332  return _Atomic_Load_uint( &the_thread->Wait.flags, ATOMIC_ORDER_RELAXED );
1333#else
1334  return the_thread->Wait.flags;
1335#endif
1336}
1337
1338/**
1339 * @brief Tries to change the thread wait flags inside a critical section
1340 * (interrupts disabled).
1341 *
1342 * In case the wait flags are equal to the expected wait flags, then the wait
1343 * flags are set to the desired wait flags.
1344 *
1345 * @param[in] the_thread The thread.
1346 * @param[in] expected_flags The expected wait flags.
1347 * @param[in] desired_flags The desired wait flags.
1348 *
1349 * @retval true The wait flags were equal to the expected wait flags.
1350 * @retval false Otherwise.
1351 */
1352RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change_critical(
1353  Thread_Control    *the_thread,
1354  Thread_Wait_flags  expected_flags,
1355  Thread_Wait_flags  desired_flags
1356)
1357{
1358#if defined(RTEMS_SMP)
1359  return _Atomic_Compare_exchange_uint(
1360    &the_thread->Wait.flags,
1361    &expected_flags,
1362    desired_flags,
1363    ATOMIC_ORDER_RELAXED,
1364    ATOMIC_ORDER_RELAXED
1365  );
1366#else
1367  bool success = the_thread->Wait.flags == expected_flags;
1368
1369  if ( success ) {
1370    the_thread->Wait.flags = desired_flags;
1371  }
1372
1373  return success;
1374#endif
1375}
1376
1377/**
1378 * @brief Tries to change the thread wait flags.
1379 *
1380 * @see _Thread_Wait_flags_try_change_critical().
1381 */
1382RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change(
1383  Thread_Control    *the_thread,
1384  Thread_Wait_flags  expected_flags,
1385  Thread_Wait_flags  desired_flags
1386)
1387{
1388  bool success;
1389#if !defined(RTEMS_SMP)
1390  ISR_Level level;
1391
1392  _ISR_Disable_without_giant( level );
1393#endif
1394
1395  success = _Thread_Wait_flags_try_change_critical(
1396    the_thread,
1397    expected_flags,
1398    desired_flags
1399  );
1400
1401#if !defined(RTEMS_SMP)
1402  _ISR_Enable_without_giant( level );
1403#endif
1404
1405  return success;
1406}
1407
1408/**
1409 * @brief Sets the thread queue.
1410 *
1411 * The caller must be the owner of the thread lock.
1412 *
1413 * @param[in] the_thread The thread.
1414 * @param[in] new_queue The new queue.
1415 *
1416 * @see _Thread_Lock_set().
1417 */
1418RTEMS_INLINE_ROUTINE void _Thread_Wait_set_queue(
1419  Thread_Control     *the_thread,
1420  Thread_queue_Queue *new_queue
1421)
1422{
1423  the_thread->Wait.queue = new_queue;
1424}
1425
1426/**
1427 * @brief Sets the thread queue operations.
1428 *
1429 * The caller must be the owner of the thread lock.
1430 *
1431 * @param[in] the_thread The thread.
1432 * @param[in] new_operations The new queue operations.
1433 *
1434 * @see _Thread_Lock_set() and _Thread_Wait_restore_default_operations().
1435 */
1436RTEMS_INLINE_ROUTINE void _Thread_Wait_set_operations(
1437  Thread_Control                *the_thread,
1438  const Thread_queue_Operations *new_operations
1439)
1440{
1441  the_thread->Wait.operations = new_operations;
1442}
1443
1444/**
1445 * @brief Restores the default thread queue operations.
1446 *
1447 * The caller must be the owner of the thread lock.
1448 *
1449 * @param[in] the_thread The thread.
1450 *
1451 * @see _Thread_Wait_set_operations().
1452 */
1453RTEMS_INLINE_ROUTINE void _Thread_Wait_restore_default_operations(
1454  Thread_Control *the_thread
1455)
1456{
1457  the_thread->Wait.operations = &_Thread_queue_Operations_default;
1458}
1459
1460/**
1461 * @brief Sets the thread wait timeout code.
1462 *
1463 * @param[in] the_thread The thread.
1464 * @param[in] timeout_code The new thread wait timeout code.
1465 */
1466RTEMS_INLINE_ROUTINE void _Thread_Wait_set_timeout_code(
1467  Thread_Control *the_thread,
1468  uint32_t        timeout_code
1469)
1470{
1471  the_thread->Wait.timeout_code = timeout_code;
1472}
1473
1474/**
1475 * @brief General purpose thread wait timeout.
1476 *
1477 * @param[in] id Unused.
1478 * @param[in] arg The thread.
1479 */
1480void _Thread_Timeout( Objects_Id id, void *arg );
1481
1482RTEMS_INLINE_ROUTINE void _Thread_Debug_set_real_processor(
1483  Thread_Control  *the_thread,
1484  Per_CPU_Control *cpu
1485)
1486{
1487#if defined(RTEMS_SMP) && defined(RTEMS_DEBUG)
1488  the_thread->Scheduler.debug_real_cpu = cpu;
1489#else
1490  (void) the_thread;
1491  (void) cpu;
1492#endif
1493}
1494
1495/** @}*/
1496
1497#ifdef __cplusplus
1498}
1499#endif
1500
1501#if defined(RTEMS_MULTIPROCESSING)
1502#include <rtems/score/threadmp.h>
1503#endif
1504
1505#endif
1506/* end of include file */
Note: See TracBrowser for help on using the repository browser.