@@ -1589,15 +1589,13 @@ kmp_str_buf_t *__kmp_affinity_str_buf_mask(kmp_str_buf_t *buf,
1589
1589
return buf;
1590
1590
}
1591
1591
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);
1598
1596
#if KMP_OS_LINUX
1599
1597
int n, begin_cpu, end_cpu;
1600
- kmp_safe_raii_file_t offline_file ;
1598
+ kmp_safe_raii_file_t file ;
1601
1599
auto skip_ws = [](FILE *f) {
1602
1600
int c;
1603
1601
do {
@@ -1606,29 +1604,29 @@ kmp_affin_mask_t *__kmp_affinity_get_offline_cpus() {
1606
1604
if (c != EOF)
1607
1605
ungetc (c, f);
1608
1606
};
1609
- // File contains CSV of integer ranges representing the offline CPUs
1607
+ // File contains CSV of integer ranges representing the CPUs
1610
1608
// 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" );
1612
1610
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);
1617
1615
if (n != 1 )
1618
1616
break ;
1619
- skip_ws (offline_file );
1620
- int c = fgetc (offline_file );
1617
+ skip_ws (file );
1618
+ int c = fgetc (file );
1621
1619
if (c == EOF || c == ' ,' ) {
1622
1620
// Just single CPU
1623
1621
end_cpu = begin_cpu;
1624
1622
} else if (c == ' -' ) {
1625
1623
// 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);
1628
1626
if (n != 1 )
1629
1627
break ;
1630
- skip_ws (offline_file );
1631
- c = fgetc (offline_file ); // skip ','
1628
+ skip_ws (file );
1629
+ c = fgetc (file ); // skip ','
1632
1630
} else {
1633
1631
// Syntax problem
1634
1632
break ;
@@ -1638,13 +1636,19 @@ kmp_affin_mask_t *__kmp_affinity_get_offline_cpus() {
1638
1636
end_cpu >= __kmp_xproc || begin_cpu > end_cpu) {
1639
1637
continue ;
1640
1638
}
1641
- // Insert [begin_cpu, end_cpu] into offline mask
1639
+ // Insert [begin_cpu, end_cpu] into mask
1642
1640
for (int cpu = begin_cpu; cpu <= end_cpu; ++cpu) {
1643
- KMP_CPU_SET (cpu, offline );
1641
+ KMP_CPU_SET (cpu, mask );
1644
1642
}
1645
1643
}
1646
1644
#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" );
1648
1652
}
1649
1653
1650
1654
// Return the number of available procs
@@ -3175,6 +3179,30 @@ static inline const char *__kmp_cpuinfo_get_envvar() {
3175
3179
return envvar;
3176
3180
}
3177
3181
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
+
3178
3206
// Parse /proc/cpuinfo (or an alternate file in the same format) to obtain the
3179
3207
// affinity map. On AIX, the map is obtained through system SRAD (Scheduler
3180
3208
// Resource Allocation Domain).
@@ -3550,18 +3578,13 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
3550
3578
return false ;
3551
3579
}
3552
3580
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 .
3555
3583
if (threadInfo[num_avail][osIdIndex] == UINT_MAX) {
3556
3584
CLEANUP_THREAD_INFO;
3557
3585
*msg_id = kmp_i18n_str_MissingProcField;
3558
3586
return false ;
3559
3587
}
3560
- if (threadInfo[0 ][pkgIdIndex] == UINT_MAX) {
3561
- CLEANUP_THREAD_INFO;
3562
- *msg_id = kmp_i18n_str_MissingPhysicalIDField;
3563
- return false ;
3564
- }
3565
3588
3566
3589
// Skip this proc if it is not included in the machine model.
3567
3590
if (KMP_AFFINITY_CAPABLE () &&
@@ -3591,6 +3614,18 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
3591
3614
}
3592
3615
*line = 0 ;
3593
3616
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
+
3594
3629
#if KMP_MIC && REDUCE_TEAM_SIZE
3595
3630
unsigned teamSize = 0 ;
3596
3631
#endif // KMP_MIC && REDUCE_TEAM_SIZE
0 commit comments