@@ -1589,15 +1589,13 @@ kmp_str_buf_t *__kmp_affinity_str_buf_mask(kmp_str_buf_t *buf,
15891589  return  buf;
15901590}
15911591
1592- //  Return (possibly empty) affinity mask representing the offline CPUs
1593- //  Caller must free the mask
1594- kmp_affin_mask_t  *__kmp_affinity_get_offline_cpus () {
1595-   kmp_affin_mask_t  *offline;
1596-   KMP_CPU_ALLOC (offline);
1597-   KMP_CPU_ZERO (offline);
1592+ static  kmp_affin_mask_t  *__kmp_parse_cpu_list (const  char  *path) {
1593+   kmp_affin_mask_t  *mask;
1594+   KMP_CPU_ALLOC (mask);
1595+   KMP_CPU_ZERO (mask);
15981596#if  KMP_OS_LINUX
15991597  int  n, begin_cpu, end_cpu;
1600-   kmp_safe_raii_file_t  offline_file ;
1598+   kmp_safe_raii_file_t  file ;
16011599  auto  skip_ws = [](FILE *f) {
16021600    int  c;
16031601    do  {
@@ -1606,29 +1604,29 @@ kmp_affin_mask_t *__kmp_affinity_get_offline_cpus() {
16061604    if  (c != EOF)
16071605      ungetc (c, f);
16081606  };
1609-   //  File contains CSV of integer ranges representing the offline  CPUs
1607+   //  File contains CSV of integer ranges representing the CPUs
16101608  //  e.g., 1,2,4-7,9,11-15
1611-   int  status = offline_file .try_open (" /sys/devices/system/cpu/offline "  , " r"  );
1609+   int  status = file .try_open (path , " r"  );
16121610  if  (status != 0 )
1613-     return  offline ;
1614-   while  (!feof (offline_file )) {
1615-     skip_ws (offline_file );
1616-     n = fscanf (offline_file , " %d"  , &begin_cpu);
1611+     return  mask ;
1612+   while  (!feof (file )) {
1613+     skip_ws (file );
1614+     n = fscanf (file , " %d"  , &begin_cpu);
16171615    if  (n != 1 )
16181616      break ;
1619-     skip_ws (offline_file );
1620-     int  c = fgetc (offline_file );
1617+     skip_ws (file );
1618+     int  c = fgetc (file );
16211619    if  (c == EOF || c == ' ,'  ) {
16221620      //  Just single CPU
16231621      end_cpu = begin_cpu;
16241622    } else  if  (c == ' -'  ) {
16251623      //  Range of CPUs
1626-       skip_ws (offline_file );
1627-       n = fscanf (offline_file , " %d"  , &end_cpu);
1624+       skip_ws (file );
1625+       n = fscanf (file , " %d"  , &end_cpu);
16281626      if  (n != 1 )
16291627        break ;
1630-       skip_ws (offline_file );
1631-       c = fgetc (offline_file ); //  skip ','
1628+       skip_ws (file );
1629+       c = fgetc (file ); //  skip ','
16321630    } else  {
16331631      //  Syntax problem
16341632      break ;
@@ -1638,13 +1636,19 @@ kmp_affin_mask_t *__kmp_affinity_get_offline_cpus() {
16381636        end_cpu >= __kmp_xproc || begin_cpu > end_cpu) {
16391637      continue ;
16401638    }
1641-     //  Insert [begin_cpu, end_cpu] into offline  mask
1639+     //  Insert [begin_cpu, end_cpu] into mask
16421640    for  (int  cpu = begin_cpu; cpu <= end_cpu; ++cpu) {
1643-       KMP_CPU_SET (cpu, offline );
1641+       KMP_CPU_SET (cpu, mask );
16441642    }
16451643  }
16461644#endif 
1647-   return  offline;
1645+   return  mask;
1646+ }
1647+ 
1648+ //  Return (possibly empty) affinity mask representing the offline CPUs
1649+ //  Caller must free the mask
1650+ kmp_affin_mask_t  *__kmp_affinity_get_offline_cpus () {
1651+   return  __kmp_parse_cpu_list (" /sys/devices/system/cpu/offline"  );
16481652}
16491653
16501654//  Return the number of available procs
@@ -3175,6 +3179,37 @@ static inline const char *__kmp_cpuinfo_get_envvar() {
31753179  return  envvar;
31763180}
31773181
3182+ static  bool  __kmp_package_id_from_core_siblings_list (unsigned  **threadInfo,
3183+                                                      unsigned  num_avail,
3184+                                                      unsigned  idx) {
3185+   if  (!KMP_AFFINITY_CAPABLE ())
3186+     return  false ;
3187+ 
3188+   char  path[256 ];
3189+   KMP_SNPRINTF (path, sizeof (path),
3190+                " /sys/devices/system/cpu/cpu%u/topology/core_siblings_list"  ,
3191+                threadInfo[idx][osIdIndex]);
3192+   kmp_affin_mask_t  *siblings = __kmp_parse_cpu_list (path);
3193+   for  (unsigned  i = 0 ; i < num_avail; ++i) {
3194+     unsigned  cpu_id = threadInfo[i][osIdIndex];
3195+     KMP_ASSERT (cpu_id < __kmp_affin_mask_size * CHAR_BIT);
3196+     if  (!KMP_CPU_ISSET (cpu_id, siblings))
3197+       continue ;
3198+     if  (threadInfo[i][pkgIdIndex] == UINT_MAX) {
3199+       //  Arbitrarily pick the first index we encounter, it only matters that
3200+       //  the value is the same for all siblings.
3201+       threadInfo[i][pkgIdIndex] = idx;
3202+     } else  if  (threadInfo[i][pkgIdIndex] != idx) {
3203+       //  Contradictory sibling lists.
3204+       KMP_CPU_FREE (siblings);
3205+       return  false ;
3206+     }
3207+   }
3208+   KMP_ASSERT (threadInfo[idx][pkgIdIndex] != UINT_MAX);
3209+   KMP_CPU_FREE (siblings);
3210+   return  true ;
3211+ }
3212+ 
31783213//  Parse /proc/cpuinfo (or an alternate file in the same format) to obtain the
31793214//  affinity map. On AIX, the map is obtained through system SRAD (Scheduler
31803215//  Resource Allocation Domain).
@@ -3550,18 +3585,13 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
35503585        return  false ;
35513586      }
35523587
3553-       //  Check for missing fields.  The osId field must be there, and we 
3554-       //  currently require that the physical  id field is specified, also .
3588+       //  Check for missing fields.  The osId field must be there. The physical 
3589+       //  id field will be checked later .
35553590      if  (threadInfo[num_avail][osIdIndex] == UINT_MAX) {
35563591        CLEANUP_THREAD_INFO;
35573592        *msg_id = kmp_i18n_str_MissingProcField;
35583593        return  false ;
35593594      }
3560-       if  (threadInfo[0 ][pkgIdIndex] == UINT_MAX) {
3561-         CLEANUP_THREAD_INFO;
3562-         *msg_id = kmp_i18n_str_MissingPhysicalIDField;
3563-         return  false ;
3564-       }
35653595
35663596      //  Skip this proc if it is not included in the machine model.
35673597      if  (KMP_AFFINITY_CAPABLE () &&
@@ -3591,6 +3621,18 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
35913621  }
35923622  *line = 0 ;
35933623
3624+   //  At least on powerpc, Linux may return -1 for physical_package_id. Try
3625+   //  to reconstruct topology from core_siblings_list in that case.
3626+   for  (i = 0 ; i < num_avail; ++i) {
3627+     if  (threadInfo[i][pkgIdIndex] == UINT_MAX) {
3628+       if  (!__kmp_package_id_from_core_siblings_list (threadInfo, num_avail, i)) {
3629+         CLEANUP_THREAD_INFO;
3630+         *msg_id = kmp_i18n_str_MissingPhysicalIDField;
3631+         return  false ;
3632+       }
3633+     }
3634+   }
3635+ 
35943636#if  KMP_MIC && REDUCE_TEAM_SIZE
35953637  unsigned  teamSize = 0 ;
35963638#endif  //  KMP_MIC && REDUCE_TEAM_SIZE
0 commit comments