1 // RUN: %libomp-compile -D_GNU_SOURCE
2 // RUN: env OMP_PLACES=threads %libomp-run
3 // RUN: env OMP_PLACES=cores %libomp-run
4 // RUN: env OMP_PLACES=sockets %libomp-run
5 // REQUIRES: linux
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "libomp_test_affinity.h"
11 #include "libomp_test_topology.h"
12
13 // Check openmp place list to make sure it follow KMP_HW_SUBSET restriction
compare_hw_subset_places(const place_list_t * openmp_places,topology_obj_type_t type,int nsockets,int ncores_per_socket,int nthreads_per_core)14 static int compare_hw_subset_places(const place_list_t *openmp_places,
15 topology_obj_type_t type, int nsockets,
16 int ncores_per_socket,
17 int nthreads_per_core) {
18 int i, j, expected_total, expected_per_place;
19 if (type == TOPOLOGY_OBJ_THREAD) {
20 expected_total = nsockets * ncores_per_socket * nthreads_per_core;
21 expected_per_place = 1;
22 } else if (type == TOPOLOGY_OBJ_CORE) {
23 expected_total = nsockets * ncores_per_socket;
24 expected_per_place = nthreads_per_core;
25 } else {
26 expected_total = nsockets;
27 expected_per_place = ncores_per_socket;
28 }
29 if (openmp_places->num_places != expected_total) {
30 fprintf(stderr, "error: KMP_HW_SUBSET did not half each resource layer!\n");
31 printf("openmp_places places:\n");
32 topology_print_places(openmp_places);
33 printf("\n");
34 return EXIT_FAILURE;
35 }
36 for (i = 0; i < openmp_places->num_places; ++i) {
37 int count = affinity_mask_count(openmp_places->masks[i]);
38 if (count != expected_per_place) {
39 fprintf(stderr, "error: place %d has %d OS procs instead of %d\n", i,
40 count, expected_per_place);
41 return EXIT_FAILURE;
42 }
43 }
44 return EXIT_SUCCESS;
45 }
46
check_places()47 static int check_places() {
48 char buf[100];
49 topology_obj_type_t type;
50 const char *value;
51 int status = EXIT_SUCCESS;
52 place_list_t *threads, *cores, *sockets, *openmp_places;
53 threads = topology_alloc_type_places(TOPOLOGY_OBJ_THREAD);
54 cores = topology_alloc_type_places(TOPOLOGY_OBJ_CORE);
55 sockets = topology_alloc_type_places(TOPOLOGY_OBJ_SOCKET);
56
57 if (threads->num_places <= 1) {
58 printf("Only one hardware thread to execute on. Skipping test.\n");
59 return status;
60 }
61
62 value = getenv("OMP_PLACES");
63 if (!value) {
64 fprintf(stderr,
65 "error: OMP_PLACES must be set to one of threads,cores,sockets!\n");
66 return EXIT_FAILURE;
67 }
68 if (strcmp(value, "threads") == 0)
69 type = TOPOLOGY_OBJ_THREAD;
70 else if (strcmp(value, "cores") == 0)
71 type = TOPOLOGY_OBJ_CORE;
72 else if (strcmp(value, "sockets") == 0)
73 type = TOPOLOGY_OBJ_SOCKET;
74 else {
75 fprintf(stderr,
76 "error: OMP_PLACES must be one of threads,cores,sockets!\n");
77 return EXIT_FAILURE;
78 }
79
80 // Calculate of num threads per core, num cores per socket, & num sockets
81 if (cores->num_places <= 0) {
82 printf("Invalid number of cores (%d). Skipping test.\n", cores->num_places);
83 return status;
84 } else if (sockets->num_places <= 0) {
85 printf("Invalid number of sockets (%d). Skipping test.\n",
86 cores->num_places);
87 return status;
88 }
89 int nthreads_per_core = threads->num_places / cores->num_places;
90 int ncores_per_socket = cores->num_places / sockets->num_places;
91 int nsockets = sockets->num_places;
92
93 if (nsockets * ncores_per_socket * nthreads_per_core != threads->num_places) {
94 printf("Only uniform topologies can be tested. Skipping test.\n");
95 return status;
96 }
97
98 // Use half the resources of every level
99 if (nthreads_per_core > 1)
100 nthreads_per_core /= 2;
101 if (ncores_per_socket > 1)
102 ncores_per_socket /= 2;
103 if (nsockets > 1)
104 nsockets /= 2;
105
106 snprintf(buf, sizeof(buf), "%ds,%dc,%dt", nsockets, ncores_per_socket,
107 nthreads_per_core);
108 setenv("KMP_HW_SUBSET", buf, 1);
109
110 openmp_places = topology_alloc_openmp_places();
111 status = compare_hw_subset_places(openmp_places, type, nsockets,
112 ncores_per_socket, nthreads_per_core);
113 topology_free_places(threads);
114 topology_free_places(cores);
115 topology_free_places(sockets);
116 topology_free_places(openmp_places);
117 return status;
118 }
119
main()120 int main() {
121 if (!topology_using_full_mask()) {
122 printf("Thread does not have access to all logical processors. Skipping "
123 "test.\n");
124 return EXIT_SUCCESS;
125 }
126 return check_places();
127 }
128