@@ -145,13 +145,144 @@ static int topology_using_full_mask() {
145145 return has_all ;
146146}
147147
148+ // Read a single integer from a sysfs file. Returns 0 on success, -1 on error.
149+ static int topology_read_int_from_file (const char * path , int * value ) {
150+ FILE * f = fopen (path , "r" );
151+ if (!f )
152+ return -1 ;
153+ int n = fscanf (f , "%d" , value );
154+ fclose (f );
155+ return (n == 1 ) ? 0 : -1 ;
156+ }
157+
158+ // On non-x86 Linux, the OpenMP runtime reads core_id and physical_package_id
159+ // from sysfs to determine topology. Use the same method in the test so that
160+ // the test's view of the topology matches the runtime's view.
161+ // On x86/x86_64 (or when sysfs id files are unavailable), fall back to the
162+ // siblings-list approach.
163+ static int topology_use_sysfs_ids () {
164+ #if defined(__i386__ ) || defined(__x86_64__ )
165+ return 0 ;
166+ #else
167+ // Check whether the sysfs id files exist for cpu0
168+ int dummy ;
169+ if (topology_read_int_from_file (
170+ "/sys/devices/system/cpu/cpu0/topology/core_id" , & dummy ) == 0 &&
171+ topology_read_int_from_file (
172+ "/sys/devices/system/cpu/cpu0/topology/physical_package_id" ,
173+ & dummy ) == 0 )
174+ return 1 ;
175+ return 0 ;
176+ #endif
177+ }
178+
179+ // Build place list using core_id / physical_package_id from sysfs,
180+ // matching what the OpenMP runtime does on non-x86 Linux.
181+ static place_list_t * topology_alloc_type_places_sysfs (topology_obj_type_t type ,
182+ int num_cpus ) {
183+ char buf [1024 ];
184+ int i , cpu , num_unique ;
185+ int * place_nums ;
186+ place_list_t * places = (place_list_t * )malloc (sizeof (place_list_t ));
187+ affinity_mask_t * * masks =
188+ (affinity_mask_t * * )malloc (sizeof (affinity_mask_t * ) * num_cpus );
189+
190+ // Read per-cpu core_id and physical_package_id
191+ int * core_ids = (int * )malloc (sizeof (int ) * num_cpus );
192+ int * pkg_ids = (int * )malloc (sizeof (int ) * num_cpus );
193+ for (cpu = 0 ; cpu < num_cpus ; ++ cpu ) {
194+ snprintf (buf , sizeof (buf ),
195+ "/sys/devices/system/cpu/cpu%d/topology/core_id" , cpu );
196+ if (topology_read_int_from_file (buf , & core_ids [cpu ]) != 0 )
197+ core_ids [cpu ] = cpu ;
198+ snprintf (buf , sizeof (buf ),
199+ "/sys/devices/system/cpu/cpu%d/topology/physical_package_id" , cpu );
200+ if (topology_read_int_from_file (buf , & pkg_ids [cpu ]) != 0 )
201+ pkg_ids [cpu ] = 0 ;
202+ }
203+
204+ num_unique = 0 ;
205+ if (type == TOPOLOGY_OBJ_THREAD ) {
206+ for (cpu = 0 ; cpu < num_cpus ; ++ cpu ) {
207+ affinity_mask_t * mask = affinity_mask_alloc ();
208+ affinity_mask_set (mask , cpu );
209+ masks [num_unique ++ ] = mask ;
210+ }
211+ } else if (type == TOPOLOGY_OBJ_CORE ) {
212+ // Group CPUs with same (physical_package_id, core_id) into one place
213+ for (cpu = 0 ; cpu < num_cpus ; ++ cpu ) {
214+ int found = 0 ;
215+ for (i = 0 ; i < num_unique ; ++ i ) {
216+ // Find a cpu already in this group to compare ids
217+ int rep ;
218+ for (rep = 0 ; rep < num_cpus ; ++ rep ) {
219+ if (affinity_mask_isset (masks [i ], rep ))
220+ break ;
221+ }
222+ if (rep < num_cpus && pkg_ids [rep ] == pkg_ids [cpu ] &&
223+ core_ids [rep ] == core_ids [cpu ]) {
224+ affinity_mask_set (masks [i ], cpu );
225+ found = 1 ;
226+ break ;
227+ }
228+ }
229+ if (!found ) {
230+ affinity_mask_t * mask = affinity_mask_alloc ();
231+ affinity_mask_set (mask , cpu );
232+ masks [num_unique ++ ] = mask ;
233+ }
234+ }
235+ } else if (type == TOPOLOGY_OBJ_SOCKET ) {
236+ // Group CPUs with same physical_package_id into one place
237+ for (cpu = 0 ; cpu < num_cpus ; ++ cpu ) {
238+ int found = 0 ;
239+ for (i = 0 ; i < num_unique ; ++ i ) {
240+ int rep ;
241+ for (rep = 0 ; rep < num_cpus ; ++ rep ) {
242+ if (affinity_mask_isset (masks [i ], rep ))
243+ break ;
244+ }
245+ if (rep < num_cpus && pkg_ids [rep ] == pkg_ids [cpu ]) {
246+ affinity_mask_set (masks [i ], cpu );
247+ found = 1 ;
248+ break ;
249+ }
250+ }
251+ if (!found ) {
252+ affinity_mask_t * mask = affinity_mask_alloc ();
253+ affinity_mask_set (mask , cpu );
254+ masks [num_unique ++ ] = mask ;
255+ }
256+ }
257+ } else {
258+ fprintf (stderr , "Unknown topology type (%d)\n" , (int )type );
259+ exit (EXIT_FAILURE );
260+ }
261+
262+ free (core_ids );
263+ free (pkg_ids );
264+ place_nums = (int * )malloc (sizeof (int ) * num_unique );
265+ for (i = 0 ; i < num_unique ; ++ i )
266+ place_nums [i ] = i ;
267+ places -> num_places = num_unique ;
268+ places -> masks = masks ;
269+ places -> place_nums = place_nums ;
270+ places -> current_place = -1 ;
271+ return places ;
272+ }
273+
148274// Return array of masks representing OMP_PLACES keyword (e.g., sockets, cores,
149275// threads)
150276static place_list_t * topology_alloc_type_places (topology_obj_type_t type ) {
151277 char buf [1024 ];
152- int i , cpu , num_places , num_unique ;
278+ int i , cpu , num_unique ;
153279 int * place_nums ;
154280 int num_cpus = topology_get_num_cpus ();
281+
282+ // On non-x86 Linux, use core_id/physical_package_id to match the runtime
283+ if (topology_use_sysfs_ids ())
284+ return topology_alloc_type_places_sysfs (type , num_cpus );
285+
155286 place_list_t * places = (place_list_t * )malloc (sizeof (place_list_t ));
156287 affinity_mask_t * * masks =
157288 (affinity_mask_t * * )malloc (sizeof (affinity_mask_t * ) * num_cpus );
0 commit comments