@@ -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,30 @@ static inline const char *__kmp_cpuinfo_get_envvar() {
31753179 return envvar;
31763180}
31773181
3182+ static bool __kmp_package_id_from_core_sibling_list (unsigned **threadInfo,
3183+ unsigned idx) {
3184+ char path[256 ];
3185+ KMP_SNPRINTF (path, sizeof (path),
3186+ " /sys/devices/system/cpu/cpu%u/topology/core_siblings_list" ,
3187+ threadInfo[idx][osIdIndex]);
3188+ kmp_affin_mask_t *siblings = __kmp_parse_cpu_list (path);
3189+ for (unsigned i = 0 ; i < __kmp_xproc; ++i) {
3190+ if (!KMP_CPU_ISSET (i, siblings))
3191+ continue ;
3192+ if (threadInfo[i][pkgIdIndex] == UINT_MAX) {
3193+ // Arbitrarily pick the first index we encounter, it only matters that
3194+ // the value is the same for all siblings.
3195+ threadInfo[i][pkgIdIndex] = idx;
3196+ } else if (threadInfo[i][pkgIdIndex] != idx) {
3197+ // Contradictory sibling lists.
3198+ KMP_CPU_FREE (siblings);
3199+ return false ;
3200+ }
3201+ }
3202+ KMP_CPU_FREE (siblings);
3203+ return true ;
3204+ }
3205+
31783206// Parse /proc/cpuinfo (or an alternate file in the same format) to obtain the
31793207// affinity map. On AIX, the map is obtained through system SRAD (Scheduler
31803208// Resource Allocation Domain).
@@ -3550,18 +3578,13 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
35503578 return false ;
35513579 }
35523580
3553- // Check for missing fields. The osId field must be there, and we
3554- // currently require that the physical id field is specified, also .
3581+ // Check for missing fields. The osId field must be there. The physical
3582+ // id field will be checked later .
35553583 if (threadInfo[num_avail][osIdIndex] == UINT_MAX) {
35563584 CLEANUP_THREAD_INFO;
35573585 *msg_id = kmp_i18n_str_MissingProcField;
35583586 return false ;
35593587 }
3560- if (threadInfo[0 ][pkgIdIndex] == UINT_MAX) {
3561- CLEANUP_THREAD_INFO;
3562- *msg_id = kmp_i18n_str_MissingPhysicalIDField;
3563- return false ;
3564- }
35653588
35663589 // Skip this proc if it is not included in the machine model.
35673590 if (KMP_AFFINITY_CAPABLE () &&
@@ -3591,6 +3614,18 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
35913614 }
35923615 *line = 0 ;
35933616
3617+ // At least on powerpc, Linux may return -1 for physical_package_id. Try
3618+ // to reconstruct topology from core_sibling_list in that case.
3619+ for (i = 0 ; i < num_avail; ++i) {
3620+ if (threadInfo[i][pkgIdIndex] == UINT_MAX) {
3621+ if (!__kmp_package_id_from_core_sibling_list (threadInfo, i)) {
3622+ CLEANUP_THREAD_INFO;
3623+ *msg_id = kmp_i18n_str_MissingPhysicalIDField;
3624+ return false ;
3625+ }
3626+ }
3627+ }
3628+
35943629#if KMP_MIC && REDUCE_TEAM_SIZE
35953630 unsigned teamSize = 0 ;
35963631#endif // KMP_MIC && REDUCE_TEAM_SIZE
0 commit comments