[rtems commit] score: Fix _Thread_Delay_ended() on SMP
Sebastian Huber
sebh at rtems.org
Fri Jun 20 06:17:02 UTC 2014
Module: rtems
Branch: master
Commit: f6b7b7ba0ae31a7e0f4aace3ebec03e0623d2e40
Changeset: http://git.rtems.org/rtems/commit/?id=f6b7b7ba0ae31a7e0f4aace3ebec03e0623d2e40
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Wed Jun 18 12:11:04 2014 +0200
score: Fix _Thread_Delay_ended() on SMP
Suppose we have two tasks A and B and two processors. Task A is about
to delete task B. Now task B calls rtems_task_wake_after(1) on the
other processor. Task B will block on the Giant lock. Task A
progresses with the task B deletion until it has to wait for
termination. Now task B obtains the Giant lock, sets its state to
STATES_DELAYING, initializes its watchdog timer and waits. Eventually
_Thread_Delay_ended() is called, but now _Thread_Get() returned NULL
since the thread is already marked as deleted. Thus task B remained
forever in the STATES_DELAYING state.
Instead of passing the thread identifier use the thread control block
directly via the watchdog user argument. This makes
_Thread_Delay_ended() also a bit more efficient.
---
cpukit/posix/src/nanosleep.c | 4 ++--
cpukit/rtems/src/taskwakeafter.c | 4 ++--
cpukit/rtems/src/taskwakewhen.c | 12 +++++++-----
cpukit/rtems/src/timerserver.c | 8 ++++----
cpukit/score/src/threaddelayended.c | 30 ++++++++++--------------------
5 files changed, 25 insertions(+), 33 deletions(-)
diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c
index 54902b9..1fbeaa3 100644
--- a/cpukit/posix/src/nanosleep.c
+++ b/cpukit/posix/src/nanosleep.c
@@ -85,8 +85,8 @@ int nanosleep(
_Watchdog_Initialize(
&executing->Timer,
_Thread_Delay_ended,
- executing->Object.id,
- NULL
+ 0,
+ executing
);
_Watchdog_Insert_ticks( &executing->Timer, ticks );
_Thread_Enable_dispatch();
diff --git a/cpukit/rtems/src/taskwakeafter.c b/cpukit/rtems/src/taskwakeafter.c
index 88de6e5..6f03227 100644
--- a/cpukit/rtems/src/taskwakeafter.c
+++ b/cpukit/rtems/src/taskwakeafter.c
@@ -42,8 +42,8 @@ rtems_status_code rtems_task_wake_after(
_Watchdog_Initialize(
&executing->Timer,
_Thread_Delay_ended,
- executing->Object.id,
- NULL
+ 0,
+ executing
);
_Watchdog_Insert_ticks( &executing->Timer, ticks );
}
diff --git a/cpukit/rtems/src/taskwakewhen.c b/cpukit/rtems/src/taskwakewhen.c
index 01e855a..a1fc15f 100644
--- a/cpukit/rtems/src/taskwakewhen.c
+++ b/cpukit/rtems/src/taskwakewhen.c
@@ -29,6 +29,7 @@ rtems_status_code rtems_task_wake_when(
)
{
Watchdog_Interval seconds;
+ Thread_Control *executing;
if ( !_TOD_Is_set() )
return RTEMS_NOT_DEFINED;
@@ -47,15 +48,16 @@ rtems_status_code rtems_task_wake_when(
return RTEMS_INVALID_CLOCK;
_Thread_Disable_dispatch();
- _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_TIME );
+ executing = _Thread_Executing;
+ _Thread_Set_state( executing, STATES_WAITING_FOR_TIME );
_Watchdog_Initialize(
- &_Thread_Executing->Timer,
+ &executing->Timer,
_Thread_Delay_ended,
- _Thread_Executing->Object.id,
- NULL
+ 0,
+ executing
);
_Watchdog_Insert_seconds(
- &_Thread_Executing->Timer,
+ &executing->Timer,
seconds - _TOD_Seconds_since_epoch()
);
_Thread_Enable_dispatch();
diff --git a/cpukit/rtems/src/timerserver.c b/cpukit/rtems/src/timerserver.c
index 76c7a3f..7523ebc 100644
--- a/cpukit/rtems/src/timerserver.c
+++ b/cpukit/rtems/src/timerserver.c
@@ -551,14 +551,14 @@ rtems_status_code rtems_timer_initiate_server(
_Watchdog_Initialize(
&ts->Interval_watchdogs.System_watchdog,
_Thread_Delay_ended,
- id,
- NULL
+ 0,
+ ts->thread
);
_Watchdog_Initialize(
&ts->TOD_watchdogs.System_watchdog,
_Thread_Delay_ended,
- id,
- NULL
+ 0,
+ ts->thread
);
/*
diff --git a/cpukit/score/src/threaddelayended.c b/cpukit/score/src/threaddelayended.c
index 0eb3adf..95dae7d 100644
--- a/cpukit/score/src/threaddelayended.c
+++ b/cpukit/score/src/threaddelayended.c
@@ -22,27 +22,17 @@
void _Thread_Delay_ended(
Objects_Id id,
- void *ignored __attribute__((unused))
+ void *arg
)
{
- Thread_Control *the_thread;
- Objects_Locations location;
+ Thread_Control *the_thread = arg;
- the_thread = _Thread_Get( id, &location );
- switch ( location ) {
- case OBJECTS_ERROR:
-#if defined(RTEMS_MULTIPROCESSING)
- case OBJECTS_REMOTE: /* impossible */
-#endif
- break;
- case OBJECTS_LOCAL:
- _Thread_Clear_state(
- the_thread,
- STATES_DELAYING
- | STATES_WAITING_FOR_TIME
- | STATES_INTERRUPTIBLE_BY_SIGNAL
- );
- _Objects_Put_without_thread_dispatch( &the_thread->Object );
- break;
- }
+ (void) id;
+
+ _Thread_Clear_state(
+ the_thread,
+ STATES_DELAYING
+ | STATES_WAITING_FOR_TIME
+ | STATES_INTERRUPTIBLE_BY_SIGNAL
+ );
}
More information about the vc
mailing list