[PATCH 11/14] score: Avoid Giant lock _Scheduler_Set_affinity()

Sebastian Huber sebastian.huber at embedded-brains.de
Wed May 11 13:23:38 UTC 2016


Update #2555.
---
 cpukit/posix/src/pthreadcreate.c                 |  8 ++--
 cpukit/posix/src/pthreadsetaffinitynp.c          | 59 +++++++++++++-----------
 cpukit/rtems/src/tasksetaffinity.c               | 43 +++++++++--------
 cpukit/score/include/rtems/score/schedulerimpl.h |  6 +--
 cpukit/score/include/rtems/score/thread.h        |  1 +
 cpukit/score/src/schedulersetaffinity.c          | 20 +++++---
 6 files changed, 78 insertions(+), 59 deletions(-)

diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c
index 2533345..eedb80e 100644
--- a/cpukit/posix/src/pthreadcreate.c
+++ b/cpukit/posix/src/pthreadcreate.c
@@ -74,7 +74,7 @@ int pthread_create(
   struct sched_param                  schedparam;
   Objects_Name                        name;
   int                                 rc;
-  ISR_Level                           level;
+  ISR_lock_Context                    lock_context;
 
   if ( !start_routine )
     return EFAULT;
@@ -202,11 +202,13 @@ int pthread_create(
   }
 
 #if defined(RTEMS_SMP) && __RTEMS_HAVE_SYS_CPUSET_H__
+  _ISR_lock_ISR_disable( &lock_context );
    status = _Scheduler_Set_affinity(
      the_thread,
      the_attr->affinitysetsize,
      the_attr->affinityset
    );
+  _ISR_lock_ISR_enable( &lock_context );
    if ( !status ) {
      _POSIX_Threads_Free( the_thread );
      _RTEMS_Unlock_allocator();
@@ -247,13 +249,13 @@ int pthread_create(
   #endif
 
   if ( schedpolicy == SCHED_SPORADIC ) {
-    _ISR_Disable_without_giant( level );
+    _ISR_lock_ISR_disable( &lock_context );
     _Watchdog_Per_CPU_insert_relative(
       &api->Sporadic_timer,
       _Per_CPU_Get(),
       _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period )
     );
-    _ISR_Enable_without_giant( level );
+    _ISR_lock_ISR_enable( &lock_context );
   }
 
   _Thread_Enable_dispatch();
diff --git a/cpukit/posix/src/pthreadsetaffinitynp.c b/cpukit/posix/src/pthreadsetaffinitynp.c
index 711d6dc..6dd8bce 100644
--- a/cpukit/posix/src/pthreadsetaffinitynp.c
+++ b/cpukit/posix/src/pthreadsetaffinitynp.c
@@ -31,41 +31,44 @@
 #include <rtems/score/schedulerimpl.h>
 
 int pthread_setaffinity_np(
-  pthread_t          id,
-  size_t             cpusetsize,
-  const cpu_set_t   *cpuset)
+  pthread_t        thread,
+  size_t           cpusetsize,
+  const cpu_set_t *cpuset
+)
 {
-  Objects_Locations        location;
-  POSIX_API_Control       *api;
-  Thread_Control          *the_thread;
-  bool                     ok;
+  Thread_Control   *the_thread;
+  ISR_lock_Context  lock_context;
+  Per_CPU_Control  *cpu_self;
+  bool              ok;
 
-  if ( !cpuset )
+  if ( cpuset == NULL ) {
     return EFAULT;
+  }
 
-  the_thread = _Thread_Get( id, &location );
-  switch ( location ) {
+  the_thread = _Thread_Get_interrupt_disable( thread, &lock_context );
 
-    case OBJECTS_LOCAL:
-      ok = _Scheduler_Set_affinity(
-        the_thread,
-        cpusetsize,
-        cpuset
-      );
-      if ( ok ) {
-        api = the_thread->API_Extensions[ THREAD_API_POSIX ];
-        CPU_COPY( api->Attributes.affinityset, cpuset );
-      }
-      _Objects_Put( &the_thread->Object );
-      return ok ? 0 : EINVAL;
+  if ( the_thread == NULL ) {
+    return ESRCH;
+  }
 
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
+  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
+  _Thread_State_acquire_critical( the_thread, &lock_context );
+
+  ok = _Scheduler_Set_affinity(
+    the_thread,
+    cpusetsize,
+    cpuset
+  );
+
+  if ( ok ) {
+    POSIX_API_Control *api;
+
+    api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+    CPU_COPY( api->Attributes.affinityset, cpuset );
   }
 
-  return ESRCH;
+  _Thread_State_release( the_thread, &lock_context );
+  _Thread_Dispatch_enable( cpu_self );
+  return ok ? 0 : EINVAL;
 }
 #endif
diff --git a/cpukit/rtems/src/tasksetaffinity.c b/cpukit/rtems/src/tasksetaffinity.c
index a7a18be..6389e4c 100644
--- a/cpukit/rtems/src/tasksetaffinity.c
+++ b/cpukit/rtems/src/tasksetaffinity.c
@@ -31,33 +31,38 @@ rtems_status_code rtems_task_set_affinity(
   const cpu_set_t *cpuset
 )
 {
-  Thread_Control        *the_thread;
-  Objects_Locations      location;
-  int                    ok;
+  Thread_Control   *the_thread;
+  ISR_lock_Context  lock_context;
+  Per_CPU_Control  *cpu_self;
+  bool              ok;
 
-  if ( !cpuset )
+  if ( cpuset == NULL ) {
     return RTEMS_INVALID_ADDRESS;
+  }
 
-  the_thread = _Thread_Get( id, &location );
-  switch ( location ) {
-
-    case OBJECTS_LOCAL:
-      ok = _Scheduler_Set_affinity(
-        the_thread,
-        cpusetsize,
-        cpuset
-      );
-      _Objects_Put( &the_thread->Object );
-      return ok ? RTEMS_SUCCESSFUL : RTEMS_INVALID_NUMBER;
+  the_thread = _Thread_Get_interrupt_disable( id, &lock_context );
 
+  if ( the_thread == NULL ) {
 #if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
+    if ( _Thread_MP_Is_remote( id ) ) {
+      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+    }
 #endif
 
-    case OBJECTS_ERROR:
-      break;
+    return RTEMS_INVALID_ID;
   }
 
-  return RTEMS_INVALID_ID;
+  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
+  _Thread_State_acquire_critical( the_thread, &lock_context );
+
+  ok = _Scheduler_Set_affinity(
+    the_thread,
+    cpusetsize,
+    cpuset
+  );
+
+  _Thread_State_release( the_thread, &lock_context );
+  _Thread_Dispatch_enable( cpu_self );
+  return ok ? RTEMS_SUCCESSFUL : RTEMS_INVALID_NUMBER;
 }
 #endif
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index 99f590e..c149a9e 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -698,9 +698,9 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_default_Set_affinity_body(
 }
 
 bool _Scheduler_Set_affinity(
-  Thread_Control          *the_thread,
-  size_t                   cpusetsize,
-  const cpu_set_t         *cpuset
+  Thread_Control  *the_thread,
+  size_t           cpusetsize,
+  const cpu_set_t *cpuset
 );
 
 #endif /* defined(__RTEMS_HAVE_SYS_CPUSET_H__) */
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 15b068d..18e0f54 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -718,6 +718,7 @@ struct _Thread_Control {
    * The lock of this thread queue is used for various purposes.  It protects
    * the following fields
    *
+   * - POSIX_API_Control::Attributes,
    * - RTEMS_API_Control::Signal,
    * - Thread_Control::current_state,
    * - Thread_Control::Post_switch_actions,
diff --git a/cpukit/score/src/schedulersetaffinity.c b/cpukit/score/src/schedulersetaffinity.c
index f7c9336..b59d8eb 100644
--- a/cpukit/score/src/schedulersetaffinity.c
+++ b/cpukit/score/src/schedulersetaffinity.c
@@ -21,32 +21,40 @@
 #if defined(__RTEMS_HAVE_SYS_CPUSET_H__)
 
 bool _Scheduler_Set_affinity(
-  Thread_Control          *the_thread,
-  size_t                   cpusetsize,
-  const cpu_set_t         *cpuset
+  Thread_Control  *the_thread,
+  size_t           cpusetsize,
+  const cpu_set_t *cpuset
 )
 {
-  const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
+  const Scheduler_Control *scheduler;
+  ISR_lock_Context         lock_context;
+  bool                     ok;
 
   if ( !_CPU_set_Is_large_enough( cpusetsize ) ) {
     return false;
   }
 
+  scheduler = _Scheduler_Get( the_thread );
+  _Scheduler_Acquire_critical( scheduler, &lock_context );
+
 #if defined(RTEMS_SMP)
-  return ( *scheduler->Operations.set_affinity )(
+  ok = ( *scheduler->Operations.set_affinity )(
     scheduler,
     the_thread,
     cpusetsize,
     cpuset
   );
 #else
-  return _Scheduler_default_Set_affinity_body(
+  ok = _Scheduler_default_Set_affinity_body(
     scheduler,
     the_thread,
     cpusetsize,
     cpuset
   );
 #endif
+
+  _Scheduler_Release_critical( scheduler, &lock_context );
+  return ok;
 }
 
 #endif /* defined(__RTEMS_HAVE_SYS_CPUSET_H__) */
-- 
1.8.4.5




More information about the devel mailing list