summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/threadrestart.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/src/threadrestart.c')
-rw-r--r--cpukit/score/src/threadrestart.c210
1 files changed, 106 insertions, 104 deletions
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 79a154e3d3..72326682ca 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -12,11 +14,28 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
- * Copyright (c) 2014, 2021 embedded brains GmbH.
+ * Copyright (C) 2014, 2022 embedded brains GmbH & Co. KG
+ *
+ * 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.
*
- * 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.
+ * 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
@@ -27,16 +46,16 @@
#include <rtems/score/apimutex.h>
#include <rtems/score/assert.h>
#include <rtems/score/chainimpl.h>
-#include <rtems/score/freechainimpl.h>
#include <rtems/score/isrlock.h>
#include <rtems/score/schedulerimpl.h>
-#include <rtems/score/stackimpl.h>
#include <rtems/score/sysstate.h>
#include <rtems/score/threadqimpl.h>
#include <rtems/score/userextimpl.h>
#include <rtems/score/watchdogimpl.h>
-#define THREAD_JOIN_TQ_OPERATIONS &_Thread_queue_Operations_priority
+#include <pthread.h>
+
+#define THREAD_JOIN_TQ_OPERATIONS &_Thread_queue_Operations_priority_inherit
static void _Thread_Life_action_handler(
Thread_Control *executing,
@@ -44,41 +63,13 @@ static void _Thread_Life_action_handler(
ISR_lock_Context *lock_context
);
-typedef struct {
- Chain_Control Chain;
- ISR_lock_Control Lock;
-} Thread_Zombie_control;
-
-static Thread_Zombie_control _Thread_Zombies = {
- .Chain = CHAIN_INITIALIZER_EMPTY( _Thread_Zombies.Chain ),
- .Lock = ISR_LOCK_INITIALIZER( "thread zombies" )
+Thread_Zombie_registry _Thread_Zombies = {
+#if defined(RTEMS_SMP)
+ .Lock = ISR_LOCK_INITIALIZER( "Thread Zombies" ),
+#endif
+ .Chain = CHAIN_INITIALIZER_EMPTY( _Thread_Zombies.Chain )
};
-static void _Thread_Raise_real_priority(
- Thread_Control *the_thread,
- Priority_Control priority
-)
-{
- Thread_queue_Context queue_context;
-
- _Thread_queue_Context_initialize( &queue_context );
- _Thread_queue_Context_clear_priority_updates( &queue_context );
- _Thread_Wait_acquire( the_thread, &queue_context );
-
- if ( priority < the_thread->Real_priority.priority ) {
- _Thread_Priority_change(
- the_thread,
- &the_thread->Real_priority,
- priority,
- false,
- &queue_context
- );
- }
-
- _Thread_Wait_release( the_thread, &queue_context );
- _Thread_Priority_update( &queue_context );
-}
-
typedef struct {
Thread_queue_Context Base;
void *exit_value;
@@ -92,6 +83,7 @@ static Thread_Control *_Thread_Join_flush_filter(
{
Thread_Join_context *join_context;
+ (void) queue;
join_context = (Thread_Join_context *) queue_context;
the_thread->Wait.return_argument = join_context->exit_value;
@@ -115,10 +107,10 @@ static void _Thread_Wake_up_joining_threads( Thread_Control *the_thread )
);
}
-static void _Thread_Add_to_zombie_chain( Thread_Control *the_thread )
+static void _Thread_Add_to_zombie_registry( Thread_Control *the_thread )
{
- ISR_lock_Context lock_context;
- Thread_Zombie_control *zombies;
+ ISR_lock_Context lock_context;
+ Thread_Zombie_registry *zombies;
zombies = &_Thread_Zombies;
_ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context );
@@ -140,20 +132,19 @@ static void _Thread_Make_zombie( Thread_Control *the_thread )
_Objects_Close( &information->Objects, &the_thread->Object );
_Thread_Set_state( the_thread, STATES_ZOMBIE );
- _Thread_queue_Extract_with_proxy( the_thread );
- _Thread_Timer_remove( the_thread );
+ _Thread_Timer_remove_and_continue( the_thread, STATUS_INTERNAL_ERROR );
/*
* Add the thread to the thread zombie chain before we wake up joining
* threads, so that they are able to clean up the thread immediately. This
* matters for SMP configurations.
*/
- _Thread_Add_to_zombie_chain( the_thread );
+ _Thread_Add_to_zombie_registry( the_thread );
_Thread_Wake_up_joining_threads( the_thread );
}
-static void _Thread_Wait_for_execution_stop( Thread_Control *the_thread )
+static void _Thread_Wait_for_execution_stop( const Thread_Control *the_thread )
{
#if defined(RTEMS_SMP)
/*
@@ -169,16 +160,21 @@ static void _Thread_Wait_for_execution_stop( Thread_Control *the_thread )
#endif
}
+static Thread_Control *_Thread_Get_zombie( Thread_Zombie_registry *zombies )
+{
+ return (Thread_Control *) _Chain_Get_unprotected( &zombies->Chain );
+}
+
void _Thread_Kill_zombies( void )
{
- ISR_lock_Context lock_context;
- Thread_Zombie_control *zombies = &_Thread_Zombies;
- Thread_Control *the_thread;
+ ISR_lock_Context lock_context;
+ Thread_Zombie_registry *zombies;
+ Thread_Control *the_thread;
+ zombies = &_Thread_Zombies;
_ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context );
- the_thread = (Thread_Control *) _Chain_Get_unprotected( &zombies->Chain );
- while ( the_thread != NULL ) {
+ while ( ( the_thread = _Thread_Get_zombie( zombies ) ) != NULL ) {
Thread_Information *information;
_ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context );
@@ -188,8 +184,6 @@ void _Thread_Kill_zombies( void )
_Thread_Free( information, the_thread );
_ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context );
-
- the_thread = (Thread_Control *) _Chain_Get_unprotected( &zombies->Chain );
}
_ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context );
@@ -217,10 +211,6 @@ static Thread_Life_state _Thread_Change_life_locked(
_Thread_Is_life_change_allowed( state )
&& _Thread_Is_life_changing( state )
) {
- the_thread->is_preemptible = the_thread->Start.is_preemptible;
- the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
- the_thread->budget_callout = the_thread->Start.budget_callout;
-
_Thread_Add_post_switch_action(
the_thread,
&the_thread->Life.Action,
@@ -362,7 +352,7 @@ static void _Thread_Remove_life_change_request( Thread_Control *the_thread )
* Do not remove states used for thread queues to avoid race conditions on
* SMP configurations. We could interrupt an extract operation on another
* processor disregarding the thread wait flags. Rely on
- * _Thread_queue_Extract_with_proxy() for removal of these states.
+ * _Thread_Continue() for removal of these states.
*/
_Thread_Clear_state_locked(
the_thread,
@@ -374,18 +364,37 @@ static void _Thread_Remove_life_change_request( Thread_Control *the_thread )
_Thread_State_release( the_thread, &lock_context );
}
-void _Thread_Join(
+static void _Thread_Clear_waiting_for_join_at_exit(
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Per_CPU_Control *cpu_self,
+ Thread_queue_Context *queue_context
+)
+{
+ (void) the_thread;
+ (void) cpu_self;
+ (void) queue_context;
+ _Thread_Clear_state( queue->owner, STATES_WAITING_FOR_JOIN_AT_EXIT );
+}
+
+Status_Control _Thread_Join(
Thread_Control *the_thread,
States_Control waiting_for_join,
Thread_Control *executing,
Thread_queue_Context *queue_context
)
{
- _Assert( the_thread != executing );
_Assert( _Thread_State_is_owner( the_thread ) );
executing->Wait.return_argument = NULL;
-
+ _Thread_queue_Context_set_enqueue_callout(
+ queue_context,
+ _Thread_Clear_waiting_for_join_at_exit
+ );
+ _Thread_queue_Context_set_deadlock_callout(
+ queue_context,
+ _Thread_queue_Deadlock_status
+ );
_Thread_queue_Context_set_thread_state( queue_context, waiting_for_join );
_Thread_queue_Enqueue(
&the_thread->Join_queue.Queue,
@@ -393,6 +402,7 @@ void _Thread_Join(
executing,
queue_context
);
+ return _Thread_Wait_get_status( executing );
}
static void _Thread_Set_exit_value(
@@ -413,8 +423,7 @@ static void _Thread_Try_life_change_request(
_Thread_Add_life_change_request( the_thread );
_Thread_State_release( the_thread, lock_context );
- _Thread_queue_Extract_with_proxy( the_thread );
- _Thread_Timer_remove( the_thread );
+ _Thread_Timer_remove_and_continue( the_thread, STATUS_INTERNAL_ERROR );
_Thread_Remove_life_change_request( the_thread );
} else {
_Thread_Clear_state_locked( the_thread, STATES_SUSPENDED );
@@ -422,77 +431,70 @@ static void _Thread_Try_life_change_request(
}
}
-void _Thread_Cancel(
- Thread_Control *the_thread,
- Thread_Control *executing,
- void *exit_value
+Thread_Cancel_state _Thread_Cancel(
+ Thread_Control *the_thread,
+ Thread_Control *executing,
+ Thread_Life_state life_states_to_clear
)
{
- ISR_lock_Context lock_context;
- Thread_Life_state previous;
- Per_CPU_Control *cpu_self;
+ ISR_lock_Context lock_context;
+ Thread_Life_state previous;
_Assert( the_thread != executing );
_Thread_State_acquire( the_thread, &lock_context );
- _Thread_Set_exit_value( the_thread, exit_value );
+ _Thread_Set_exit_value( the_thread, PTHREAD_CANCELED );
previous = _Thread_Change_life_locked(
the_thread,
- 0,
+ life_states_to_clear,
THREAD_LIFE_TERMINATING,
0
);
- cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
-
if ( _States_Is_dormant( the_thread->current_state ) ) {
_Thread_State_release( the_thread, &lock_context );
_Thread_Make_zombie( the_thread );
- } else {
- Priority_Control priority;
-
- _Thread_Try_life_change_request( the_thread, previous, &lock_context );
- priority = _Thread_Get_priority( executing );
- _Thread_Raise_real_priority( the_thread, priority );
+ return THREAD_CANCEL_DONE;
}
- _Thread_Dispatch_enable( cpu_self );
+ _Thread_Try_life_change_request( the_thread, previous, &lock_context );
+ return THREAD_CANCEL_IN_PROGRESS;
}
-static void _Thread_Close_enqueue_callout(
- Thread_queue_Queue *queue,
+Status_Control _Thread_Close(
Thread_Control *the_thread,
- Per_CPU_Control *cpu_self,
+ Thread_Control *executing,
Thread_queue_Context *queue_context
)
{
- Thread_Close_context *context;
+ Per_CPU_Control *cpu_self;
+ Thread_Cancel_state cancel_state;
- context = (Thread_Close_context *) queue_context;
- _Thread_Cancel( context->cancel, the_thread, NULL );
-}
-
-void _Thread_Close(
- Thread_Control *the_thread,
- Thread_Control *executing,
- Thread_Close_context *context
-)
-{
- context->cancel = the_thread;
- _Thread_queue_Context_set_enqueue_callout(
- &context->Base,
- _Thread_Close_enqueue_callout
+ cpu_self = _Thread_Dispatch_disable_critical(
+ &queue_context->Lock_context.Lock_context
);
+ _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
+
+ cancel_state = _Thread_Cancel( the_thread, executing, THREAD_LIFE_DETACHED );
+
+ if ( cancel_state == THREAD_CANCEL_DONE ) {
+ _Thread_Dispatch_enable( cpu_self );
+ return STATUS_SUCCESSFUL;
+ }
+
+ _ISR_lock_ISR_disable( &queue_context->Lock_context.Lock_context );
+ _Thread_Dispatch_unnest( cpu_self );
_Thread_State_acquire_critical(
the_thread,
- &context->Base.Lock_context.Lock_context
+ &queue_context->Lock_context.Lock_context
);
- _Thread_Join(
+
+ return _Thread_Join(
the_thread,
STATES_WAITING_FOR_JOIN,
executing,
- &context->Base
+ queue_context
);
}
@@ -576,7 +578,7 @@ Status_Control _Thread_Restart(
the_thread,
&the_thread->Real_priority,
the_thread->Start.initial_priority,
- false,
+ PRIORITY_GROUP_LAST,
&queue_context
);
_Thread_Wait_release( the_thread, &queue_context );