xref: /llvm-project/openmp/runtime/test/affinity/kmp-abs-hw-subset.c (revision eeaaf33fc296d52a28252ba0d6cfe187b7b3412f)
1 // RUN: %libomp-compile -D_GNU_SOURCE
2 // RUN: env OMP_PLACES=threads %libomp-run 1 0
3 // RUN: env OMP_PLACES=threads %libomp-run 1 1
4 // RUN: env OMP_PLACES=threads %libomp-run 2 1
5 // RUN: env OMP_PLACES=threads %libomp-run 2 2
6 // RUN: env OMP_PLACES=threads %libomp-run 3 1
7 // RUN: env OMP_PLACES=threads %libomp-run 3 2
8 // REQUIRES: linux
9 //
10 // The test requires topologies with sockets, cores, threads layers where
11 // the socket layer contains multiple threads.
12 // The s390x architecture does not produce this topology and seems to have
13 // one thread per socket.
14 // UNSUPPORTED: s390x-target-arch
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include "libomp_test_affinity.h"
20 #include "libomp_test_topology.h"
21 
22 // Check openmp place list to make sure it follow KMP_HW_SUBSET restriction
compare_abs_hw_subset_places(const place_list_t * openmp_places,int nthreads,int offset)23 static int compare_abs_hw_subset_places(const place_list_t *openmp_places,
24                                         int nthreads, int offset) {
25   int i, j, expected_per_place;
26   if (openmp_places->num_places != nthreads) {
27     fprintf(
28         stderr,
29         "error: KMP_HW_SUBSET did not restrict the thread resource layer!\n");
30     printf("openmp_places places:\n");
31     topology_print_places(openmp_places);
32     printf("\n");
33     return EXIT_FAILURE;
34   }
35   for (i = 0; i < openmp_places->num_places; ++i) {
36     int count = affinity_mask_count(openmp_places->masks[i]);
37     if (count != 1) {
38       fprintf(stderr, "error: place %d has %d OS procs instead of %d\n", i,
39               count, expected_per_place);
40       return EXIT_FAILURE;
41     }
42   }
43   return EXIT_SUCCESS;
44 }
45 
check_places(int nthreads,int offset)46 static int check_places(int nthreads, int offset) {
47   char buf[100];
48   topology_obj_type_t type;
49   const char *value;
50   int status = EXIT_SUCCESS;
51   place_list_t *threads, *openmp_places;
52   threads = topology_alloc_type_places(TOPOLOGY_OBJ_THREAD);
53 
54   if (threads->num_places <= 1) {
55     printf("Only one hardware thread to execute on. Skipping test.\n");
56     return status;
57   }
58 
59   if (nthreads + offset > threads->num_places) {
60     printf("Only %d total hardware threads to execute on. Skipping test with "
61            "nthreads=%d and offset=%d (too big).\n",
62            threads->num_places, nthreads, offset);
63     return status;
64   }
65 
66   value = getenv("OMP_PLACES");
67   if (!value) {
68     fprintf(stderr, "error: OMP_PLACES must be set to threads!\n");
69     return EXIT_FAILURE;
70   }
71 
72   snprintf(buf, sizeof(buf), ":1s,%dt@%d", nthreads, offset);
73   setenv("KMP_HW_SUBSET", buf, 1);
74 
75   openmp_places = topology_alloc_openmp_places();
76   status = compare_abs_hw_subset_places(openmp_places, nthreads, offset);
77   topology_free_places(threads);
78   topology_free_places(openmp_places);
79   return status;
80 }
81 
main(int argc,char ** argv)82 int main(int argc, char **argv) {
83   int offset = 0;
84   int nthreads = 1;
85 
86   if (!topology_using_full_mask()) {
87     printf("Thread does not have access to all logical processors. Skipping "
88            "test.\n");
89     return EXIT_SUCCESS;
90   }
91 
92   if (argc != 3) {
93     fprintf(stderr, "usage: %s <nthreads> <offset>\n", argv[0]);
94     return EXIT_FAILURE;
95   }
96 
97   nthreads = atoi(argv[1]);
98   offset = atoi(argv[2]);
99 
100   return check_places(nthreads, offset);
101 }
102