diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-06-18 12:11:04 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-06-20 08:24:46 +0200 |
commit | f6b7b7ba0ae31a7e0f4aace3ebec03e0623d2e40 (patch) | |
tree | a9770794691dfb7ea6128005675d6f5c49872160 /cpukit/rtems | |
parent | smptests/smpwakeafter01: New test (diff) | |
download | rtems-f6b7b7ba0ae31a7e0f4aace3ebec03e0623d2e40.tar.bz2 |
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.
Diffstat (limited to 'cpukit/rtems')
-rw-r--r-- | cpukit/rtems/src/taskwakeafter.c | 4 | ||||
-rw-r--r-- | cpukit/rtems/src/taskwakewhen.c | 12 | ||||
-rw-r--r-- | cpukit/rtems/src/timerserver.c | 8 |
3 files changed, 13 insertions, 11 deletions
diff --git a/cpukit/rtems/src/taskwakeafter.c b/cpukit/rtems/src/taskwakeafter.c index 88de6e51a8..6f0322723a 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 01e855a125..a1fc15f047 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 76c7a3fe79..7523ebcdf4 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 ); /* |