1 | // RUN: %libomp-compile-and-run |
2 | |
3 | #include <stdio.h> |
4 | #include <stdlib.h> |
5 | #include <string.h> |
6 | #include <omp.h> |
7 | |
8 | #define XSTR(x) #x |
9 | #define STR(x) XSTR(x) |
10 | |
11 | #define streqls(s1, s2) (!strcmp(s1, s2)) |
12 | |
13 | #define check(condition) \ |
14 | if (!(condition)) { \ |
15 | fprintf(stderr, "error: %s: %d: " STR(condition) "\n", __FILE__, \ |
16 | __LINE__); \ |
17 | exit(1); \ |
18 | } |
19 | |
20 | #if defined(_WIN32) |
21 | #include <windows.h> |
22 | #include <process.h> |
23 | #define getpid _getpid |
24 | #ifndef __MINGW32__ |
25 | typedef int pid_t; |
26 | #endif |
27 | #define gettid GetCurrentThreadId |
28 | #define my_gethostname(buf, sz) GetComputerNameA(buf, &(sz)) |
29 | #else |
30 | #include <unistd.h> |
31 | #include <sys/types.h> |
32 | #define my_gethostname(buf, sz) gethostname(buf, sz) |
33 | #endif |
34 | |
35 | #define BUFFER_SIZE 256 |
36 | |
37 | int get_integer() { |
38 | int n, retval; |
39 | char buf[BUFFER_SIZE]; |
40 | size_t needed = omp_capture_affinity(buf, BUFFER_SIZE, NULL); |
41 | check(needed < BUFFER_SIZE); |
42 | n = sscanf(s: buf, format: "%d" , &retval); |
43 | check(n == 1); |
44 | return retval; |
45 | } |
46 | |
47 | char* get_string() { |
48 | int n, retval; |
49 | char buf[BUFFER_SIZE]; |
50 | size_t needed = omp_capture_affinity(buf, BUFFER_SIZE, NULL); |
51 | check(needed < BUFFER_SIZE); |
52 | return strdup(s: buf); |
53 | } |
54 | |
55 | void check_integer(const char* formats[2], int(*func)()) { |
56 | int i; |
57 | for (i = 0; i < 2; ++i) { |
58 | omp_set_affinity_format(formats[i]); |
59 | #pragma omp parallel num_threads(8) |
60 | { |
61 | check(get_integer() == func()); |
62 | #pragma omp parallel num_threads(3) |
63 | { |
64 | check(get_integer() == func()); |
65 | } |
66 | check(get_integer() == func()); |
67 | } |
68 | } |
69 | } |
70 | |
71 | void check_nesting_level() { |
72 | // Check %{nesting_level} and %L |
73 | const char* formats[2] = {"%{nesting_level}" , "%L" }; |
74 | check_integer(formats, omp_get_level); |
75 | } |
76 | |
77 | void check_thread_num() { |
78 | // Check %{thread_num} and %n |
79 | const char* formats[2] = {"%{thread_num}" , "%n" }; |
80 | check_integer(formats, omp_get_thread_num); |
81 | } |
82 | |
83 | void check_num_threads() { |
84 | // Check %{num_threads} and %N |
85 | const char* formats[2] = {"%{num_threads}" , "%N" }; |
86 | check_integer(formats, omp_get_num_threads); |
87 | } |
88 | |
89 | int ancestor_helper() { |
90 | return omp_get_ancestor_thread_num(omp_get_level() - 1); |
91 | } |
92 | void check_ancestor_tnum() { |
93 | // Check %{ancestor_tnum} and %a |
94 | const char* formats[2] = {"%{ancestor_tnum}" , "%a" }; |
95 | check_integer(formats, func: ancestor_helper); |
96 | } |
97 | |
98 | int my_get_pid() { return (int)getpid(); } |
99 | void check_process_id() { |
100 | // Check %{process_id} and %P |
101 | const char* formats[2] = {"%{process_id}" , "%P" }; |
102 | check_integer(formats, func: my_get_pid); |
103 | } |
104 | |
105 | /* |
106 | int my_get_tid() { return (int)gettid(); } |
107 | void check_native_thread_id() { |
108 | // Check %{native_thread_id} and %i |
109 | const char* formats[2] = {"%{native_thread_id}", "%i"}; |
110 | check_integer(formats, my_get_tid); |
111 | } |
112 | */ |
113 | |
114 | void check_host() { |
115 | int i; |
116 | int buffer_size = 256; |
117 | const char* formats[2] = {"%{host}" , "%H" }; |
118 | char hostname[256]; |
119 | my_gethostname(hostname, buffer_size); |
120 | for (i = 0; i < 2; ++i) { |
121 | omp_set_affinity_format(formats[i]); |
122 | #pragma omp parallel num_threads(8) |
123 | { |
124 | char* host = get_string(); |
125 | check(streqls(host, hostname)); |
126 | free(ptr: host); |
127 | } |
128 | } |
129 | } |
130 | |
131 | void check_undefined() { |
132 | int i; |
133 | const char* formats[2] = {"%{foobar}" , "%X" }; |
134 | for (i = 0; i < 2; ++i) { |
135 | omp_set_affinity_format(formats[i]); |
136 | #pragma omp parallel num_threads(8) |
137 | { |
138 | char* undef = get_string(); |
139 | check(streqls(undef, "undefined" )); |
140 | free(ptr: undef); |
141 | } |
142 | } |
143 | } |
144 | |
145 | int main(int argc, char** argv) { |
146 | omp_set_nested(1); |
147 | check_nesting_level(); |
148 | check_num_threads(); |
149 | check_ancestor_tnum(); |
150 | check_process_id(); |
151 | //check_native_thread_id(); |
152 | check_host(); |
153 | check_undefined(); |
154 | return 0; |
155 | } |
156 | |