[PATCH] score: Fix _Thread_Delay_ended() on SMP

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Jun 18 12:04:39 UTC 2014


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
+  );
 }
-- 
1.7.7



More information about the devel mailing list