1 // RUN: %libomp-compile && env LIBOMP_NUM_HIDDEN_HELPER_THREADS=0 OMP_PROC_BIND=close OMP_PLACES=cores KMP_AFFINITY=verbose %libomp-run 8 1 4
4 // This test pthread_creates 8 root threads before any OpenMP
5 // runtime entry is ever called. We have all the root threads
6 // register with the runtime by calling omp_set_num_threads(),
7 // but this does not initialize their affinity. The fourth root thread
8 // then calls a parallel region and we make sure its affinity
9 // is correct. We also make sure all the other root threads are
10 // free-floating since they have not called into a parallel region.
19 #include <sys/types.h>
20 #include <sys/syscall.h>
21 #include "libomp_test_affinity.h"
23 volatile int entry_flag
= 0;
24 volatile int flag
= 0;
25 volatile int num_roots_arrived
= 0;
29 int register_workers
= 0; // boolean
30 affinity_mask_t
*full_mask
;
32 int __kmpc_global_thread_num(void*);
34 int get_os_thread_id() {
35 return (int)syscall(SYS_gettid
);
38 int place_and_affinity_match() {
41 affinity_mask_t
*mask
= affinity_mask_alloc();
42 int place
= omp_get_place_num();
43 int num_procs
= omp_get_place_num_procs(place
);
44 int *ids
= (int*)malloc(sizeof(int) * num_procs
);
45 omp_get_place_proc_ids(place
, ids
);
46 get_thread_affinity(mask
);
47 affinity_mask_snprintf(buf
, sizeof(buf
), mask
);
48 printf("Primary Thread Place: %d\n", place
);
49 printf("Primary Thread mask: %s\n", buf
);
51 for (i
= 0; i
< num_procs
; ++i
) {
53 if (!affinity_mask_isset(mask
, cpu
))
57 max_cpu
= AFFINITY_MAX_CPUS
;
58 for (i
= 0; i
< max_cpu
; ++i
) {
60 if (affinity_mask_isset(mask
, cpu
)) {
62 for (j
= 0; j
< num_procs
; ++j
) {
73 affinity_mask_free(mask
);
78 void* thread_func(void *arg
) {
80 int root_id
= *((int*)arg
);
82 int tid
= get_os_thread_id();
84 // Order how the root threads are assigned a gtid in the runtime
85 // i.e., root_id = gtid
92 // If main root thread
93 if (root_id
== spawner
) {
94 printf("Initial application thread (pid=%d, tid=%d, spawner=%d) reached thread_func (will call OpenMP)\n", pid
, tid
, spawner
);
95 omp_set_num_threads(4);
98 // Wait for the workers to signal their arrival before #pragma omp parallel
99 while (num_roots_arrived
< num_roots
- 1) {}
100 // This will trigger the output for KMP_AFFINITY in this case
103 int gtid
= __kmpc_global_thread_num(NULL
);
106 printf("Exactly %d threads in the #pragma omp parallel\n",
107 omp_get_num_threads());
111 printf("OpenMP thread %d: gtid=%d\n", omp_get_thread_num(), gtid
);
115 if (!place_and_affinity_match()) {
116 fprintf(stderr
, "error: place and affinity mask do not match for primary thread\n");
120 } else { // If worker root thread
121 // Worker root threads, register with OpenMP through omp_set_num_threads()
122 // if designated to, signal their arrival and then wait for the main root
123 // thread to signal them to exit.
124 printf("New root pthread (pid=%d, tid=%d) reached thread_func\n", pid
, tid
);
125 if (register_workers
)
126 omp_set_num_threads(4);
130 pthread_mutex_lock(&lock
);
132 pthread_mutex_unlock(&lock
);
135 // Main check whether root threads' mask is equal to the
136 // initial affinity mask
137 affinity_mask_t
*mask
= affinity_mask_alloc();
138 get_thread_affinity(mask
);
139 if (!affinity_mask_equal(mask
, full_mask
)) {
141 printf("root thread %d mask: ", root_id
);
142 affinity_mask_snprintf(buf
, sizeof(buf
), mask
);
143 printf("initial affinity mask: %s\n", buf
);
144 fprintf(stderr
, "error: root thread %d affinity mask not equal"
145 " to initial full mask\n", root_id
);
146 affinity_mask_free(mask
);
149 affinity_mask_free(mask
);
154 int main(int argc
, char** argv
) {
156 if (argc
!= 3 && argc
!= 4) {
157 fprintf(stderr
, "usage: %s <num_roots> <register_workers_bool> [<spawn_root_number>]\n", argv
[0]);
161 // Initialize pthread mutex
162 pthread_mutex_init(&lock
, NULL
);
164 // Get initial full mask
165 full_mask
= affinity_mask_alloc();
166 get_thread_affinity(full_mask
);
168 // Get the number of root pthreads to create and allocate resources for them
169 num_roots
= atoi(argv
[1]);
170 pthread_t
*roots
= (pthread_t
*)malloc(sizeof(pthread_t
) * num_roots
);
171 int *root_ids
= (int*)malloc(sizeof(int) * num_roots
);
173 // Get the flag indicating whether to have root pthreads call omp_set_num_threads() or not
174 register_workers
= atoi(argv
[2]);
177 spawner
= atoi(argv
[3]);
179 // Spawn worker root threads
180 for (i
= 1; i
< num_roots
; ++i
) {
182 pthread_create(roots
+ i
, NULL
, thread_func
, root_ids
+ i
);
184 // Have main root thread (root 0) go into thread_func
186 thread_func(root_ids
);
188 // Cleanup all resources
189 for (i
= 1; i
< num_roots
; ++i
) {
191 pthread_join(roots
[i
], &status
);
195 pthread_mutex_destroy(&lock
);