summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-05-20 17:15:53 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-05-26 13:40:24 +0200
commitce6319ade410d304c187de6d107b52da4a32e255 (patch)
treef5fa9164cc353bd726f7e794612630f874917aa9 /cpukit
parent29187be532c7d6c7b81f2e7def132bbfba7c916c (diff)
downloadrtems-ce6319ade410d304c187de6d107b52da4a32e255.tar.bz2
score: Fix _Thread_Cancel()
The _Thread_Cancel() (in contrast to _Thread_Restart() which used a similar code block) may have produced ready threads with an active timer in case the thread to cancel had its thread life protection enabled. The problem was this code block: Priority_Control priority; _Thread_Add_life_change_request( the_thread ); if ( _Thread_Is_life_change_allowed( previous ) ) { _Thread_State_release( the_thread, &lock_context ); _Thread_queue_Extract_with_proxy( the_thread ); _Thread_Timer_remove( the_thread ); } else { _Thread_Clear_state_locked( the_thread, STATES_SUSPENDED ); _Thread_State_release( the_thread, &lock_context ); } priority = _Thread_Get_priority( executing ); _Thread_Raise_real_priority( the_thread, priority ); _Thread_Remove_life_change_request( the_thread ); The life change request should only be added/removed if a life change is allowed (see _Thread_Restart()). Add _Thread_Try_life_change_request() and use it in _Thread_Cancel() and _Thread_Restart(). Close #4435.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/score/src/threadrestart.c48
1 files changed, 22 insertions, 26 deletions
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 0ba5ca24ba..e4e123b9f0 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -12,7 +12,7 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
- * Copyright (c) 2014, 2016 embedded brains GmbH.
+ * Copyright (c) 2014, 2021 embedded brains GmbH.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -403,6 +403,25 @@ static void _Thread_Set_exit_value(
the_thread->Life.exit_value = exit_value;
}
+static void _Thread_Try_life_change_request(
+ Thread_Control *the_thread,
+ Thread_Life_state previous,
+ ISR_lock_Context *lock_context
+)
+{
+ if ( _Thread_Is_life_change_allowed( previous ) ) {
+ _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_Remove_life_change_request( the_thread );
+ } else {
+ _Thread_Clear_state_locked( the_thread, STATES_SUSPENDED );
+ _Thread_State_release( the_thread, lock_context );
+ }
+}
+
void _Thread_Cancel(
Thread_Control *the_thread,
Thread_Control *executing,
@@ -433,21 +452,9 @@ void _Thread_Cancel(
} else {
Priority_Control priority;
- _Thread_Add_life_change_request( the_thread );
-
- if ( _Thread_Is_life_change_allowed( previous ) ) {
- _Thread_State_release( the_thread, &lock_context );
-
- _Thread_queue_Extract_with_proxy( the_thread );
- _Thread_Timer_remove( the_thread );
- } else {
- _Thread_Clear_state_locked( the_thread, STATES_SUSPENDED );
- _Thread_State_release( the_thread, &lock_context );
- }
-
+ _Thread_Try_life_change_request( the_thread, previous, &lock_context );
priority = _Thread_Get_priority( executing );
_Thread_Raise_real_priority( the_thread, priority );
- _Thread_Remove_life_change_request( the_thread );
}
_Thread_Dispatch_enable( cpu_self );
@@ -560,18 +567,7 @@ Status_Control _Thread_Restart(
THREAD_LIFE_RESTARTING,
ignored_life_states
);
-
- if ( _Thread_Is_life_change_allowed( previous ) ) {
- _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_Remove_life_change_request( the_thread );
- } else {
- _Thread_Clear_state_locked( the_thread, STATES_SUSPENDED );
- _Thread_State_release( the_thread, lock_context );
- }
+ _Thread_Try_life_change_request( the_thread, previous, lock_context );
_Thread_queue_Context_initialize( &queue_context );
_Thread_queue_Context_clear_priority_updates( &queue_context );