aboutsummaryrefslogtreecommitdiff
path: root/final/runtime/test/affinity/format
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2019-03-18 12:53:32 +0000
committerHans Wennborg <hans@hanshq.net>2019-03-18 12:53:32 +0000
commitabdd46b7db373cb68b58d543400ceb178347b056 (patch)
tree04720549cebf68f6bd10f0009d01c340d7a65c9f /final/runtime/test/affinity/format
parent001d07557b8ffbecdb4f51536c1115f9bcba5ef1 (diff)
Creating release candidate final from release_800 branchsvn-tags/RELEASE_800
git-svn-id: https://llvm.org/svn/llvm-project/openmp/tags/RELEASE_800@356365 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'final/runtime/test/affinity/format')
-rw-r--r--final/runtime/test/affinity/format/affinity_display.1.c92
-rw-r--r--final/runtime/test/affinity/format/affinity_values.c135
-rw-r--r--final/runtime/test/affinity/format/api.c56
-rw-r--r--final/runtime/test/affinity/format/api2.c84
-rw-r--r--final/runtime/test/affinity/format/check.py73
-rw-r--r--final/runtime/test/affinity/format/fields_modifiers.c117
-rw-r--r--final/runtime/test/affinity/format/fields_values.c152
-rw-r--r--final/runtime/test/affinity/format/increase.c36
-rw-r--r--final/runtime/test/affinity/format/lit.local.cfg2
-rw-r--r--final/runtime/test/affinity/format/nested.c23
-rw-r--r--final/runtime/test/affinity/format/nested2.c29
-rw-r--r--final/runtime/test/affinity/format/nested_mixed.c46
-rw-r--r--final/runtime/test/affinity/format/nested_serial.c35
-rw-r--r--final/runtime/test/affinity/format/proc_bind.c31
-rw-r--r--final/runtime/test/affinity/format/simple.c27
-rw-r--r--final/runtime/test/affinity/format/simple_env.c16
16 files changed, 954 insertions, 0 deletions
diff --git a/final/runtime/test/affinity/format/affinity_display.1.c b/final/runtime/test/affinity/format/affinity_display.1.c
new file mode 100644
index 0000000..fe357d3
--- /dev/null
+++ b/final/runtime/test/affinity/format/affinity_display.1.c
@@ -0,0 +1,92 @@
+// RUN: %libomp-compile
+// RUN: env OMP_DISPLAY_AFFINITY=TRUE OMP_NUM_THREADS=4 OMP_PLACES='{0,1},{2,3},{4,5},{6,7}' %libomp-run | %python %S/check.py -c 'CHECK' %s
+
+// Affinity Display examples
+#include <stdio.h>
+#include <stdlib.h> // also null is in <stddef.h>
+#include <stddef.h>
+#include <omp.h>
+#include <string.h>
+
+// ENVIRONMENT
+// OMP_DISPLAY_AFFINITY=TRUE
+// OMP_NUM_THREADS=4
+// OMP_PLACES='{0,1},{2,3},{4,5},{6,7}'
+
+// CHECK: num_threads=1 OMP: pid [0-9]+ tid [0-9]+ thread [0-4] bound to OS proc set \{([0-7])|(0,1)|(undefined)\}
+// CHECK: num_threads=4 Thread id [0-3] reporting in
+// CHECK: num_threads=4 OMP: pid [0-9]+ tid [0-9]+ thread [0-4] bound to OS proc set \{([0-7])|([0246],[1357])|(undefined)\}
+// CHECK: num_threads=1 Default Affinity Format is:
+// CHECK: num_threads=1 Affinity Format set to: host=%20H tid=%0.4n binds_to=%A
+// CHECK: num_threads=4 tid=[0-3] affinity:host=[a-zA-Z0-9_.-]+[ ]+tid=000[0-4][ ]+binds_to=(([0-7])|([0246],[1357])|(undefined))
+
+#define FORMAT_STORE 80
+#define BUFFER_STORE 80
+
+int main(int argc, char** argv) {
+ int i, n, tid, max_req_store = 0;
+ size_t nchars;
+ char default_format[FORMAT_STORE];
+ char my_format[] = "host=%20H tid=%0.4n binds_to=%A";
+ char **buffer;
+
+ // CODE SEGMENT 1 AFFINITY DISPLAY
+ omp_display_affinity(NULL);
+
+ // OMP_DISPLAY_AFFINITY=TRUE,
+ // Affinity reported for 1 parallel region
+ #pragma omp parallel
+ {
+ printf("Thread id %d reporting in.\n", omp_get_thread_num());
+ }
+
+ // Get and Display Default Affinity Format
+ nchars = omp_get_affinity_format(default_format, (size_t)FORMAT_STORE);
+ printf("Default Affinity Format is: %s\n", default_format);
+
+ if (nchars > FORMAT_STORE) {
+ printf("Caution: Reported Format is truncated. Increase\n");
+ printf(" FORMAT_STORE by %d.\n", (int)nchars - FORMAT_STORE);
+ }
+
+ // Set Affinity Format
+ omp_set_affinity_format(my_format);
+ printf("Affinity Format set to: %s\n", my_format);
+
+ // CODE SEGMENT 3 CAPTURE AFFINITY
+ // Set up buffer for affinity of n threads
+ n = omp_get_max_threads();
+ buffer = (char **)malloc(sizeof(char *) * n);
+ for (i = 0; i < n; i++) {
+ buffer[i] = (char *)malloc(sizeof(char) * BUFFER_STORE);
+ }
+
+ // Capture Affinity using Affinity Format set above.
+ // Use critical reduction to check size of buffer areas
+ #pragma omp parallel private(tid, nchars)
+ {
+ tid = omp_get_thread_num();
+ nchars = omp_capture_affinity(buffer[tid], (size_t)BUFFER_STORE, NULL);
+ #pragma omp critical
+ {
+ if (nchars > max_req_store)
+ max_req_store = nchars;
+ }
+ }
+
+ for (i = 0; i < n; i++) {
+ printf("tid=%d affinity:%s:\n", i, buffer[i]);
+ }
+ // for 4 threads with OMP_PLACES='{0,1},{2,3},{4,5},{6,7}'
+ // host=%20H tid=%0.4n binds_to=%A
+ // host=<hostname> tid=0000 binds_to=0,1
+ // host=<hostname> tid=0001 binds_to=2,3
+ // host=<hostname> tid=0002 binds_to=4,5
+ // host=<hostname> tid=0003 binds_to=6,7
+
+ if (max_req_store > BUFFER_STORE) {
+ printf("Caution: Affinity string truncated. Increase\n");
+ printf(" BUFFER_STORE by %d\n", max_req_store - BUFFER_STORE);
+ }
+ return 0;
+}
diff --git a/final/runtime/test/affinity/format/affinity_values.c b/final/runtime/test/affinity/format/affinity_values.c
new file mode 100644
index 0000000..37ab210
--- /dev/null
+++ b/final/runtime/test/affinity/format/affinity_values.c
@@ -0,0 +1,135 @@
+// RUN: %libomp-compile
+// RUN: env OMP_PROC_BIND=close OMP_PLACES=threads %libomp-run
+// RUN: env OMP_PROC_BIND=close OMP_PLACES=cores %libomp-run
+// RUN: env OMP_PROC_BIND=close OMP_PLACES=sockets %libomp-run
+// RUN: env KMP_AFFINITY=compact %libomp-run
+// RUN: env KMP_AFFINITY=scatter %libomp-run
+// REQUIRES: affinity
+
+#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); \
+ }
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdarg.h>
+#endif
+
+#define BUFFER_SIZE 1024
+
+char buf[BUFFER_SIZE];
+#pragma omp threadprivate(buf)
+
+static int debug_printf(const char* format, ...) {
+ int retval = 0;
+#if DEBUG
+ va_list args;
+ va_start(args, format);
+ retval = vprintf(format, args);
+ va_end(args);
+#endif
+ return retval;
+}
+
+static void display_affinity_environment() {
+#if DEBUG
+ printf("Affinity Environment:\n");
+ printf(" OMP_PROC_BIND=%s\n", getenv("OMP_PROC_BIND"));
+ printf(" OMP_PLACES=%s\n", getenv("OMP_PLACES"));
+ printf(" KMP_AFFINITY=%s\n", getenv("KMP_AFFINITY"));
+#endif
+}
+
+// Reads in a list of integers into ids array (not going past ids_size)
+// e.g., if affinity = "0-4,6,8-10,14,16,17-20,23"
+// then ids = [0,1,2,3,4,6,8,9,10,14,16,17,18,19,20,23]
+void list_to_ids(const char* affinity, int* ids, int ids_size) {
+ int id, b, e, ids_index;
+ char *aff, *begin, *end, *absolute_end;
+ aff = strdup(affinity);
+ absolute_end = aff + strlen(aff);
+ ids_index = 0;
+ begin = end = aff;
+ while (end < absolute_end) {
+ end = begin;
+ while (*end != '\0' && *end != ',')
+ end++;
+ *end = '\0';
+ if (strchr(begin, '-') != NULL) {
+ // Range
+ sscanf(begin, "%d-%d", &b, &e);
+ } else {
+ // Single Number
+ sscanf(begin, "%d", &b);
+ e = b;
+ }
+ for (id = b; id <= e; ++id) {
+ ids[ids_index++] = id;
+ if (ids_index >= ids_size) {
+ free(aff);
+ return;
+ }
+ }
+ begin = end + 1;
+ }
+ free(aff);
+}
+
+void check_thread_affinity() {
+ int i;
+ const char *formats[2] = {"%{thread_affinity}", "%A"};
+ for (i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) {
+ omp_set_affinity_format(formats[i]);
+ #pragma omp parallel
+ {
+ int j, k;
+ int place = omp_get_place_num();
+ int num_procs = omp_get_place_num_procs(place);
+ int *ids = (int *)malloc(sizeof(int) * num_procs);
+ int *ids2 = (int *)malloc(sizeof(int) * num_procs);
+ char buf[256];
+ size_t n = omp_capture_affinity(buf, 256, NULL);
+ check(n <= 256);
+ omp_get_place_proc_ids(place, ids);
+ list_to_ids(buf, ids2, num_procs);
+
+ #pragma omp for schedule(static) ordered
+ for (k = 0; k < omp_get_num_threads(); ++k) {
+ #pragma omp ordered
+ {
+ debug_printf("Thread %d: captured affinity = %s\n",
+ omp_get_thread_num(), buf);
+ for (j = 0; j < num_procs; ++j) {
+ debug_printf("Thread %d: ids[%d] = %d ids2[%d] = %d\n",
+ omp_get_thread_num(), j, ids[j], j, ids2[j]);
+ check(ids[j] == ids2[j]);
+ }
+ }
+ }
+
+ free(ids);
+ free(ids2);
+ }
+ }
+}
+
+int main(int argc, char** argv) {
+ omp_set_nested(1);
+ display_affinity_environment();
+ check_thread_affinity();
+ return 0;
+}
diff --git a/final/runtime/test/affinity/format/api.c b/final/runtime/test/affinity/format/api.c
new file mode 100644
index 0000000..08805e7
--- /dev/null
+++ b/final/runtime/test/affinity/format/api.c
@@ -0,0 +1,56 @@
+// RUN: %libomp-compile-and-run
+// RUN: %libomp-run | %python %S/check.py -c 'CHECK' %s
+
+#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); \
+ }
+
+#define BUFFER_SIZE 1024
+
+int main(int argc, char** argv) {
+ char buf[BUFFER_SIZE];
+ size_t needed;
+
+ omp_set_affinity_format("0123456789");
+
+ needed = omp_get_affinity_format(buf, BUFFER_SIZE);
+ check(streqls(buf, "0123456789"));
+ check(needed == 10)
+
+ // Check that it is truncated properly
+ omp_get_affinity_format(buf, 5);
+ check(streqls(buf, "0123"));
+
+ #pragma omp parallel
+ {
+ char my_buf[512];
+ size_t needed = omp_capture_affinity(my_buf, 512, NULL);
+ check(streqls(my_buf, "0123456789"));
+ check(needed == 10);
+ // Check that it is truncated properly
+ omp_capture_affinity(my_buf, 5, NULL);
+ check(streqls(my_buf, "0123"));
+ }
+
+ #pragma omp parallel num_threads(4)
+ {
+ omp_display_affinity(NULL);
+ }
+
+ return 0;
+}
+
+// CHECK: num_threads=4 0123456789
diff --git a/final/runtime/test/affinity/format/api2.c b/final/runtime/test/affinity/format/api2.c
new file mode 100644
index 0000000..c32da93
--- /dev/null
+++ b/final/runtime/test/affinity/format/api2.c
@@ -0,0 +1,84 @@
+// RUN: %libomp-compile-and-run
+// RUN: %libomp-run | %python %S/check.py -c 'CHECK' %s
+
+#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)
+#define snprintf _snprintf
+#endif
+
+#define BUFFER_SIZE 1024
+
+int main(int argc, char** argv) {
+ char buf[BUFFER_SIZE];
+ size_t needed, length;
+ const char* format = "tl:%L tn:%n nt:%N an:%a";
+ const char* second_format = "nesting_level:%{nesting_level} thread_num:%{thread_num} num_threads:%{num_threads} ancestor_tnum:%{ancestor_tnum}";
+
+ length = strlen(format);
+ omp_set_affinity_format(format);
+
+ needed = omp_get_affinity_format(buf, BUFFER_SIZE);
+ check(streqls(buf, format));
+ check(needed == length)
+
+ // Check that it is truncated properly
+ omp_get_affinity_format(buf, 5);
+ check(streqls(buf, "tl:%"));
+
+ #pragma omp parallel
+ {
+ char my_buf[512];
+ char supposed[512];
+ int tl, tn, nt, an;
+ size_t needed, needed2;
+ tl = omp_get_level();
+ tn = omp_get_thread_num();
+ nt = omp_get_num_threads();
+ an = omp_get_ancestor_thread_num(omp_get_level()-1);
+ needed = omp_capture_affinity(my_buf, 512, NULL);
+ needed2 = (size_t)snprintf(supposed, 512, "tl:%d tn:%d nt:%d an:%d", tl, tn, nt, an);
+ check(streqls(my_buf, supposed));
+ check(needed == needed2);
+ // Check that it is truncated properly
+ supposed[4] = '\0';
+ omp_capture_affinity(my_buf, 5, NULL);
+ check(streqls(my_buf, supposed));
+
+ needed = omp_capture_affinity(my_buf, 512, second_format);
+ needed2 = (size_t)snprintf(supposed, 512, "nesting_level:%d thread_num:%d num_threads:%d ancestor_tnum:%d", tl, tn, nt, an);
+ check(streqls(my_buf, supposed));
+ check(needed == needed2);
+
+ // Check that it is truncated properly
+ supposed[25] = '\0';
+ omp_capture_affinity(my_buf, 26, second_format);
+ check(streqls(my_buf, supposed));
+ }
+
+ #pragma omp parallel num_threads(4)
+ {
+ omp_display_affinity(NULL);
+ omp_display_affinity(second_format);
+ }
+
+ return 0;
+}
+
+// CHECK: num_threads=4 tl:[0-9]+ tn:[0-9]+ nt:[0-9]+ an:[0-9]+
+// CHECK: num_threads=4 nesting_level:[0-9]+ thread_num:[0-9]+ num_threads:[0-9]+ ancestor_tnum:[0-9]+
diff --git a/final/runtime/test/affinity/format/check.py b/final/runtime/test/affinity/format/check.py
new file mode 100644
index 0000000..0adddbd
--- /dev/null
+++ b/final/runtime/test/affinity/format/check.py
@@ -0,0 +1,73 @@
+import os
+import sys
+import argparse
+import re
+
+class Checks(object):
+ class CheckError(Exception):
+ pass
+
+ def __init__(self, filename, prefix):
+ self.checks = []
+ self.lines = []
+ self.check_no_output = False
+ self.filename = filename
+ self.prefix = prefix
+ def readStdin(self):
+ self.lines = [l.rstrip('\r\n') for l in sys.stdin.readlines()]
+ def readChecks(self):
+ with open(self.filename) as f:
+ for line in f:
+ match = re.search('{}: NO_OUTPUT'.format(self.prefix), line)
+ if match is not None:
+ self.check_no_output = True
+ return
+ match = re.search('{}: num_threads=([0-9]+) (.*)$'.format(self.prefix), line)
+ if match is not None:
+ num_threads = int(match.group(1))
+ for i in range(num_threads):
+ self.checks.append(match.group(2))
+ continue
+ def check(self):
+ # If no checks at all, then nothing to do
+ if len(self.checks) == 0 and not self.check_no_output:
+ print('Nothing to check for')
+ return
+ # Check if we are expecting no output
+ if self.check_no_output:
+ if len(self.lines) == 0:
+ return
+ else:
+ raise Checks.CheckError('{}: Output was found when expecting none.'.format(self.prefix))
+ # Run through each check line and see if it exists in the output
+ # If it does, then delete the line from output and look for the
+ # next check line.
+ # If you don't find the line then raise Checks.CheckError
+ # If there are extra lines of output then raise Checks.CheckError
+ for c in self.checks:
+ found = False
+ index = -1
+ for idx, line in enumerate(self.lines):
+ if re.search(c, line) is not None:
+ found = True
+ index = idx
+ break
+ if not found:
+ raise Checks.CheckError('{}: Did not find: {}'.format(self.prefix, c))
+ else:
+ del self.lines[index]
+ if len(self.lines) != 0:
+ raise Checks.CheckError('{}: Extra output: {}'.format(self.prefix, self.lines))
+
+# Setup argument parsing
+parser = argparse.ArgumentParser(description='''This script checks output of
+ a program against "CHECK" lines in filename''')
+parser.add_argument('filename', default=None, help='filename to check against')
+parser.add_argument('-c', '--check-prefix', dest='prefix',
+ default='CHECK', help='check prefix token default: %(default)s')
+command_args = parser.parse_args()
+# Do the checking
+checks = Checks(command_args.filename, command_args.prefix)
+checks.readStdin()
+checks.readChecks()
+checks.check()
diff --git a/final/runtime/test/affinity/format/fields_modifiers.c b/final/runtime/test/affinity/format/fields_modifiers.c
new file mode 100644
index 0000000..c180271
--- /dev/null
+++ b/final/runtime/test/affinity/format/fields_modifiers.c
@@ -0,0 +1,117 @@
+// 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); \
+ }
+
+#define BUFFER_SIZE 1024
+
+char buf[BUFFER_SIZE];
+#pragma omp threadprivate(buf)
+
+char* get_string(size_t check_needed) {
+ size_t needed = omp_capture_affinity(buf, BUFFER_SIZE, NULL);
+ //printf("buf = %s\n", buf);
+ check(needed < BUFFER_SIZE);
+ if (check_needed != 0) {
+ check(needed == check_needed);
+ }
+ return buf;
+}
+
+void check_thread_num_padded_rjustified() {
+ int i;
+ const char* formats[2] = {"%0.8{thread_num}", "%0.8n"};
+ for (i = 0; i < sizeof(formats)/sizeof(formats[0]); ++i) {
+ omp_set_affinity_format(formats[i]);
+ #pragma omp parallel num_threads(8)
+ {
+ int j;
+ int tid = omp_get_thread_num();
+ char ctid = '0' + (char)tid;
+ char* s = get_string(8);
+ for (j = 0; j < 7; ++j) {
+ check(s[j] == '0');
+ }
+ check(s[j] == ctid);
+ }
+ }
+}
+
+void check_thread_num_rjustified() {
+ int i;
+ const char* formats[2] = {"%.12{thread_num}", "%.12n"};
+ for (i = 0; i < sizeof(formats)/sizeof(formats[0]); ++i) {
+ omp_set_affinity_format(formats[i]);
+ #pragma omp parallel num_threads(8)
+ {
+ int j;
+ int tid = omp_get_thread_num();
+ char ctid = '0' + (char)tid;
+ char* s = get_string(12);
+ for (j = 0; j < 11; ++j) {
+ check(s[j] == ' ');
+ }
+ check(s[j] == ctid);
+ }
+ }
+}
+
+void check_thread_num_ljustified() {
+ int i;
+ const char* formats[2] = {"%5{thread_num}", "%5n"};
+ for (i = 0; i < sizeof(formats)/sizeof(formats[0]); ++i) {
+ omp_set_affinity_format(formats[i]);
+ #pragma omp parallel num_threads(8)
+ {
+ int j;
+ int tid = omp_get_thread_num();
+ char ctid = '0' + (char)tid;
+ char* s = get_string(5);
+ check(s[0] == ctid);
+ for (j = 1; j < 5; ++j) {
+ check(s[j] == ' ');
+ }
+ }
+ }
+}
+
+void check_thread_num_padded_ljustified() {
+ int i;
+ const char* formats[2] = {"%018{thread_num}", "%018n"};
+ for (i = 0; i < sizeof(formats)/sizeof(formats[0]); ++i) {
+ omp_set_affinity_format(formats[i]);
+ #pragma omp parallel num_threads(8)
+ {
+ int j;
+ int tid = omp_get_thread_num();
+ char ctid = '0' + (char)tid;
+ char* s = get_string(18);
+ check(s[0] == ctid);
+ for (j = 1; j < 18; ++j) {
+ check(s[j] == ' ');
+ }
+ }
+ }
+}
+
+int main(int argc, char** argv) {
+ check_thread_num_ljustified();
+ check_thread_num_rjustified();
+ check_thread_num_padded_ljustified();
+ check_thread_num_padded_rjustified();
+ return 0;
+}
diff --git a/final/runtime/test/affinity/format/fields_values.c b/final/runtime/test/affinity/format/fields_values.c
new file mode 100644
index 0000000..e56ce27
--- /dev/null
+++ b/final/runtime/test/affinity/format/fields_values.c
@@ -0,0 +1,152 @@
+// 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>
+#define getpid _getpid
+typedef int pid_t;
+#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;
+}
diff --git a/final/runtime/test/affinity/format/increase.c b/final/runtime/test/affinity/format/increase.c
new file mode 100644
index 0000000..b3942db
--- /dev/null
+++ b/final/runtime/test/affinity/format/increase.c
@@ -0,0 +1,36 @@
+// RUN: %libomp-compile && env OMP_DISPLAY_AFFINITY=true %libomp-run | %python %S/check.py -c 'CHECK' %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+
+int main(int argc, char** argv) {
+ omp_set_affinity_format("TESTER: tl:%L tn:%n nt:%N");
+ // should print all for first parallel
+ omp_set_num_threads(4);
+ #pragma omp parallel
+ { }
+ // should print all because of new threads
+ omp_set_num_threads(8);
+ #pragma omp parallel
+ { }
+ // should not print anything here
+ omp_set_num_threads(6);
+ #pragma omp parallel
+ { }
+ // should print all because of new thread
+ omp_set_num_threads(9);
+ #pragma omp parallel
+ { }
+ // should not print anything here
+ omp_set_num_threads(2);
+ #pragma omp parallel
+ { }
+ return 0;
+}
+
+// CHECK: num_threads=4 TESTER: tl:1 tn:[0-3] nt:4
+// CHECK: num_threads=8 TESTER: tl:1 tn:[0-7] nt:8
+// CHECK: num_threads=6 TESTER: tl:1 tn:[0-5] nt:6
+// CHECK: num_threads=9 TESTER: tl:1 tn:[0-8] nt:9
+// CHECK: num_threads=2 TESTER: tl:1 tn:[01] nt:2
diff --git a/final/runtime/test/affinity/format/lit.local.cfg b/final/runtime/test/affinity/format/lit.local.cfg
new file mode 100644
index 0000000..80583af
--- /dev/null
+++ b/final/runtime/test/affinity/format/lit.local.cfg
@@ -0,0 +1,2 @@
+if 'openmp-5.0' not in config.available_features:
+ config.unsupported = True
diff --git a/final/runtime/test/affinity/format/nested.c b/final/runtime/test/affinity/format/nested.c
new file mode 100644
index 0000000..2ecc918
--- /dev/null
+++ b/final/runtime/test/affinity/format/nested.c
@@ -0,0 +1,23 @@
+// RUN: %libomp-compile && env OMP_DISPLAY_AFFINITY=true OMP_PLACES=threads OMP_PROC_BIND=spread,close %libomp-run | %python %S/check.py -c 'CHECK' %s
+// REQUIRES: affinity
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+
+int main(int argc, char** argv) {
+ omp_set_affinity_format("TESTER: tl:%L at:%a tn:%n nt:%N");
+ omp_set_nested(1);
+ #pragma omp parallel num_threads(4)
+ {
+ #pragma omp parallel num_threads(3)
+ { }
+ }
+ return 0;
+}
+
+// CHECK: num_threads=4 TESTER: tl:1 at:0 tn:[0-3] nt:4
+// CHECK: num_threads=3 TESTER: tl:2 at:[0-3] tn:[0-2] nt:3
+// CHECK: num_threads=3 TESTER: tl:2 at:[0-3] tn:[0-2] nt:3
+// CHECK: num_threads=3 TESTER: tl:2 at:[0-3] tn:[0-2] nt:3
+// CHECK: num_threads=3 TESTER: tl:2 at:[0-3] tn:[0-2] nt:3
diff --git a/final/runtime/test/affinity/format/nested2.c b/final/runtime/test/affinity/format/nested2.c
new file mode 100644
index 0000000..4b54912
--- /dev/null
+++ b/final/runtime/test/affinity/format/nested2.c
@@ -0,0 +1,29 @@
+// RUN: %libomp-compile && env OMP_DISPLAY_AFFINITY=true OMP_PLACES=threads OMP_PROC_BIND=spread,close KMP_HOT_TEAMS_MAX_LEVEL=2 %libomp-run | %python %S/check.py -c 'CHECK' %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+
+// Currently, KMP_HOT_TEAMS_MAX_LEVEL has to be equal to the
+// nest depth for intuitive behavior
+int main(int argc, char** argv) {
+ omp_set_affinity_format("TESTER: tl:%L tn:%n nt:%N");
+ omp_set_nested(1);
+ #pragma omp parallel num_threads(4)
+ {
+ #pragma omp parallel num_threads(3)
+ { }
+ #pragma omp parallel num_threads(3)
+ { }
+ }
+ #pragma omp parallel num_threads(4)
+ { }
+ return 0;
+}
+
+// CHECK: num_threads=4 TESTER: tl:1 tn:[0-3] nt:4
+// CHECK: num_threads=3 TESTER: tl:2 tn:[0-2] nt:3
+// CHECK: num_threads=3 TESTER: tl:2 tn:[0-2] nt:3
+// CHECK: num_threads=3 TESTER: tl:2 tn:[0-2] nt:3
+// CHECK: num_threads=3 TESTER: tl:2 tn:[0-2] nt:3
+// CHECK: num_threads=4 TESTER: tl:1 tn:[0-3] nt:4
diff --git a/final/runtime/test/affinity/format/nested_mixed.c b/final/runtime/test/affinity/format/nested_mixed.c
new file mode 100644
index 0000000..1e4c753
--- /dev/null
+++ b/final/runtime/test/affinity/format/nested_mixed.c
@@ -0,0 +1,46 @@
+// RUN: %libomp-compile && env OMP_DISPLAY_AFFINITY=true %libomp-run | %python %S/check.py -c 'CHECK' %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+
+int main(int argc, char** argv) {
+ omp_set_affinity_format("TESTER: tl:%L at:%a tn:%n nt:%N");
+ omp_set_nested(1);
+ #pragma omp parallel num_threads(1)
+ {
+ #pragma omp parallel num_threads(2)
+ { }
+ #pragma omp parallel num_threads(2)
+ {
+ #pragma omp parallel num_threads(1)
+ {
+ #pragma omp parallel num_threads(2)
+ { }
+ }
+ }
+ #pragma omp parallel num_threads(1)
+ { }
+ }
+ #pragma omp parallel num_threads(2)
+ { }
+ #pragma omp parallel num_threads(1)
+ { }
+ return 0;
+}
+
+// CHECK: num_threads=1 TESTER: tl:1 at:0 tn:0 nt:1
+
+// CHECK: num_threads=2 TESTER: tl:2 at:[0-9] tn:[01] nt:2
+
+// CHECK: num_threads=1 TESTER: tl:3 at:[0-9] tn:0 nt:1
+// CHECK: num_threads=1 TESTER: tl:3 at:[0-9] tn:0 nt:1
+
+// CHECK: num_threads=2 TESTER: tl:4 at:[0-9] tn:[01] nt:2
+// CHECK: num_threads=2 TESTER: tl:4 at:[0-9] tn:[01] nt:2
+
+// CHECK: num_threads=1 TESTER: tl:2 at:[0-9] tn:0 nt:1
+
+// CHECK: num_threads=2 TESTER: tl:1 at:[0-9] tn:[01] nt:2
+
+// CHECK: num_threads=1 TESTER: tl:1 at:[0-9] tn:0 nt:1
diff --git a/final/runtime/test/affinity/format/nested_serial.c b/final/runtime/test/affinity/format/nested_serial.c
new file mode 100644
index 0000000..8b84ba6
--- /dev/null
+++ b/final/runtime/test/affinity/format/nested_serial.c
@@ -0,0 +1,35 @@
+// RUN: %libomp-compile && env OMP_DISPLAY_AFFINITY=true %libomp-run | %python %S/check.py -c 'CHECK' %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+
+int main(int argc, char** argv) {
+ omp_set_affinity_format("TESTER: tl:%L at:%a tn:%n nt:%N");
+ omp_set_nested(1);
+ #pragma omp parallel num_threads(1)
+ {
+ #pragma omp parallel num_threads(1)
+ { }
+ #pragma omp parallel num_threads(1)
+ { }
+ #pragma omp parallel num_threads(1)
+ {
+ #pragma omp parallel num_threads(1)
+ { }
+ }
+ #pragma omp parallel num_threads(1)
+ { }
+ }
+ #pragma omp parallel num_threads(1)
+ { }
+ #pragma omp parallel num_threads(1)
+ { }
+ return 0;
+}
+
+// CHECK: num_threads=1 TESTER: tl:1 at:0 tn:0 nt:1
+// CHECK: num_threads=1 TESTER: tl:2 at:0 tn:0 nt:1
+// CHECK: num_threads=1 TESTER: tl:3 at:0 tn:0 nt:1
+// CHECK: num_threads=1 TESTER: tl:2 at:0 tn:0 nt:1
+// CHECK: num_threads=1 TESTER: tl:1 at:0 tn:0 nt:1
diff --git a/final/runtime/test/affinity/format/proc_bind.c b/final/runtime/test/affinity/format/proc_bind.c
new file mode 100644
index 0000000..765c3ce
--- /dev/null
+++ b/final/runtime/test/affinity/format/proc_bind.c
@@ -0,0 +1,31 @@
+// RUN: %libomp-compile && env OMP_DISPLAY_AFFINITY=true OMP_PLACES='{0},{0,1},{0},{0,1},{0},{0,1},{0},{0,1},{0},{0,1},{0}' %libomp-run | %python %S/check.py -c 'CHECK' %s
+// REQUIRES: affinity
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+
+int main(int argc, char** argv) {
+ omp_set_affinity_format("TESTER: tl:%L tn:%n nt:%N aff:{%A}");
+ omp_set_num_threads(8);
+ // Initial parallel
+ #pragma omp parallel proc_bind(spread)
+ { }
+ #pragma omp parallel proc_bind(spread)
+ { }
+ // Affinity changes here
+ #pragma omp parallel proc_bind(close)
+ { }
+ #pragma omp parallel proc_bind(close)
+ { }
+ // Affinity changes here
+ #pragma omp parallel proc_bind(master)
+ { }
+ #pragma omp parallel proc_bind(master)
+ { }
+ return 0;
+}
+
+// CHECK: num_threads=8 TESTER: tl:1 tn:[0-7] nt:8 aff:
+// CHECK: num_threads=8 TESTER: tl:1 tn:[0-7] nt:8 aff:
+// CHECK: num_threads=8 TESTER: tl:1 tn:[0-7] nt:8 aff:
diff --git a/final/runtime/test/affinity/format/simple.c b/final/runtime/test/affinity/format/simple.c
new file mode 100644
index 0000000..701c207
--- /dev/null
+++ b/final/runtime/test/affinity/format/simple.c
@@ -0,0 +1,27 @@
+// RUN: %libomp-compile
+// RUN: env OMP_DISPLAY_AFFINITY=false %libomp-run | %python %S/check.py -c 'NOTHING' %s
+// RUN: env OMP_DISPLAY_AFFINITY=true OMP_NUM_THREADS=1 %libomp-run | %python %S/check.py -c 'CHECK' %s
+// RUN: env OMP_DISPLAY_AFFINITY=true OMP_NUM_THREADS=2 %libomp-run | %python %S/check.py -c 'CHECK-2' %s
+// RUN: env OMP_DISPLAY_AFFINITY=true OMP_NUM_THREADS=3 %libomp-run | %python %S/check.py -c 'CHECK-3' %s
+// RUN: env OMP_DISPLAY_AFFINITY=true OMP_NUM_THREADS=4 %libomp-run | %python %S/check.py -c 'CHECK-4' %s
+// RUN: env OMP_DISPLAY_AFFINITY=true OMP_NUM_THREADS=8 %libomp-run | %python %S/check.py -c 'CHECK-8' %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+
+int main(int argc, char** argv) {
+ omp_set_affinity_format("TESTER: tl:%L tn:%n nt:%N");
+ #pragma omp parallel
+ { }
+ #pragma omp parallel
+ { }
+ return 0;
+}
+
+// NOTHING: NO_OUTPUT
+// CHECK: num_threads=1 TESTER: tl:1 tn:0 nt:1
+// CHECK-2: num_threads=2 TESTER: tl:1 tn:[01] nt:2
+// CHECK-3: num_threads=3 TESTER: tl:1 tn:[0-2] nt:3
+// CHECK-4: num_threads=4 TESTER: tl:1 tn:[0-3] nt:4
+// CHECK-8: num_threads=8 TESTER: tl:1 tn:[0-7] nt:8
diff --git a/final/runtime/test/affinity/format/simple_env.c b/final/runtime/test/affinity/format/simple_env.c
new file mode 100644
index 0000000..ad0a265
--- /dev/null
+++ b/final/runtime/test/affinity/format/simple_env.c
@@ -0,0 +1,16 @@
+// RUN: %libomp-compile
+// RUN: env OMP_DISPLAY_AFFINITY=true OMP_AFFINITY_FORMAT='TESTER-ENV: tl:%L tn:%n nt:%N' OMP_NUM_THREADS=8 %libomp-run | %python %S/check.py -c 'CHECK-8' %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+
+int main(int argc, char** argv) {
+ #pragma omp parallel
+ { }
+ #pragma omp parallel
+ { }
+ return 0;
+}
+
+// CHECK-8: num_threads=8 TESTER-ENV: tl:1 tn:[0-7] nt:8