| 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 | |