On 2014-05-21 16:00, Joel Sherrill wrote:
Hi

We have an SMP behavioral decision to make and it isn't getting
enough discussion.

With cluster scheduling, there are potentially multiple scheduler
instances associated with non-overlapping subsets of cores.

With affinity, a thread can be restricted to execute on a subset
of the cores associated with a scheduler instance.

There are operations to change the scheduler associated with
a thread and the affinity of a thread.

The question is whether changing affinity should be able to
implicitly change the scheduler instance?

I lean to no because affinity and scheduler changes should
should be so rare in practical use that nothing should be
implicit.

The pthread_setaffinity_np() is the only way to set the scheduler via the non-portable POSIX API. So I would keep the ability to change the scheduler with it.

How would you change the scheduler with the non-portable POSIX API?


Consider this scenario:

Scheduler A: cores 0-1
Scheduler B: cores 2-3

Thread 1 is associated with Scheduler B and with affinity 2-3
can run on either processor scheduled by B.

Thread 1 changes affinity 1-3. Should this change the scheduler,
be an error, or just have an affinity for a core in the system
that is not scheduled by this scheduler instance?

This is currently an error:

http://git.rtems.org/rtems/tree/testsuites/smptests/smpscheduler02/init.c#n141


If you look at the current code for _Scheduler_Set_affinity(),
it looks like the current behavior is none of the above and
appears to just be broken. Scheduler A's set affinity operation
is invoked and Scheduler B is not informed that it no longer
has control of Thread 1.


It is informed in case _Scheduler_default_Set_affinity_body() is used. What is broken is the _Scheduler_priority_affinity_SMP_Set_affinity() function.

Please have a look at the attached patch which I already sent to a similar 
thread.

--
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.hu...@embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
>From 4c7a22c3b110856b3654b3ad8d29acc98448b284 Mon Sep 17 00:00:00 2001
From: Sebastian Huber <sebastian.hu...@embedded-brains.de>
Date: Wed, 21 May 2014 09:07:51 +0200
Subject: [PATCH] score: _Scheduler_Set_affinity()

Check that the CPU set doesn't overlap two or more scheduler instances
in _Scheduler_Set_affinity() and remove this check in
_Scheduler_default_Set_affinity().

Allow that CPUs are set outside of the processor set of the system in
_Scheduler_default_Set_affinity().  This avoids errors in case an
application is used on systems with different processor sets.
---
 cpukit/score/include/rtems/score/schedulerimpl.h |   28 ++++------
 cpukit/score/src/schedulersetaffinity.c          |   61 +++++++++++++---------
 2 files changed, 48 insertions(+), 41 deletions(-)

diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index 15a4207..401cef9 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -419,35 +419,31 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_default_Set_affinity_body(
   const cpu_set_t         *cpuset
 )
 {
-  size_t   cpu_max   = _CPU_set_Maximum_CPU_count( cpusetsize );
+#if defined(RTEMS_SMP)
   uint32_t cpu_count = _SMP_Get_processor_count();
   uint32_t cpu_index;
   bool     ok = true;
 
+  /* Check that the CPU set covers all processors of this scheduler instance */
   for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
-#if defined(RTEMS_SMP)
     const Scheduler_Control *scheduler_of_cpu =
       _Scheduler_Get_by_CPU_index( cpu_index );
 
-    ok = ok
-      && ( ( CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset )
-          && scheduler == scheduler_of_cpu )
-        || ( !CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset )
-          && scheduler != scheduler_of_cpu ) );
-#else
-    (void) scheduler;
-
-    ok = ok && CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset );
-#endif
+    if ( !CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset ) ) {
+      ok = ok && scheduler != scheduler_of_cpu;
+    }
   }
 
-  for ( ; cpu_index < cpu_max ; ++cpu_index ) {
-    ok = ok && !CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset );
+  if ( ok ) {
+    _Scheduler_Set( scheduler, the_thread );
   }
 
-  _Scheduler_Set( scheduler, the_thread );
-
   return ok;
+#else
+  (void) scheduler;
+
+  return CPU_ISSET_S( 0, cpusetsize, cpuset );
+#endif
 }
 
 bool _Scheduler_Set_affinity(
diff --git a/cpukit/score/src/schedulersetaffinity.c b/cpukit/score/src/schedulersetaffinity.c
index a20888b..b4fea3c 100644
--- a/cpukit/score/src/schedulersetaffinity.c
+++ b/cpukit/score/src/schedulersetaffinity.c
@@ -26,45 +26,56 @@ bool _Scheduler_Set_affinity(
   const cpu_set_t         *cpuset
 )
 {
-  bool ok;
-
-  if ( _CPU_set_Is_large_enough( cpusetsize ) ) {
 #if defined(RTEMS_SMP)
-    uint32_t cpu_count = _SMP_Get_processor_count();
-    uint32_t cpu_index;
+  uint32_t                 cpu_count = _SMP_Get_processor_count();
+  uint32_t                 cpu_index;
+  const Scheduler_Control *scheduler_of_cpuset = NULL;
+  bool                     ok = false;
+#endif
 
-    ok = false;
+  if ( !_CPU_set_Is_large_enough( cpusetsize ) ) {
+    return false;
+  }
 
-    for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
-      if ( CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset ) ) {
-        const Scheduler_Control *scheduler_of_cpu =
-          _Scheduler_Get_by_CPU_index( cpu_index );
+#if defined(RTEMS_SMP)
+  /*
+   * Check that the CPU set doesn't overlap with two or more scheduler
+   * instances.
+   */
+  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
+    if ( CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset ) ) {
+      const Scheduler_Control *scheduler_of_cpu =
+        _Scheduler_Get_by_CPU_index( cpu_index );
 
-        if ( scheduler_of_cpu != NULL ) {
-          ok = ( *scheduler_of_cpu->Operations.set_affinity )(
-            scheduler_of_cpu,
-            the_thread,
-            cpusetsize,
-            cpuset
-          );
+      if ( scheduler_of_cpu != NULL ) {
+        if ( scheduler_of_cpuset == NULL ) {
+          scheduler_of_cpuset = scheduler_of_cpu;
+          ok = true;
+        } else {
+          ok = ok && scheduler_of_cpu == scheduler_of_cpuset;
         }
-
-        break;
       }
     }
-#else
-    ok = _Scheduler_default_Set_affinity_body(
-      _Scheduler_Get( the_thread ),
+  }
+
+  if ( ok ) {
+    ok = ( *scheduler_of_cpuset->Operations.set_affinity )(
+      scheduler_of_cpuset,
       the_thread,
       cpusetsize,
       cpuset
     );
-#endif
-  } else {
-    ok = false;
   }
 
   return ok;
+#else
+  return _Scheduler_default_Set_affinity_body(
+    _Scheduler_Get( the_thread ),
+    the_thread,
+    cpusetsize,
+    cpuset
+  );
+#endif
 }
 
 #endif /* defined(__RTEMS_HAVE_SYS_CPUSET_H__) */
-- 
1.7.7

_______________________________________________
rtems-devel mailing list
rtems-devel@rtems.org
http://www.rtems.org/mailman/listinfo/rtems-devel

Reply via email to