@@ -2906,12 +2906,17 @@ static inline const char *__kmp_cpuinfo_get_envvar() {
2906
2906
}
2907
2907
2908
2908
// Parse /proc/cpuinfo (or an alternate file in the same format) to obtain the
2909
- // affinity map.
2909
+ // affinity map. On AIX, the map is obtained through system SRAD (Scheduler
2910
+ // Resource Allocation Domain).
2910
2911
static bool __kmp_affinity_create_cpuinfo_map (int *line,
2911
2912
kmp_i18n_id_t *const msg_id) {
2913
+ *msg_id = kmp_i18n_null;
2914
+
2915
+ #if KMP_OS_AIX
2916
+ unsigned num_records = __kmp_xproc;
2917
+ #else
2912
2918
const char *filename = __kmp_cpuinfo_get_filename ();
2913
2919
const char *envvar = __kmp_cpuinfo_get_envvar ();
2914
- *msg_id = kmp_i18n_null;
2915
2920
2916
2921
if (__kmp_affinity.flags .verbose ) {
2917
2922
KMP_INFORM (AffParseFilename, " KMP_AFFINITY" , filename);
@@ -2970,6 +2975,7 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
2970
2975
*msg_id = kmp_i18n_str_CantRewindCpuinfo;
2971
2976
return false ;
2972
2977
}
2978
+ #endif // KMP_OS_AIX
2973
2979
2974
2980
// Allocate the array of records to store the proc info in. The dummy
2975
2981
// element at the end makes the logic in filling them out easier to code.
@@ -2999,6 +3005,99 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
2999
3005
INIT_PROC_INFO (threadInfo[i]);
3000
3006
}
3001
3007
3008
+ #if KMP_OS_AIX
3009
+ int smt_threads;
3010
+ lpar_info_format1_t cpuinfo;
3011
+ unsigned num_avail = __kmp_xproc;
3012
+
3013
+ if (__kmp_affinity.flags .verbose )
3014
+ KMP_INFORM (AffParseFilename, " KMP_AFFINITY" , " system info for topology" );
3015
+
3016
+ // Get the number of SMT threads per core.
3017
+ int retval =
3018
+ lpar_get_info (LPAR_INFO_FORMAT1, &cpuinfo, sizeof (lpar_info_format1_t ));
3019
+ if (!retval)
3020
+ smt_threads = cpuinfo.smt_threads ;
3021
+ else {
3022
+ CLEANUP_THREAD_INFO;
3023
+ *msg_id = kmp_i18n_str_UnknownTopology;
3024
+ return false ;
3025
+ }
3026
+
3027
+ // Allocate a resource set containing available system resourses.
3028
+ rsethandle_t sys_rset = rs_alloc (RS_SYSTEM);
3029
+ if (sys_rset == NULL ) {
3030
+ CLEANUP_THREAD_INFO;
3031
+ *msg_id = kmp_i18n_str_UnknownTopology;
3032
+ return false ;
3033
+ }
3034
+ // Allocate a resource set for the SRAD info.
3035
+ rsethandle_t srad = rs_alloc (RS_EMPTY);
3036
+ if (srad == NULL ) {
3037
+ rs_free (sys_rset);
3038
+ CLEANUP_THREAD_INFO;
3039
+ *msg_id = kmp_i18n_str_UnknownTopology;
3040
+ return false ;
3041
+ }
3042
+
3043
+ // Get the SRAD system detail level.
3044
+ int sradsdl = rs_getinfo (NULL , R_SRADSDL, 0 );
3045
+ if (sradsdl < 0 ) {
3046
+ rs_free (sys_rset);
3047
+ rs_free (srad);
3048
+ CLEANUP_THREAD_INFO;
3049
+ *msg_id = kmp_i18n_str_UnknownTopology;
3050
+ return false ;
3051
+ }
3052
+ // Get the number of RADs at that SRAD SDL.
3053
+ int num_rads = rs_numrads (sys_rset, sradsdl, 0 );
3054
+ if (num_rads < 0 ) {
3055
+ rs_free (sys_rset);
3056
+ rs_free (srad);
3057
+ CLEANUP_THREAD_INFO;
3058
+ *msg_id = kmp_i18n_str_UnknownTopology;
3059
+ return false ;
3060
+ }
3061
+
3062
+ // Get the maximum number of procs that may be contained in a resource set.
3063
+ int max_procs = rs_getinfo (NULL , R_MAXPROCS, 0 );
3064
+ if (max_procs < 0 ) {
3065
+ rs_free (sys_rset);
3066
+ rs_free (srad);
3067
+ CLEANUP_THREAD_INFO;
3068
+ *msg_id = kmp_i18n_str_UnknownTopology;
3069
+ return false ;
3070
+ }
3071
+
3072
+ int cur_rad = 0 ;
3073
+ int num_set = 0 ;
3074
+ for (int srad_idx = 0 ; cur_rad < num_rads && srad_idx < VMI_MAXRADS;
3075
+ ++srad_idx) {
3076
+ // Check if the SRAD is available in the RSET.
3077
+ if (rs_getrad (sys_rset, srad, sradsdl, srad_idx, 0 ) < 0 )
3078
+ continue ;
3079
+
3080
+ for (int cpu = 0 ; cpu < max_procs; cpu++) {
3081
+ // Set the info for the cpu if it is in the SRAD.
3082
+ if (rs_op (RS_TESTRESOURCE, srad, NULL , R_PROCS, cpu)) {
3083
+ threadInfo[cpu][osIdIndex] = cpu;
3084
+ threadInfo[cpu][pkgIdIndex] = cur_rad;
3085
+ threadInfo[cpu][coreIdIndex] = cpu / smt_threads;
3086
+ ++num_set;
3087
+ if (num_set >= num_avail) {
3088
+ // Done if all available CPUs have been set.
3089
+ break ;
3090
+ }
3091
+ }
3092
+ }
3093
+ ++cur_rad;
3094
+ }
3095
+ rs_free (sys_rset);
3096
+ rs_free (srad);
3097
+
3098
+ // The topology is already sorted.
3099
+
3100
+ #else // !KMP_OS_AIX
3002
3101
unsigned num_avail = 0 ;
3003
3102
*line = 0 ;
3004
3103
#if KMP_ARCH_S390X
@@ -3246,6 +3345,8 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
3246
3345
qsort (threadInfo, num_avail, sizeof (*threadInfo),
3247
3346
__kmp_affinity_cmp_ProcCpuInfo_phys_id);
3248
3347
3348
+ #endif // KMP_OS_AIX
3349
+
3249
3350
// The table is now sorted by pkgId / coreId / threadId, but we really don't
3250
3351
// know the radix of any of the fields. pkgId's may be sparsely assigned among
3251
3352
// the chips on a system. Although coreId's are usually assigned
@@ -4441,7 +4542,7 @@ static bool __kmp_aux_affinity_initialize_topology(kmp_affinity_t &affinity) {
4441
4542
}
4442
4543
#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
4443
4544
4444
- #if KMP_OS_LINUX
4545
+ #if KMP_OS_LINUX || KMP_OS_AIX
4445
4546
if (!success) {
4446
4547
int line = 0 ;
4447
4548
success = __kmp_affinity_create_cpuinfo_map (&line, &msg_id);
@@ -4837,7 +4938,12 @@ void __kmp_affinity_uninitialize(void) {
4837
4938
}
4838
4939
if (__kmp_affin_origMask != NULL ) {
4839
4940
if (KMP_AFFINITY_CAPABLE ()) {
4941
+ #if KMP_OS_AIX
4942
+ // Uninitialize by unbinding the thread.
4943
+ bindprocessor (BINDTHREAD, thread_self (), PROCESSOR_CLASS_ANY);
4944
+ #else
4840
4945
__kmp_set_system_affinity (__kmp_affin_origMask, FALSE );
4946
+ #endif
4841
4947
}
4842
4948
KMP_CPU_FREE (__kmp_affin_origMask);
4843
4949
__kmp_affin_origMask = NULL ;
@@ -5011,7 +5117,10 @@ void __kmp_affinity_bind_init_mask(int gtid) {
5011
5117
__kmp_set_system_affinity (th->th .th_affin_mask , FALSE );
5012
5118
} else
5013
5119
#endif
5120
+ #ifndef KMP_OS_AIX
5121
+ // Do not set the full mask as the init mask on AIX.
5014
5122
__kmp_set_system_affinity (th->th .th_affin_mask , TRUE );
5123
+ #endif
5015
5124
}
5016
5125
5017
5126
void __kmp_affinity_bind_place (int gtid) {
@@ -5124,15 +5233,15 @@ int __kmp_aux_set_affinity(void **mask) {
5124
5233
int __kmp_aux_get_affinity (void **mask) {
5125
5234
int gtid;
5126
5235
int retval;
5127
- #if KMP_OS_WINDOWS || KMP_DEBUG
5236
+ #if KMP_OS_WINDOWS || KMP_OS_AIX || KMP_DEBUG
5128
5237
kmp_info_t *th;
5129
5238
#endif
5130
5239
if (!KMP_AFFINITY_CAPABLE ()) {
5131
5240
return -1 ;
5132
5241
}
5133
5242
5134
5243
gtid = __kmp_entry_gtid ();
5135
- #if KMP_OS_WINDOWS || KMP_DEBUG
5244
+ #if KMP_OS_WINDOWS || KMP_OS_AIX || KMP_DEBUG
5136
5245
th = __kmp_threads[gtid];
5137
5246
#else
5138
5247
(void )gtid; // unused variable
@@ -5155,7 +5264,7 @@ int __kmp_aux_get_affinity(void **mask) {
5155
5264
}
5156
5265
}
5157
5266
5158
- #if !KMP_OS_WINDOWS
5267
+ #if !KMP_OS_WINDOWS && !KMP_OS_AIX
5159
5268
5160
5269
retval = __kmp_get_system_affinity ((kmp_affin_mask_t *)(*mask), FALSE );
5161
5270
KA_TRACE (
@@ -5175,7 +5284,7 @@ int __kmp_aux_get_affinity(void **mask) {
5175
5284
KMP_CPU_COPY ((kmp_affin_mask_t *)(*mask), th->th .th_affin_mask );
5176
5285
return 0 ;
5177
5286
5178
- #endif /* KMP_OS_WINDOWS */
5287
+ #endif /* ! KMP_OS_WINDOWS && !KMP_OS_AIX */
5179
5288
}
5180
5289
5181
5290
int __kmp_aux_get_affinity_max_proc () {
@@ -5557,7 +5666,7 @@ void __kmp_balanced_affinity(kmp_info_t *th, int nthreads) {
5557
5666
}
5558
5667
}
5559
5668
5560
- #if KMP_OS_LINUX || KMP_OS_FREEBSD
5669
+ #if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_AIX
5561
5670
// We don't need this entry for Windows because
5562
5671
// there is GetProcessAffinityMask() api
5563
5672
//
@@ -5592,7 +5701,11 @@ extern "C"
5592
5701
" set full mask for thread %d\n " ,
5593
5702
gtid));
5594
5703
KMP_DEBUG_ASSERT (__kmp_affin_fullMask != NULL );
5704
+ #if KMP_OS_AIX
5705
+ return bindprocessor (BINDTHREAD, thread_self (), PROCESSOR_CLASS_ANY);
5706
+ #else
5595
5707
return __kmp_set_system_affinity (__kmp_affin_fullMask, FALSE );
5708
+ #endif
5596
5709
}
5597
5710
#endif
5598
5711
0 commit comments