@@ -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