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