// RUN: %libomp-compile-and-run
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define streqls(s1, s2) (!strcmp(s1, s2))
#define check(condition) \
if (!(condition)) { \
fprintf(stderr, "error: %s: %d: " STR(condition) "\n", __FILE__, \
__LINE__); \
exit(1); \
}
#if defined(_WIN32)
#include <windows.h>
#include <process.h>
#define getpid _getpid
#ifndef __MINGW32__
typedef int pid_t;
#endif
#define gettid GetCurrentThreadId
#define my_gethostname(buf, sz) GetComputerNameA(buf, &(sz))
#else
#include <unistd.h>
#include <sys/types.h>
#define my_gethostname(buf, sz) gethostname(buf, sz)
#endif
#define BUFFER_SIZE 256
int get_integer() {
int n, retval;
char buf[BUFFER_SIZE];
size_t needed = omp_capture_affinity(buf, BUFFER_SIZE, NULL);
check(needed < BUFFER_SIZE);
n = sscanf(buf, "%d", &retval);
check(n == 1);
return retval;
}
char* get_string() {
int n, retval;
char buf[BUFFER_SIZE];
size_t needed = omp_capture_affinity(buf, BUFFER_SIZE, NULL);
check(needed < BUFFER_SIZE);
return strdup(buf);
}
void check_integer(const char* formats[2], int(*func)()) {
int i;
for (i = 0; i < 2; ++i) {
omp_set_affinity_format(formats[i]);
#pragma omp parallel num_threads(8)
{
check(get_integer() == func());
#pragma omp parallel num_threads(3)
{
check(get_integer() == func());
}
check(get_integer() == func());
}
}
}
void check_nesting_level() {
// Check %{nesting_level} and %L
const char* formats[2] = {"%{nesting_level}", "%L"};
check_integer(formats, omp_get_level);
}
void check_thread_num() {
// Check %{thread_num} and %n
const char* formats[2] = {"%{thread_num}", "%n"};
check_integer(formats, omp_get_thread_num);
}
void check_num_threads() {
// Check %{num_threads} and %N
const char* formats[2] = {"%{num_threads}", "%N"};
check_integer(formats, omp_get_num_threads);
}
int ancestor_helper() {
return omp_get_ancestor_thread_num(omp_get_level() - 1);
}
void check_ancestor_tnum() {
// Check %{ancestor_tnum} and %a
const char* formats[2] = {"%{ancestor_tnum}", "%a"};
check_integer(formats, ancestor_helper);
}
int my_get_pid() { return (int)getpid(); }
void check_process_id() {
// Check %{process_id} and %P
const char* formats[2] = {"%{process_id}", "%P"};
check_integer(formats, my_get_pid);
}
/*
int my_get_tid() { return (int)gettid(); }
void check_native_thread_id() {
// Check %{native_thread_id} and %i
const char* formats[2] = {"%{native_thread_id}", "%i"};
check_integer(formats, my_get_tid);
}
*/
void check_host() {
int i;
int buffer_size = 256;
const char* formats[2] = {"%{host}", "%H"};
char hostname[256];
my_gethostname(hostname, buffer_size);
for (i = 0; i < 2; ++i) {
omp_set_affinity_format(formats[i]);
#pragma omp parallel num_threads(8)
{
char* host = get_string();
check(streqls(host, hostname));
free(host);
}
}
}
void check_undefined() {
int i;
const char* formats[2] = {"%{foobar}", "%X"};
for (i = 0; i < 2; ++i) {
omp_set_affinity_format(formats[i]);
#pragma omp parallel num_threads(8)
{
char* undef = get_string();
check(streqls(undef, "undefined"));
free(undef);
}
}
}
int main(int argc, char** argv) {
omp_set_nested(1);
check_nesting_level();
check_num_threads();
check_ancestor_tnum();
check_process_id();
//check_native_thread_id();
check_host();
check_undefined();
return 0;
}