re PR libgomp/80822 (libgomp incorrect affinity when OMP_PLACES=threads)
authorJakub Jelinek <jakub@redhat.com>
Tue, 30 May 2017 12:05:30 +0000 (14:05 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 30 May 2017 12:05:30 +0000 (14:05 +0200)
PR libgomp/80822
* config/linux/affinity.c (gomp_affinity_init_level_1): New function.
(gomp_affinity_init_level): Use it.  Always analyze the core and thread
sibling lists, depending on level just pick up what CPUs to put
together into a place vs. whether add multiple ordered places.

From-SVN: r248683

libgomp/ChangeLog
libgomp/config/linux/affinity.c

index 8adc10b3614fc3623cfb35c470f4aca866ffd778..a51228b4504c2102fca00cf3b1a0ec22e67adf87 100644 (file)
@@ -1,3 +1,11 @@
+2017-05-30  Jakub Jelinek  <jakub@redhat.com>
+
+       PR libgomp/80822
+       * config/linux/affinity.c (gomp_affinity_init_level_1): New function.
+       (gomp_affinity_init_level): Use it.  Always analyze the core and thread
+       sibling lists, depending on level just pick up what CPUs to put
+       together into a place vs. whether add multiple ordered places.
+
 2017-05-24  Thomas Schwinge  <thomas@codesourcery.com>
 
        * openacc.h (acc_async_wait, acc_async_wait_all): New prototypes.
index c5b2cb810063b0a7641165628d73754f2eb74897..cbc96870f4fc87aa30d7bd2098191d5a8c041d2d 100644 (file)
@@ -222,10 +222,87 @@ gomp_affinity_finalize_place_list (bool quiet)
   return true;
 }
 
+static void
+gomp_affinity_init_level_1 (int level, int this_level, unsigned long count,
+                           cpu_set_t *copy, char *name, bool quiet)
+{
+  size_t prefix_len = sizeof ("/sys/devices/system/cpu/cpu") - 1;
+  FILE *f;
+  char *line = NULL;
+  size_t linelen = 0;
+  unsigned long i, max = 8 * gomp_cpuset_size;
+
+  for (i = 0; i < max && gomp_places_list_len < count; i++)
+    if (CPU_ISSET_S (i, gomp_cpuset_size, copy))
+      {
+       sprintf (name + prefix_len, "%lu/topology/%s_siblings_list",
+                i, this_level == 3 ? "core" : "thread");
+       f = fopen (name, "r");
+       if (f == NULL)
+         {
+           CPU_CLR_S (i, gomp_cpuset_size, copy);
+           continue;
+         }
+       if (getline (&line, &linelen, f) > 0)
+         {
+           char *p = line;
+           void *pl = gomp_places_list[gomp_places_list_len];
+           if (level == this_level)
+             gomp_affinity_init_place (pl);
+           while (*p && *p != '\n')
+             {
+               unsigned long first, last;
+               errno = 0;
+               first = strtoul (p, &p, 10);
+               if (errno)
+                 break;
+               last = first;
+               if (*p == '-')
+                 {
+                   errno = 0;
+                   last = strtoul (p + 1, &p, 10);
+                   if (errno || last < first)
+                     break;
+                 }
+               for (; first <= last; first++)
+                 if (!CPU_ISSET_S (first, gomp_cpuset_size, copy))
+                   continue;
+                 else if (this_level == 3 && level < this_level)
+                   gomp_affinity_init_level_1 (level, 2, count, copy,
+                                               name, quiet);
+                 else
+                   {
+                     if (level == 1)
+                       {
+                         pl = gomp_places_list[gomp_places_list_len];
+                         gomp_affinity_init_place (pl);
+                       }
+                     if (gomp_affinity_add_cpus (pl, first, 1, 0, true))
+                       {
+                         CPU_CLR_S (first, gomp_cpuset_size, copy);
+                         if (level == 1)
+                           gomp_places_list_len++;
+                       }
+                   }
+               if (*p == ',')
+                 ++p;
+             }
+           if (level == this_level
+               && !CPU_ISSET_S (i, gomp_cpuset_size, copy))
+             gomp_places_list_len++;
+           CPU_CLR_S (i, gomp_cpuset_size, copy);
+         }
+       fclose (f);
+      }
+  free (line);
+}
+
 bool
 gomp_affinity_init_level (int level, unsigned long count, bool quiet)
 {
-  unsigned long i, max = 8 * gomp_cpuset_size;
+  char name[sizeof ("/sys/devices/system/cpu/cpu/topology/"
+                   "thread_siblings_list") + 3 * sizeof (unsigned long)];
+  cpu_set_t *copy;
 
   if (gomp_cpusetp)
     {
@@ -238,90 +315,20 @@ gomp_affinity_init_level (int level, unsigned long count, bool quiet)
   gomp_places_list_len = 0;
   if (gomp_places_list == NULL)
     return false;
-  /* SMT (threads).  */
-  if (level == 1)
-    {
-      for (i = 0; i < max && gomp_places_list_len < count; i++)
-       if (CPU_ISSET_S (i, gomp_cpuset_size, gomp_cpusetp))
-         {
-           gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
-           gomp_affinity_add_cpus (gomp_places_list[gomp_places_list_len],
-                                   i, 1, 0, true);
-           ++gomp_places_list_len;
-         }
-      return true;
-    }
-  else
+
+  copy = gomp_alloca (gomp_cpuset_size);
+  strcpy (name, "/sys/devices/system/cpu/cpu");
+  memcpy (copy, gomp_cpusetp, gomp_cpuset_size);
+  gomp_affinity_init_level_1 (level, 3, count, copy, name, quiet);
+  if (gomp_places_list_len == 0)
     {
-      char name[sizeof ("/sys/devices/system/cpu/cpu/topology/"
-                       "thread_siblings_list") + 3 * sizeof (unsigned long)];
-      size_t prefix_len = sizeof ("/sys/devices/system/cpu/cpu") - 1;
-      cpu_set_t *copy = gomp_alloca (gomp_cpuset_size);
-      FILE *f;
-      char *line = NULL;
-      size_t linelen = 0;
-
-      memcpy (name, "/sys/devices/system/cpu/cpu", prefix_len);
-      memcpy (copy, gomp_cpusetp, gomp_cpuset_size);
-      for (i = 0; i < max && gomp_places_list_len < count; i++)
-       if (CPU_ISSET_S (i, gomp_cpuset_size, copy))
-         {
-           sprintf (name + prefix_len, "%lu/topology/%s_siblings_list",
-                    i, level == 2 ? "thread" : "core");
-           f = fopen (name, "r");
-           if (f != NULL)
-             {
-               if (getline (&line, &linelen, f) > 0)
-                 {
-                   char *p = line;
-                   bool seen_i = false;
-                   void *pl = gomp_places_list[gomp_places_list_len];
-                   gomp_affinity_init_place (pl);
-                   while (*p && *p != '\n')
-                     {
-                       unsigned long first, last;
-                       errno = 0;
-                       first = strtoul (p, &p, 10);
-                       if (errno)
-                         break;
-                       last = first;
-                       if (*p == '-')
-                         {
-                           errno = 0;
-                           last = strtoul (p + 1, &p, 10);
-                           if (errno || last < first)
-                             break;
-                         }
-                       for (; first <= last; first++)
-                         if (CPU_ISSET_S (first, gomp_cpuset_size, copy)
-                             && gomp_affinity_add_cpus (pl, first, 1, 0,
-                                                        true))
-                           {
-                             CPU_CLR_S (first, gomp_cpuset_size, copy);
-                             if (first == i)
-                               seen_i = true;
-                           }
-                       if (*p == ',')
-                         ++p;
-                     }
-                   if (seen_i)
-                     gomp_places_list_len++;
-                 }
-               fclose (f);
-             }
-         }
-      if (gomp_places_list_len == 0)
-       {
-         if (!quiet)
-           gomp_error ("Error reading %s topology",
-                       level == 2 ? "core" : "socket");
-         free (gomp_places_list);
-         gomp_places_list = NULL;
-         return false;
-       }
-      return true;
+      if (!quiet)
+       gomp_error ("Error reading core/socket topology");
+      free (gomp_places_list);
+      gomp_places_list = NULL;
+      return false;
     }
-  return false;
+  return true;
 }
 
 void