@@ -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,37 @@ static inline const char *__kmp_cpuinfo_get_envvar() {
3175
3179
return envvar;
3176
3180
}
3177
3181
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
+
3178
3213
// Parse /proc/cpuinfo (or an alternate file in the same format) to obtain the
3179
3214
// affinity map. On AIX, the map is obtained through system SRAD (Scheduler
3180
3215
// Resource Allocation Domain).
@@ -3550,18 +3585,13 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
3550
3585
return false ;
3551
3586
}
3552
3587
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 .
3555
3590
if (threadInfo[num_avail][osIdIndex] == UINT_MAX) {
3556
3591
CLEANUP_THREAD_INFO;
3557
3592
*msg_id = kmp_i18n_str_MissingProcField;
3558
3593
return false ;
3559
3594
}
3560
- if (threadInfo[0 ][pkgIdIndex] == UINT_MAX) {
3561
- CLEANUP_THREAD_INFO;
3562
- *msg_id = kmp_i18n_str_MissingPhysicalIDField;
3563
- return false ;
3564
- }
3565
3595
3566
3596
// Skip this proc if it is not included in the machine model.
3567
3597
if (KMP_AFFINITY_CAPABLE () &&
@@ -3591,6 +3621,18 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
3591
3621
}
3592
3622
*line = 0 ;
3593
3623
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
+
3594
3636
#if KMP_MIC && REDUCE_TEAM_SIZE
3595
3637
unsigned teamSize = 0 ;
3596
3638
#endif // KMP_MIC && REDUCE_TEAM_SIZE
0 commit comments