summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/threadinitialize.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/src/threadinitialize.c')
-rw-r--r--cpukit/score/src/threadinitialize.c229
1 files changed, 141 insertions, 88 deletions
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 9c1b809c3a..e1a6c7de93 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -11,9 +13,26 @@
* COPYRIGHT (c) 1989-2014.
* 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.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
@@ -96,6 +115,116 @@ void _Thread_Free(
_Objects_Free( &information->Objects, &the_thread->Object );
}
+static void _Thread_Initialize_scheduler_and_wait_nodes(
+ Thread_Control *the_thread,
+ const Thread_Configuration *config
+)
+{
+ Scheduler_Node *home_scheduler_node;
+#if defined(RTEMS_SMP)
+ Scheduler_Node *scheduler_node;
+ const Scheduler_Control *scheduler;
+ size_t scheduler_index;
+#endif
+
+#if defined(RTEMS_SMP)
+ home_scheduler_node = NULL;
+ scheduler_node = the_thread->Scheduler.nodes;
+ scheduler = &_Scheduler_Table[ 0 ];
+ scheduler_index = 0;
+
+ /*
+ * In SMP configurations, the thread has exactly one scheduler node for each
+ * configured scheduler. Initialize the scheduler nodes of each scheduler.
+ * The application configuration ensures that we have at least one scheduler
+ * configured.
+ */
+
+ _Assert ( _Scheduler_Count >= 1 );
+
+ do {
+ Priority_Control priority;
+
+ if ( scheduler == config->scheduler ) {
+ priority = config->priority;
+ home_scheduler_node = scheduler_node;
+ } else {
+ /*
+ * Use the idle thread priority for the non-home scheduler instances by
+ * default.
+ */
+ priority = _Scheduler_Map_priority(
+ scheduler,
+ scheduler->maximum_priority
+ );
+ }
+
+ _Scheduler_Node_initialize(
+ scheduler,
+ scheduler_node,
+ the_thread,
+ priority
+ );
+
+ /*
+ * Since the size of a scheduler node depends on the application
+ * configuration, the _Scheduler_Node_size constant is used to get the next
+ * scheduler node. Using sizeof( Scheduler_Node ) would be wrong.
+ */
+ scheduler_node = (Scheduler_Node *)
+ ( (uintptr_t) scheduler_node + _Scheduler_Node_size );
+ ++scheduler;
+ ++scheduler_index;
+ } while ( scheduler_index < _Scheduler_Count );
+
+ /*
+ * The thread is initialized to use exactly one scheduler node which is
+ * provided by its home scheduler.
+ */
+ _Assert( home_scheduler_node != NULL );
+ _Chain_Initialize_one(
+ &the_thread->Scheduler.Wait_nodes,
+ &home_scheduler_node->Thread.Wait_node
+ );
+ _Chain_Initialize_one(
+ &the_thread->Scheduler.Scheduler_nodes,
+ &home_scheduler_node->Thread.Scheduler_node.Chain
+ );
+#else
+ /*
+ * In uniprocessor configurations, the thread has exactly one scheduler node.
+ */
+ home_scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
+ _Scheduler_Node_initialize(
+ config->scheduler,
+ home_scheduler_node,
+ the_thread,
+ config->priority
+ );
+#endif
+
+ /*
+ * The current priority of the thread is initialized to exactly the real
+ * priority of the thread. During the lifetime of the thread, it may gain
+ * more priority nodes, for example through locking protocols such as
+ * priority inheritance or priority ceiling.
+ */
+ _Priority_Node_initialize( &the_thread->Real_priority, config->priority );
+ _Priority_Initialize_one(
+ &home_scheduler_node->Wait.Priority,
+ &the_thread->Real_priority
+ );
+
+#if defined(RTEMS_SMP)
+ RTEMS_STATIC_ASSERT( THREAD_SCHEDULER_BLOCKED == 0, Scheduler_state );
+ the_thread->Scheduler.home_scheduler = config->scheduler;
+ _ISR_lock_Initialize( &the_thread->Scheduler.Lock, "Thread Scheduler" );
+ _ISR_lock_Initialize( &the_thread->Wait.Lock.Default, "Thread Wait Default" );
+ _Thread_queue_Gate_open( &the_thread->Wait.Lock.Tranquilizer );
+ _RBTree_Initialize_node( &the_thread->Wait.Link.Registry_node );
+#endif
+}
+
static bool _Thread_Try_initialize(
Thread_Information *information,
Thread_Control *the_thread,
@@ -107,12 +236,6 @@ static bool _Thread_Try_initialize(
char *stack_begin;
char *stack_end;
uintptr_t stack_align;
- Scheduler_Node *scheduler_node;
-#if defined(RTEMS_SMP)
- Scheduler_Node *scheduler_node_for_index;
- const Scheduler_Control *scheduler_for_index;
- size_t scheduler_index;
-#endif
Per_CPU_Control *cpu = _Per_CPU_Get_by_index( 0 );
memset(
@@ -147,12 +270,8 @@ static bool _Thread_Try_initialize(
/* Allocate thread-local storage (TLS) area in stack area */
if ( tls_size > 0 ) {
- uintptr_t tls_align;
-
stack_end -= tls_size;
- tls_align = (uintptr_t) _TLS_Alignment;
- the_thread->Start.tls_area = (void *)
- ( ( (uintptr_t) stack_end + tls_align - 1 ) & ~( tls_align - 1 ) );
+ the_thread->Start.tls_area = stack_end;
}
_Stack_Initialize(
@@ -173,87 +292,21 @@ static bool _Thread_Try_initialize(
* General initialization
*/
- the_thread->is_fp = config->is_fp;
- the_thread->cpu_time_budget = config->cpu_time_budget;
- the_thread->Start.isr_level = config->isr_level;
- the_thread->Start.is_preemptible = config->is_preemptible;
- the_thread->Start.budget_algorithm = config->budget_algorithm;
- the_thread->Start.budget_callout = config->budget_callout;
- the_thread->Start.stack_free = config->stack_free;
+ the_thread->is_fp = config->is_fp;
+ the_thread->Start.isr_level = config->isr_level;
+ the_thread->Start.is_preemptible = config->is_preemptible;
+ the_thread->Start.cpu_budget_operations = config->cpu_budget_operations;
+ the_thread->Start.stack_free = config->stack_free;
+ the_thread->Join_queue.Queue.owner = the_thread;
_Thread_Timer_initialize( &the_thread->Timer, cpu );
+ _Thread_Initialize_scheduler_and_wait_nodes( the_thread, config );
#if defined(RTEMS_SMP)
- scheduler_node = NULL;
- scheduler_node_for_index = the_thread->Scheduler.nodes;
- scheduler_for_index = &_Scheduler_Table[ 0 ];
- scheduler_index = 0;
-
- while ( scheduler_index < _Scheduler_Count ) {
- Priority_Control priority_for_index;
-
- if ( scheduler_for_index == config->scheduler ) {
- priority_for_index = config->priority;
- scheduler_node = scheduler_node_for_index;
- } else {
- /*
- * Use the idle thread priority for the non-home scheduler instances by
- * default.
- */
- priority_for_index = _Scheduler_Map_priority(
- scheduler_for_index,
- scheduler_for_index->maximum_priority
- );
- }
-
- _Scheduler_Node_initialize(
- scheduler_for_index,
- scheduler_node_for_index,
- the_thread,
- priority_for_index
- );
- scheduler_node_for_index = (Scheduler_Node *)
- ( (uintptr_t) scheduler_node_for_index + _Scheduler_Node_size );
- ++scheduler_for_index;
- ++scheduler_index;
- }
-
- _Assert( scheduler_node != NULL );
- _Chain_Initialize_one(
- &the_thread->Scheduler.Wait_nodes,
- &scheduler_node->Thread.Wait_node
- );
- _Chain_Initialize_one(
- &the_thread->Scheduler.Scheduler_nodes,
- &scheduler_node->Thread.Scheduler_node.Chain
- );
-#else
- scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
- _Scheduler_Node_initialize(
- config->scheduler,
- scheduler_node,
- the_thread,
- config->priority
- );
-#endif
-
- _Priority_Node_initialize( &the_thread->Real_priority, config->priority );
- _Priority_Initialize_one(
- &scheduler_node->Wait.Priority,
- &the_thread->Real_priority
- );
-
-#if defined(RTEMS_SMP)
- RTEMS_STATIC_ASSERT( THREAD_SCHEDULER_BLOCKED == 0, Scheduler_state );
- the_thread->Scheduler.home_scheduler = config->scheduler;
- _ISR_lock_Initialize( &the_thread->Scheduler.Lock, "Thread Scheduler" );
_Processor_mask_Assign(
&the_thread->Scheduler.Affinity,
_SMP_Get_online_processors()
);
- _ISR_lock_Initialize( &the_thread->Wait.Lock.Default, "Thread Wait Default" );
- _Thread_queue_Gate_open( &the_thread->Wait.Lock.Tranquilizer );
- _RBTree_Initialize_node( &the_thread->Wait.Link.Registry_node );
_SMP_lock_Stats_initialize( &the_thread->Potpourri_stats, "Thread Potpourri" );
_SMP_lock_Stats_initialize( &the_thread->Join_queue.Lock_stats, "Thread State" );
#endif
@@ -265,7 +318,7 @@ static bool _Thread_Try_initialize(
the_thread->Wait.operations = &_Thread_queue_Operations_default;
the_thread->Start.initial_priority = config->priority;
- RTEMS_STATIC_ASSERT( THREAD_WAIT_FLAGS_INITIAL == 0, Wait_flags );
+ RTEMS_STATIC_ASSERT( THREAD_WAIT_STATE_READY == 0, Wait_flags );
/* POSIX Keys */
_RBTree_Initialize_empty( &the_thread->Keys.Key_value_pairs );