summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score/threadimpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/include/rtems/score/threadimpl.h')
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h691
1 files changed, 691 insertions, 0 deletions
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
new file mode 100644
index 0000000000..205c704508
--- /dev/null
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -0,0 +1,691 @@
+/**
+ * @file
+ *
+ * @brief Inlined Routines from the Thread Handler
+ *
+ * This file contains the macro implementation of the inlined
+ * routines from the Thread handler.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_THREADIMPL_H
+#define _RTEMS_SCORE_THREADIMPL_H
+
+#include <rtems/score/thread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup ScoreThread
+ */
+/**@{**/
+
+/**
+ * The following structure contains the information necessary to manage
+ * a thread which it is waiting for a resource.
+ */
+#define THREAD_STATUS_PROXY_BLOCKING 0x1111111
+
+/**
+ * Self for the GNU Ada Run-Time
+ */
+SCORE_EXTERN void *rtems_ada_self;
+
+/**
+ * The following defines the information control block used to
+ * manage this class of objects.
+ */
+SCORE_EXTERN Objects_Information _Thread_Internal_information;
+
+/**
+ * The following context area contains the context of the "thread"
+ * which invoked the start multitasking routine. This context is
+ * restored as the last action of the stop multitasking routine. Thus
+ * control of the processor can be returned to the environment
+ * which initiated the system.
+ */
+SCORE_EXTERN Context_Control _Thread_BSP_context;
+
+/**
+ * The following holds how many user extensions are in the system. This
+ * is used to determine how many user extension data areas to allocate
+ * per thread.
+ */
+SCORE_EXTERN uint32_t _Thread_Maximum_extensions;
+
+/**
+ * The following is used to manage the length of a timeslice quantum.
+ */
+SCORE_EXTERN uint32_t _Thread_Ticks_per_timeslice;
+
+/**
+ * The following points to the thread whose floating point
+ * context is currently loaded.
+ */
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+SCORE_EXTERN Thread_Control *_Thread_Allocated_fp;
+#endif
+
+#if !defined(__DYNAMIC_REENT__)
+/**
+ * The C library re-enter-rant global pointer. Some C library implementations
+ * such as newlib have a single global pointer that changed during a context
+ * switch. The pointer points to that global pointer. The Thread control block
+ * holds a pointer to the task specific data.
+ */
+SCORE_EXTERN struct _reent **_Thread_libc_reent;
+#endif
+
+/**
+ * @brief Initialize thread handler.
+ *
+ * This routine performs the initialization necessary for this handler.
+ */
+void _Thread_Handler_initialization(void);
+
+/**
+ * @brief Create idle thread.
+ *
+ * This routine creates the idle thread.
+ *
+ * @warning No thread should be created before this one.
+ */
+void _Thread_Create_idle(void);
+
+/**
+ * @brief Start thread multitasking.
+ *
+ * This routine initiates multitasking. It is invoked only as
+ * part of initialization and its invocation is the last act of
+ * the non-multitasking part of the system initialization.
+ *
+ *
+ * - INTERRUPT LATENCY:
+ * + ready chain
+ * + select heir
+ */
+void _Thread_Start_multitasking( void );
+
+/**
+ * @brief Allocate the requested stack space for the thread.
+ *
+ * Allocate the requested stack space for the thread.
+ * Set the Start.stack field to the address of the stack.
+ *
+ * @param[in] the_thread is the thread where the stack space is requested
+ *
+ * @retval actual size allocated after any adjustment
+ * @retval zero if the allocation failed
+ */
+size_t _Thread_Stack_Allocate(
+ Thread_Control *the_thread,
+ size_t stack_size
+);
+
+/**
+ * @brief Deallocate thread stack.
+ *
+ * Deallocate the Thread's stack.
+ */
+void _Thread_Stack_Free(
+ Thread_Control *the_thread
+);
+
+/**
+ * @brief Initialize thread.
+ *
+ * This routine initializes the specified the thread. It allocates
+ * all memory associated with this thread. It completes by adding
+ * the thread to the local object table so operations on this
+ * thread id are allowed.
+ *
+ * @note If stack_area is NULL, it is allocated from the workspace.
+ *
+ * @note If the stack is allocated from the workspace, then it is
+ * guaranteed to be of at least minimum size.
+ */
+bool _Thread_Initialize(
+ Objects_Information *information,
+ Thread_Control *the_thread,
+ void *stack_area,
+ size_t stack_size,
+ bool is_fp,
+ Priority_Control priority,
+ bool is_preemptible,
+ Thread_CPU_budget_algorithms budget_algorithm,
+ Thread_CPU_budget_algorithm_callout budget_callout,
+ uint32_t isr_level,
+ Objects_Name name
+);
+
+/**
+ * @brief Initializes thread and executes it.
+ *
+ * This routine initializes the executable information for a thread
+ * and makes it ready to execute. After this routine executes, the
+ * thread competes with all other threads for CPU time.
+ *
+ * @param the_thread is the thread to be initialized
+ * @param the_prototype
+ * @param entry_point
+ * @param pointer_argument
+ * @param numeric_argument
+ * @param[in,out] processor The processor if used to start an idle thread
+ * during system initialization. Must be set to @c NULL to start a normal
+ * thread.
+ */
+bool _Thread_Start(
+ Thread_Control *the_thread,
+ Thread_Start_types the_prototype,
+ void *entry_point,
+ void *pointer_argument,
+ Thread_Entry_numeric_type numeric_argument,
+ Per_CPU_Control *processor
+);
+
+/**
+ * @brief Restarts the specified thread.
+ *
+ * This support routine restarts the specified task in a way that the
+ * next time this thread executes, it will begin execution at its
+ * original starting point.
+ *
+ * TODO: multiple task arg profiles
+ */
+bool _Thread_Restart(
+ Thread_Control *the_thread,
+ void *pointer_argument,
+ Thread_Entry_numeric_type numeric_argument
+);
+
+/**
+ * @brief Resets a thread to its initial state.
+ *
+ * This routine resets a thread to its initial state but does
+ * not restart it. Some APIs do this in separate
+ * operations and this division helps support this.
+ *
+ * @param[in] the_thread is the thread to resets
+ * @param[in] pointer_argument
+ * @param[in] numeric_argument
+ */
+void _Thread_Reset(
+ Thread_Control *the_thread,
+ void *pointer_argument,
+ Thread_Entry_numeric_type numeric_argument
+);
+
+/**
+ * @brief Frees all memory associated with the specified thread.
+ *
+ * This routine frees all memory associated with the specified
+ * thread and removes it from the local object table so no further
+ * operations on this thread are allowed.
+ */
+void _Thread_Close(
+ Objects_Information *information,
+ Thread_Control *the_thread
+);
+
+/**
+ * @brief Removes any set states for @a the_thread.
+ *
+ * This routine removes any set states for @a the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ *
+ * - INTERRUPT LATENCY:
+ * + ready chain
+ * + select heir
+ */
+void _Thread_Ready(
+ Thread_Control *the_thread
+);
+
+/**
+ * @brief Clears the indicated STATES for @a the_thread.
+ *
+ * This routine clears the indicated STATES for @a the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ *
+ * - INTERRUPT LATENCY:
+ * + priority map
+ * + select heir
+ */
+void _Thread_Clear_state(
+ Thread_Control *the_thread,
+ States_Control state
+);
+
+/**
+ * @brief Sets the indicated @a state for @a the_thread.
+ *
+ * This routine sets the indicated @a state for @a the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ *
+ * @param[in] the_thread is the thread to set the state for.
+ * @param[in] state is the state to set the_thread to.
+ *
+ * - INTERRUPT LATENCY:
+ * + ready chain
+ * + select map
+ */
+void _Thread_Set_state(
+ Thread_Control *the_thread,
+ States_Control state
+);
+
+/**
+ * @brief Sets the transient state for a thread.
+ *
+ * This routine sets the Transient state for @a the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ *
+ * @param[in] the_thread is the thread to preform the action upon.
+ *
+ * - INTERRUPT LATENCY:
+ * + single case
+ */
+void _Thread_Set_transient(
+ Thread_Control *the_thread
+);
+
+/**
+ * @brief Initializes enviroment for a thread.
+ *
+ * This routine initializes the context of @a the_thread to its
+ * appropriate starting state.
+ *
+ * @param[in] the_thread is the pointer to the thread control block.
+ */
+void _Thread_Load_environment(
+ Thread_Control *the_thread
+);
+
+/**
+ * @brief Wrapper function for all threads.
+ *
+ * This routine is the wrapper function for all threads. It is
+ * the starting point for all threads. The user provided thread
+ * entry point is invoked by this routine. Operations
+ * which must be performed immediately before and after the user's
+ * thread executes are found here.
+ *
+ * @note On entry, it is assumed all interrupts are blocked and that this
+ * routine needs to set the initial isr level. This may or may not
+ * actually be needed by the context switch routine and as a result
+ * interrupts may already be at there proper level. Either way,
+ * setting the initial isr level properly here is safe.
+ */
+void _Thread_Handler( void );
+
+/**
+ * @brief Ended the delay of a thread.
+ *
+ * This routine is invoked when a thread must be unblocked at the
+ * end of a time based delay (i.e. wake after or wake when).
+ * It is called by the watchdog handler.
+ *
+ * @param[in] id is the thread id
+ */
+void _Thread_Delay_ended(
+ Objects_Id id,
+ void *ignored
+);
+
+/**
+ * @brief Change the priority of a thread.
+ *
+ * This routine changes the current priority of @a the_thread to
+ * @a new_priority. It performs any necessary scheduling operations
+ * including the selection of a new heir thread.
+ *
+ * @param[in] the_thread is the thread to change
+ * @param[in] new_priority is the priority to set @a the_thread to
+ * @param[in] prepend_it is a switch to prepend the thread
+ */
+void _Thread_Change_priority (
+ Thread_Control *the_thread,
+ Priority_Control new_priority,
+ bool prepend_it
+);
+
+/**
+ * @brief Set thread priority.
+ *
+ * This routine updates the priority related fields in the_thread
+ * control block to indicate the current priority is now new_priority.
+ */
+void _Thread_Set_priority(
+ Thread_Control *the_thread,
+ Priority_Control new_priority
+);
+
+/**
+ * This routine updates the related suspend fields in the_thread
+ * control block to indicate the current nested level.
+ */
+#define _Thread_Suspend( _the_thread ) \
+ _Thread_Set_state( _the_thread, STATES_SUSPENDED )
+
+/**
+ * This routine updates the related suspend fields in the_thread
+ * control block to indicate the current nested level. A force
+ * parameter of true will force a resume and clear the suspend count.
+ */
+#define _Thread_Resume( _the_thread ) \
+ _Thread_Clear_state( _the_thread, STATES_SUSPENDED )
+
+/**
+ * @brief Maps thread Id to a TCB pointer.
+ *
+ * This function maps thread IDs to thread control
+ * blocks. If ID corresponds to a local thread, then it
+ * returns the_thread control pointer which maps to ID
+ * and @a location is set to OBJECTS_LOCAL. If the thread ID is
+ * global and resides on a remote node, then location is set
+ * to OBJECTS_REMOTE, and the_thread is undefined.
+ * Otherwise, location is set to OBJECTS_ERROR and
+ * the_thread is undefined.
+ *
+ * @param[in] id is the id of the thread.
+ * @param[in] location is the location of the block.
+ *
+ * @note The performance of many RTEMS services depends upon
+ * the quick execution of the "good object" path in this
+ * routine. If there is a possibility of saving a few
+ * cycles off the execution time, this routine is worth
+ * further optimization attention.
+ */
+Thread_Control *_Thread_Get (
+ Objects_Id id,
+ Objects_Locations *location
+);
+
+/**
+ * @brief Cancel a blocking operation due to ISR.
+ *
+ * This method is used to cancel a blocking operation that was
+ * satisfied from an ISR while the thread executing was in the
+ * process of blocking.
+ *
+ * This method will restore the previous ISR disable level during the cancel
+ * operation. Thus it is an implicit _ISR_Enable().
+ *
+ * @param[in] sync_state is the synchronization state
+ * @param[in] the_thread is the thread whose blocking is canceled
+ * @param[in] level is the previous ISR disable level
+ *
+ * @note This is a rare routine in RTEMS. It is called with
+ * interrupts disabled and only when an ISR completed
+ * a blocking condition in process.
+ */
+void _Thread_blocking_operation_Cancel(
+ Thread_blocking_operation_States sync_state,
+ Thread_Control *the_thread,
+ ISR_Level level
+);
+
+/**
+ * This routine halts multitasking and returns control to
+ * the "thread" (i.e. the BSP) which initially invoked the
+ * routine which initialized the system.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Stop_multitasking( void )
+{
+#if defined(_CPU_Stop_multitasking)
+ _CPU_Stop_multitasking( &_Thread_BSP_context );
+#else
+ /*
+ * This may look a bit of an odd but _Context_Restart_self is just
+ * a very careful restore of a specific context which ensures that
+ * if we were running within the same context, it would work.
+ *
+ * And we will not return to this thread, so there is no point of
+ * saving the context.
+ */
+ _Context_Restart_self( &_Thread_BSP_context );
+#endif
+
+ /***************************************************************
+ ***************************************************************
+ * SYSTEM SHUTS DOWN!!! WE DO NOT RETURN TO THIS POINT!!! *
+ ***************************************************************
+ ***************************************************************
+ */
+}
+
+/**
+ * This function returns true if the_thread is the currently executing
+ * thread, and false otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE bool _Thread_Is_executing (
+ const Thread_Control *the_thread
+)
+{
+ return ( the_thread == _Thread_Executing );
+}
+
+/**
+ * This function returns true if the_thread is the heir
+ * thread, and false otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE bool _Thread_Is_heir (
+ const Thread_Control *the_thread
+)
+{
+ return ( the_thread == _Thread_Heir );
+}
+
+/**
+ * This function returns true if the currently executing thread
+ * is also the heir thread, and false otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE bool _Thread_Is_executing_also_the_heir( void )
+{
+ return ( _Thread_Executing == _Thread_Heir );
+}
+
+/**
+ * This routine clears any blocking state for the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Unblock (
+ Thread_Control *the_thread
+)
+{
+ _Thread_Clear_state( the_thread, STATES_BLOCKED );
+}
+
+/**
+ * This routine resets the current context of the calling thread
+ * to that of its initial state.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Restart_self( void )
+{
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ if ( _Thread_Executing->fp_context != NULL )
+ _Context_Restore_fp( &_Thread_Executing->fp_context );
+#endif
+
+ _CPU_Context_Restart_self( &_Thread_Executing->Registers );
+}
+
+/**
+ * This function returns true if the floating point context of
+ * the_thread is currently loaded in the floating point unit, and
+ * false otherwise.
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+RTEMS_INLINE_ROUTINE bool _Thread_Is_allocated_fp (
+ const Thread_Control *the_thread
+)
+{
+ return ( the_thread == _Thread_Allocated_fp );
+}
+#endif
+
+/**
+ * This routine is invoked when the currently loaded floating
+ * point context is now longer associated with an active thread.
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+RTEMS_INLINE_ROUTINE void _Thread_Deallocate_fp( void )
+{
+ _Thread_Allocated_fp = NULL;
+}
+#endif
+
+/**
+ * This function returns true if dispatching is disabled, and false
+ * otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE bool _Thread_Is_context_switch_necessary( void )
+{
+ return ( _Thread_Dispatch_necessary );
+}
+
+/**
+ * This function returns true if the_thread is NULL and false otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE bool _Thread_Is_null (
+ const Thread_Control *the_thread
+)
+{
+ return ( the_thread == NULL );
+}
+
+/**
+ * @brief Is proxy blocking.
+ *
+ * status which indicates that a proxy is blocking, and false otherwise.
+ */
+RTEMS_INLINE_ROUTINE bool _Thread_Is_proxy_blocking (
+ uint32_t code
+)
+{
+ return (code == THREAD_STATUS_PROXY_BLOCKING);
+}
+
+/**
+ * This routine allocates an internal thread.
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Internal_allocate( void )
+{
+ return (Thread_Control *) _Objects_Allocate( &_Thread_Internal_information );
+}
+
+/**
+ * This routine frees an internal thread.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Internal_free (
+ Thread_Control *the_task
+)
+{
+ _Objects_Free( &_Thread_Internal_information, &the_task->Object );
+}
+
+RTEMS_INLINE_ROUTINE void _Thread_Set_global_exit_status(
+ uint32_t exit_status
+)
+{
+ Thread_Control *idle = (Thread_Control *)
+ _Thread_Internal_information.local_table[ 1 ];
+
+ idle->Wait.return_code = exit_status;
+}
+
+RTEMS_INLINE_ROUTINE uint32_t _Thread_Get_global_exit_status( void )
+{
+ const Thread_Control *idle = (const Thread_Control *)
+ _Thread_Internal_information.local_table[ 1 ];
+
+ return idle->Wait.return_code;
+}
+
+/**
+ * @brief Issues a thread dispatch if necessary.
+ *
+ * @param[in] executing The executing thread.
+ * @param[in] needs_asr_dispatching Indicates whether or not the API
+ * level signals are pending and a dispatch is necessary.
+ */
+RTEMS_INLINE_ROUTINE void _Thread_Dispatch_if_necessary(
+ Thread_Control *executing,
+ bool needs_asr_dispatching
+)
+{
+ if ( _Thread_Dispatch_is_enabled() ) {
+ bool dispatch_necessary = needs_asr_dispatching;
+
+ if ( !_Thread_Is_heir( executing ) && executing->is_preemptible ) {
+ dispatch_necessary = true;
+ _Thread_Dispatch_necessary = dispatch_necessary;
+ }
+
+ if ( dispatch_necessary ) {
+ _Thread_Dispatch();
+ }
+ }
+}
+
+#if !defined(__DYNAMIC_REENT__)
+/**
+ * This routine returns the C library re-enterant pointer.
+ */
+
+RTEMS_INLINE_ROUTINE struct _reent **_Thread_Get_libc_reent( void )
+{
+ return _Thread_libc_reent;
+}
+
+/**
+ * This routine set the C library re-enterant pointer.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Set_libc_reent (
+ struct _reent **libc_reent
+)
+{
+ _Thread_libc_reent = libc_reent;
+}
+#endif
+
+/** @}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/threadmp.h>
+#endif
+
+#endif
+/* end of include file */