summaryrefslogtreecommitdiffstats
path: root/openmp/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'openmp/runtime')
-rw-r--r--openmp/runtime/src/dllexports8
-rw-r--r--openmp/runtime/src/i18n/en_US.txt1
-rw-r--r--openmp/runtime/src/include/50/omp.h.var11
-rw-r--r--openmp/runtime/src/include/50/omp_lib.f.var37
-rw-r--r--openmp/runtime/src/include/50/omp_lib.f90.var21
-rw-r--r--openmp/runtime/src/include/50/omp_lib.h.var29
-rw-r--r--openmp/runtime/src/kmp.h30
-rw-r--r--openmp/runtime/src/kmp_affinity.cpp140
-rw-r--r--openmp/runtime/src/kmp_barrier.cpp18
-rw-r--r--openmp/runtime/src/kmp_csupport.cpp53
-rw-r--r--openmp/runtime/src/kmp_ftn_entry.h195
-rw-r--r--openmp/runtime/src/kmp_ftn_os.h16
-rw-r--r--openmp/runtime/src/kmp_global.cpp5
-rw-r--r--openmp/runtime/src/kmp_io.cpp60
-rw-r--r--openmp/runtime/src/kmp_io.h3
-rw-r--r--openmp/runtime/src/kmp_os.h2
-rw-r--r--openmp/runtime/src/kmp_runtime.cpp409
-rw-r--r--openmp/runtime/src/kmp_safe_c_api.h15
-rw-r--r--openmp/runtime/src/kmp_settings.cpp46
-rw-r--r--openmp/runtime/src/kmp_str.cpp29
-rw-r--r--openmp/runtime/src/kmp_str.h7
-rw-r--r--openmp/runtime/src/kmp_stub.cpp15
-rw-r--r--openmp/runtime/test/lit.cfg3
23 files changed, 1024 insertions, 129 deletions
diff --git a/openmp/runtime/src/dllexports b/openmp/runtime/src/dllexports
index 63bb2227f85..963ac619ae7 100644
--- a/openmp/runtime/src/dllexports
+++ b/openmp/runtime/src/dllexports
@@ -547,6 +547,14 @@ kmp_set_disp_num_buffers 890
omp_get_default_allocator 893
omp_alloc 894
omp_free 895
+ omp_set_affinity_format 748
+ omp_get_affinity_format 749
+ omp_display_affinity 750
+ omp_capture_affinity 751
+ ompc_set_affinity_format 752
+ ompc_get_affinity_format 753
+ ompc_display_affinity 754
+ ompc_capture_affinity 755
OMP_NULL_ALLOCATOR DATA
omp_default_mem_alloc DATA
diff --git a/openmp/runtime/src/i18n/en_US.txt b/openmp/runtime/src/i18n/en_US.txt
index 067cb94c616..3e5283ed38f 100644
--- a/openmp/runtime/src/i18n/en_US.txt
+++ b/openmp/runtime/src/i18n/en_US.txt
@@ -425,6 +425,7 @@ AffHWSubsetManyNodes "KMP_HW_SUBSET ignored: too many NUMA Nodes request
AffHWSubsetManyTiles "KMP_HW_SUBSET ignored: too many L2 Caches requested."
AffHWSubsetManyProcs "KMP_HW_SUBSET ignored: too many Procs requested."
HierSchedInvalid "Hierarchy ignored: unsupported level: %1$s."
+AffFormatDefault "OMP: pid %1$s tid %2$s thread %3$s bound to OS proc set {%4$s}"
# --------------------------------------------------------------------------------------------------
diff --git a/openmp/runtime/src/include/50/omp.h.var b/openmp/runtime/src/include/50/omp.h.var
index 7a626bd0711..81b6c854246 100644
--- a/openmp/runtime/src/include/50/omp.h.var
+++ b/openmp/runtime/src/include/50/omp.h.var
@@ -25,6 +25,11 @@
extern "C" {
# endif
+# define omp_set_affinity_format ompc_set_affinity_format
+# define omp_get_affinity_format ompc_get_affinity_format
+# define omp_display_affinity ompc_display_affinity
+# define omp_capture_affinity ompc_capture_affinity
+
# if defined(_WIN32)
# define __KAI_KMPC_CONVENTION __cdecl
# ifndef __KMP_IMP
@@ -235,6 +240,12 @@
extern void __KAI_KMPC_CONVENTION omp_free(void *ptr, const omp_allocator_t *allocator);
#endif
+ /* OpenMP 5.0 Affinity Format */
+ extern void __KAI_KMPC_CONVENTION omp_set_affinity_format(char const *);
+ extern size_t __KAI_KMPC_CONVENTION omp_get_affinity_format(char *, size_t);
+ extern void __KAI_KMPC_CONVENTION omp_display_affinity(char const *);
+ extern size_t __KAI_KMPC_CONVENTION omp_capture_affinity(char *, size_t, char const *);
+
# undef __KAI_KMPC_CONVENTION
# undef __KMP_IMP
diff --git a/openmp/runtime/src/include/50/omp_lib.f.var b/openmp/runtime/src/include/50/omp_lib.f.var
index 8a02b629e4e..d5a80573429 100644
--- a/openmp/runtime/src/include/50/omp_lib.f.var
+++ b/openmp/runtime/src/include/50/omp_lib.f.var
@@ -375,6 +375,27 @@
integer (kind=omp_allocator_kind) omp_get_default_allocator
end function omp_get_default_allocator
+ subroutine omp_set_affinity_format(format)
+ character (len=*) format
+ end subroutine omp_set_affinity_format
+
+ function omp_get_affinity_format(buffer)
+ use omp_lib_kinds
+ character (len=*) buffer
+ integer (kind=kmp_size_t_kind) omp_get_affinity_format
+ end function omp_get_affinity_format
+
+ subroutine omp_display_affinity(format)
+ character (len=*) format
+ end subroutine omp_display_affinity
+
+ function omp_capture_affinity(buffer, format)
+ use omp_lib_kinds
+ character (len=*) format
+ character (len=*) buffer
+ integer (kind=kmp_size_t_kind) omp_capture_affinity
+ end function omp_capture_affinity
+
! ***
! *** kmp_* entry points
! ***
@@ -594,6 +615,10 @@
!dec$ attributes alias:'OMP_IS_INITIAL_DEVICE' :: omp_is_initial_device
!dec$ attributes alias:'OMP_GET_MAX_TASK_PRIORITY' :: omp_get_max_task_priority
!dec$ attributes alias:'OMP_CONTROL_TOOL' :: omp_control_tool
+!dec$ attributes alias:'OMP_SET_AFFINITY_FORMAT' :: omp_set_affinity_format
+!dec$ attributes alias:'OMP_GET_AFFINITY_FORMAT' :: omp_get_affinity_format
+!dec$ attributes alias:'OMP_DISPLAY_AFFINITY' :: omp_display_affinity
+!dec$ attributes alias:'OMP_CAPTURE_AFFINITY' :: omp_capture_affinity
!dec$ attributes alias:'omp_init_lock' :: omp_init_lock
!dec$ attributes alias:'omp_init_lock_with_hint' :: omp_init_lock_with_hint
@@ -675,6 +700,10 @@
!dec$ attributes alias:'_OMP_IS_INITIAL_DEVICE' :: omp_is_initial_device
!dec$ attributes alias:'_OMP_GET_MAX_TASK_PRIORTY' :: omp_get_max_task_priority
!dec$ attributes alias:'_OMP_CONTROL_TOOL' :: omp_control_tool
+!dec$ attributes alias:'_OMP_SET_AFFINITY_FORMAT' :: omp_set_affinity_format
+!dec$ attributes alias:'_OMP_GET_AFFINITY_FORMAT' :: omp_get_affinity_format
+!dec$ attributes alias:'_OMP_DISPLAY_AFFINITY' :: omp_display_affinity
+!dec$ attributes alias:'_OMP_CAPTURE_AFFINITY' :: omp_capture_affinity
!dec$ attributes alias:'_omp_init_lock' :: omp_init_lock
!dec$ attributes alias:'_omp_init_lock_with_hint' :: omp_init_lock_with_hint
@@ -758,6 +787,10 @@
!dec$ attributes alias:'omp_get_cancellation_'::omp_get_cancellation
!dec$ attributes alias:'omp_is_initial_device_'::omp_is_initial_device
!dec$ attributes alias:'omp_get_max_task_priority_'::omp_get_max_task_priority
+!dec$ attributes alias:'omp_set_affinity_format_' :: omp_set_affinity_format
+!dec$ attributes alias:'omp_get_affinity_format_' :: omp_get_affinity_format
+!dec$ attributes alias:'omp_display_affinity_' :: omp_display_affinity
+!dec$ attributes alias:'omp_capture_affinity_' :: omp_capture_affinity
!dec$ attributes alias:'omp_init_lock_'::omp_init_lock
!dec$ attributes alias:'omp_init_lock_with_hint_'::omp_init_lock_with_hint
@@ -852,6 +885,10 @@
!dec$ attributes alias:'_omp_unset_nest_lock_'::omp_unset_nest_lock
!dec$ attributes alias:'_omp_test_nest_lock_'::omp_test_nest_lock
!dec$ attributes alias:'_omp_control_tool_'::omp_control_tool
+!dec$ attributes alias:'_omp_set_affinity_format_' :: omp_set_affinity_format
+!dec$ attributes alias:'_omp_get_affinity_format_' :: omp_get_affinity_format
+!dec$ attributes alias:'_omp_display_affinity_' :: omp_display_affinity
+!dec$ attributes alias:'_omp_capture_affinity_' :: omp_capture_affinity
!dec$ attributes alias:'_kmp_set_stacksize_'::kmp_set_stacksize
!dec$ attributes alias:'_kmp_set_stacksize_s_'::kmp_set_stacksize_s
diff --git a/openmp/runtime/src/include/50/omp_lib.f90.var b/openmp/runtime/src/include/50/omp_lib.f90.var
index 624774d783c..afc6d6739f4 100644
--- a/openmp/runtime/src/include/50/omp_lib.f90.var
+++ b/openmp/runtime/src/include/50/omp_lib.f90.var
@@ -391,6 +391,27 @@
integer (kind=omp_allocator_kind) omp_get_default_allocator
end function omp_get_default_allocator
+ subroutine omp_set_affinity_format(format)
+ character (len=*) :: format
+ end subroutine omp_set_affinity_format
+
+ function omp_get_affinity_format(buffer)
+ use omp_lib_kinds
+ character (len=*) :: buffer
+ integer (kind=kmp_size_t_kind) :: omp_get_affinity_format
+ end function omp_get_affinity_format
+
+ subroutine omp_display_affinity(format)
+ character (len=*) :: format
+ end subroutine omp_display_affinity
+
+ function omp_capture_affinity(buffer, format)
+ use omp_lib_kinds
+ character (len=*) :: format
+ character (len=*) :: buffer
+ integer (kind=kmp_size_t_kind) :: omp_capture_affinity
+ end function omp_capture_affinity
+
! ***
! *** kmp_* entry points
! ***
diff --git a/openmp/runtime/src/include/50/omp_lib.h.var b/openmp/runtime/src/include/50/omp_lib.h.var
index 0e4c2c6ac9c..11dbc0a5911 100644
--- a/openmp/runtime/src/include/50/omp_lib.h.var
+++ b/openmp/runtime/src/include/50/omp_lib.h.var
@@ -424,6 +424,27 @@
integer (kind=omp_allocator_kind) omp_get_default_allocator
end function omp_get_default_allocator
+ subroutine omp_set_affinity_format(format)
+ character (len=*) :: format
+ end subroutine omp_set_affinity_format
+
+ function omp_get_affinity_format(buffer)
+ import
+ character (len=*) :: buffer
+ integer (kind=kmp_size_t_kind) :: omp_get_affinity_format
+ end function omp_get_affinity_format
+
+ subroutine omp_display_affinity(format)
+ character (len=*) :: format
+ end subroutine omp_display_affinity
+
+ function omp_capture_affinity(buffer, format)
+ import
+ character (len=*) :: format
+ character (len=*) :: buffer
+ integer (kind=kmp_size_t_kind) :: omp_capture_affinity
+ end function omp_capture_affinity
+
! ***
! *** kmp_* entry points
! ***
@@ -637,6 +658,10 @@
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_unset_nest_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_test_nest_lock
!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_max_task_priority
+!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_set_affinity_format
+!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_affinity_format
+!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_display_affinity
+!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_capture_affinity
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_stacksize
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_stacksize_s
!DIR$ ATTRIBUTES OFFLOAD:MIC :: kmp_set_blocktime
@@ -710,6 +735,10 @@
!$omp declare target(omp_unset_nest_lock )
!$omp declare target(omp_test_nest_lock )
!$omp declare target(omp_get_max_task_priority )
+!$omp declare target(omp_set_affinity_format )
+!$omp declare target(omp_get_affinity_format )
+!$omp declare target(omp_display_affinity )
+!$omp declare target(omp_capture_affinity )
!$omp declare target(kmp_set_stacksize )
!$omp declare target(kmp_set_stacksize_s )
!$omp declare target(kmp_set_blocktime )
diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h
index c09f4b2d7ec..23bbeb35ca9 100644
--- a/openmp/runtime/src/kmp.h
+++ b/openmp/runtime/src/kmp.h
@@ -129,6 +129,11 @@ class kmp_stats_list;
#include "ompt-internal.h"
#endif
+#if OMP_50_ENABLED
+// Affinity format function
+#include "kmp_str.h"
+#endif
+
// 0 - no fast memory allocation, alignment: 8-byte on x86, 16-byte on x64.
// 3 - fast allocation using sync, non-sync free lists of any size, non-self
// free lists of limited size.
@@ -797,6 +802,12 @@ extern kmp_nested_proc_bind_t __kmp_nested_proc_bind;
#endif /* OMP_40_ENABLED */
+#if OMP_50_ENABLED
+extern int __kmp_display_affinity;
+extern char *__kmp_affinity_format;
+static const size_t KMP_AFFINITY_FORMAT_SIZE = 512;
+#endif // OMP_50_ENABLED
+
#if KMP_AFFINITY_SUPPORTED
#define KMP_PLACE_ALL (-1)
#define KMP_PLACE_UNDEFINED (-2)
@@ -2507,6 +2518,10 @@ typedef struct KMP_ALIGN_CACHE kmp_base_info {
int th_last_place; /* last place in partition */
#endif
#endif
+#if OMP_50_ENABLED
+ int th_prev_level; /* previous level for affinity format */
+ int th_prev_num_threads; /* previous num_threads for affinity format */
+#endif
#if USE_ITT_BUILD
kmp_uint64 th_bar_arrive_time; /* arrival to barrier timestamp */
kmp_uint64 th_bar_min_time; /* minimum arrival time at the barrier */
@@ -2700,6 +2715,9 @@ typedef struct KMP_ALIGN_CACHE kmp_base_team {
int t_first_place; // first & last place in parent thread's partition.
int t_last_place; // Restore these values to master after par region.
#endif // OMP_40_ENABLED && KMP_AFFINITY_SUPPORTED
+#if OMP_50_ENABLED
+ int t_display_affinity;
+#endif
int t_size_changed; // team size was changed?: 0: no, 1: yes, -1: changed via
// omp_set_num_threads() call
#if OMP_50_ENABLED
@@ -3383,6 +3401,8 @@ extern void __kmp_runtime_destroy(void);
#if KMP_AFFINITY_SUPPORTED
extern char *__kmp_affinity_print_mask(char *buf, int buf_len,
kmp_affin_mask_t *mask);
+extern kmp_str_buf_t *__kmp_affinity_str_buf_mask(kmp_str_buf_t *buf,
+ kmp_affin_mask_t *mask);
extern void __kmp_affinity_initialize(void);
extern void __kmp_affinity_uninitialize(void);
extern void __kmp_affinity_set_init_mask(
@@ -3402,6 +3422,14 @@ extern void __kmp_balanced_affinity(kmp_info_t *th, int team_size);
extern int kmp_set_thread_affinity_mask_initial(void);
#endif
#endif /* KMP_AFFINITY_SUPPORTED */
+#if OMP_50_ENABLED
+// No need for KMP_AFFINITY_SUPPORTED guard as only one field in the
+// format string is for affinity, so platforms that do not support
+// affinity can still use the other fields, e.g., %n for num_threads
+extern size_t __kmp_aux_capture_affinity(int gtid, const char *format,
+ kmp_str_buf_t *buffer);
+extern void __kmp_aux_display_affinity(int gtid, const char *format);
+#endif
extern void __kmp_cleanup_hierarchy();
extern void __kmp_get_hierarchy(kmp_uint32 nproc, kmp_bstate_t *thr_bar);
@@ -3554,6 +3582,8 @@ KMP_EXPORT int __kmpc_invoke_task_func(int gtid);
#if OMP_40_ENABLED
extern int __kmp_invoke_teams_master(int gtid);
extern void __kmp_teams_master(int gtid);
+extern int __kmp_aux_get_team_num();
+extern int __kmp_aux_get_num_teams();
#endif
extern void __kmp_save_internal_controls(kmp_info_t *thread);
extern void __kmp_user_set_library(enum library_type arg);
diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp
index a9a21cf98c7..775862ebb7e 100644
--- a/openmp/runtime/src/kmp_affinity.cpp
+++ b/openmp/runtime/src/kmp_affinity.cpp
@@ -83,55 +83,135 @@ void KMPAffinity::destroy_api() {
}
}
+#define KMP_ADVANCE_SCAN(scan) \
+ while (*scan != '\0') { \
+ scan++; \
+ }
+
// Print the affinity mask to the character array in a pretty format.
+// The format is a comma separated list of non-negative integers or integer
+// ranges: e.g., 1,2,3-5,7,9-15
+// The format can also be the string "{<empty>}" if no bits are set in mask
char *__kmp_affinity_print_mask(char *buf, int buf_len,
kmp_affin_mask_t *mask) {
+ int start = 0, finish = 0, previous = 0;
+ bool first_range;
+ KMP_ASSERT(buf);
KMP_ASSERT(buf_len >= 40);
+ KMP_ASSERT(mask);
char *scan = buf;
char *end = buf + buf_len - 1;
- // Find first element / check for empty set.
- int i;
- i = mask->begin();
- if (i == mask->end()) {
+ // Check for empty set.
+ if (mask->begin() == mask->end()) {
KMP_SNPRINTF(scan, end - scan + 1, "{<empty>}");
- while (*scan != '\0')
- scan++;
+ KMP_ADVANCE_SCAN(scan);
KMP_ASSERT(scan <= end);
return buf;
}
- KMP_SNPRINTF(scan, end - scan + 1, "{%d", i);
- while (*scan != '\0')
- scan++;
- i++;
- for (; i != mask->end(); i = mask->next(i)) {
- if (!KMP_CPU_ISSET(i, mask)) {
- continue;
+ first_range = true;
+ start = mask->begin();
+ while (1) {
+ // Find next range
+ // [start, previous] is inclusive range of contiguous bits in mask
+ for (finish = mask->next(start), previous = start;
+ finish == previous + 1 && finish != mask->end();
+ finish = mask->next(finish)) {
+ previous = finish;
}
- // Check for buffer overflow. A string of the form ",<n>" will have at most
- // 10 characters, plus we want to leave room to print ",...}" if the set is
- // too large to print for a total of 15 characters. We already left room for
- // '\0' in setting end.
- if (end - scan < 15) {
- break;
+ // The first range does not need a comma printed before it, but the rest
+ // of the ranges do need a comma beforehand
+ if (!first_range) {
+ KMP_SNPRINTF(scan, end - scan + 1, "%s", ",");
+ KMP_ADVANCE_SCAN(scan);
+ } else {
+ first_range = false;
}
- KMP_SNPRINTF(scan, end - scan + 1, ",%-d", i);
- while (*scan != '\0')
- scan++;
- }
- if (i != mask->end()) {
- KMP_SNPRINTF(scan, end - scan + 1, ",...");
- while (*scan != '\0')
- scan++;
+ // Range with three or more contiguous bits in the affinity mask
+ if (previous - start > 1) {
+ KMP_SNPRINTF(scan, end - scan + 1, "%d-%d", static_cast<int>(start),
+ static_cast<int>(previous));
+ } else {
+ // Range with one or two contiguous bits in the affinity mask
+ KMP_SNPRINTF(scan, end - scan + 1, "%d", static_cast<int>(start));
+ KMP_ADVANCE_SCAN(scan);
+ if (previous - start > 0) {
+ KMP_SNPRINTF(scan, end - scan + 1, ",%d", static_cast<int>(previous));
+ }
+ }
+ KMP_ADVANCE_SCAN(scan);
+ // Start over with new start point
+ start = finish;
+ if (start == mask->end())
+ break;
+ // Check for overflow
+ if (end - scan < 2)
+ break;
}
- KMP_SNPRINTF(scan, end - scan + 1, "}");
- while (*scan != '\0')
- scan++;
+
+ // Check for overflow
KMP_ASSERT(scan <= end);
return buf;
}
+#undef KMP_ADVANCE_SCAN
+
+// Print the affinity mask to the string buffer object in a pretty format
+// The format is a comma separated list of non-negative integers or integer
+// ranges: e.g., 1,2,3-5,7,9-15
+// The format can also be the string "{<empty>}" if no bits are set in mask
+kmp_str_buf_t *__kmp_affinity_str_buf_mask(kmp_str_buf_t *buf,
+ kmp_affin_mask_t *mask) {
+ int start = 0, finish = 0, previous = 0;
+ bool first_range;
+ KMP_ASSERT(buf);
+ KMP_ASSERT(mask);
+
+ __kmp_str_buf_clear(buf);
+
+ // Check for empty set.
+ if (mask->begin() == mask->end()) {
+ __kmp_str_buf_print(buf, "%s", "{<empty>}");
+ return buf;
+ }
+
+ first_range = true;
+ start = mask->begin();
+ while (1) {
+ // Find next range
+ // [start, previous] is inclusive range of contiguous bits in mask
+ for (finish = mask->next(start), previous = start;
+ finish == previous + 1 && finish != mask->end();
+ finish = mask->next(finish)) {
+ previous = finish;
+ }
+
+ // The first range does not need a comma printed before it, but the rest
+ // of the ranges do need a comma beforehand
+ if (!first_range) {
+ __kmp_str_buf_print(buf, "%s", ",");
+ } else {
+ first_range = false;
+ }
+ // Range with three or more contiguous bits in the affinity mask
+ if (previous - start > 1) {
+ __kmp_str_buf_print(buf, "%d-%d", static_cast<int>(start),
+ static_cast<int>(previous));
+ } else {
+ // Range with one or two contiguous bits in the affinity mask
+ __kmp_str_buf_print(buf, "%d", static_cast<int>(start));
+ if (previous - start > 0) {
+ __kmp_str_buf_print(buf, ",%d", static_cast<int>(previous));
+ }
+ }
+ // Start over with new start point
+ start = finish;
+ if (start == mask->end())
+ break;
+ }
+ return buf;
+}
void __kmp_affinity_entire_machine_mask(kmp_affin_mask_t *mask) {
KMP_CPU_ZERO(mask);
diff --git a/openmp/runtime/src/kmp_barrier.cpp b/openmp/runtime/src/kmp_barrier.cpp
index 2b78b546a90..01782a5a29b 100644
--- a/openmp/runtime/src/kmp_barrier.cpp
+++ b/openmp/runtime/src/kmp_barrier.cpp
@@ -1698,6 +1698,11 @@ void __kmp_join_barrier(int gtid) {
if (__kmp_tasking_mode != tskm_immediate_exec) {
__kmp_task_team_wait(this_thr, team USE_ITT_BUILD_ARG(itt_sync_obj));
}
+#if OMP_50_ENABLED
+ if (__kmp_display_affinity) {
+ KMP_CHECK_UPDATE(team->t.t_display_affinity, 0);
+ }
+#endif
#if KMP_STATS_ENABLED
// Have master thread flag the workers to indicate they are now waiting for
// next parallel region, Also wake them up so they switch their timers to
@@ -1985,6 +1990,19 @@ void __kmp_fork_barrier(int gtid, int tid) {
}
#endif
#if OMP_50_ENABLED
+ // Perform the display affinity functionality
+ if (__kmp_display_affinity) {
+ if (team->t.t_display_affinity
+#if KMP_AFFINITY_SUPPORTED
+ || (__kmp_affinity_type == affinity_balanced && team->t.t_size_changed)
+#endif
+ ) {
+ // NULL means use the affinity-format-var ICV
+ __kmp_aux_display_affinity(gtid, NULL);
+ this_thr->th.th_prev_num_threads = team->t.t_nproc;
+ this_thr->th.th_prev_level = team->t.t_level;
+ }
+ }
if (!KMP_MASTER_TID(tid))
KMP_CHECK_UPDATE(this_thr->th.th_def_allocator, team->t.t_def_allocator);
#endif
diff --git a/openmp/runtime/src/kmp_csupport.cpp b/openmp/runtime/src/kmp_csupport.cpp
index 5cf074f8fe7..6a63834ce8b 100644
--- a/openmp/runtime/src/kmp_csupport.cpp
+++ b/openmp/runtime/src/kmp_csupport.cpp
@@ -1867,6 +1867,59 @@ int ompc_get_team_size(int level) {
return __kmp_get_team_size(__kmp_entry_gtid(), level);
}
+#if OMP_50_ENABLED
+/* OpenMP 5.0 Affinity Format API */
+
+void ompc_set_affinity_format(char const *format) {
+ if (!__kmp_init_serial) {
+ __kmp_serial_initialize();
+ }
+ __kmp_strncpy_truncate(__kmp_affinity_format, KMP_AFFINITY_FORMAT_SIZE,
+ format, KMP_STRLEN(format) + 1);
+}
+
+size_t ompc_get_affinity_format(char *buffer, size_t size) {
+ size_t format_size;
+ if (!__kmp_init_serial) {
+ __kmp_serial_initialize();
+ }
+ format_size = KMP_STRLEN(__kmp_affinity_format);
+ if (buffer && size) {
+ __kmp_strncpy_truncate(buffer, size, __kmp_affinity_format,
+ format_size + 1);
+ }
+ return format_size;
+}
+
+void ompc_display_affinity(char const *format) {
+ int gtid;
+ if (!TCR_4(__kmp_init_middle)) {
+ __kmp_middle_initialize();
+ }
+ gtid = __kmp_get_gtid();
+ __kmp_aux_display_affinity(gtid, format);
+}
+
+size_t ompc_capture_affinity(char *buffer, size_t buf_size,
+ char const *format) {
+ int gtid;
+ size_t num_required;
+ kmp_str_buf_t capture_buf;
+ if (!TCR_4(__kmp_init_middle)) {
+ __kmp_middle_initialize();
+ }
+ gtid = __kmp_get_gtid();
+ __kmp_str_buf_init(&capture_buf);
+ num_required = __kmp_aux_capture_affinity(gtid, format, &capture_buf);
+ if (buffer && buf_size) {
+ __kmp_strncpy_truncate(buffer, buf_size, capture_buf.str,
+ capture_buf.used + 1);
+ }
+ __kmp_str_buf_free(&capture_buf);
+ return num_required;
+}
+#endif /* OMP_50_ENABLED */
+
void kmpc_set_stacksize(int arg) {
// __kmp_aux_set_stacksize initializes the library if needed
__kmp_aux_set_stacksize(arg);
diff --git a/openmp/runtime/src/kmp_ftn_entry.h b/openmp/runtime/src/kmp_ftn_entry.h
index c9519014ebd..2d349f0398b 100644
--- a/openmp/runtime/src/kmp_ftn_entry.h
+++ b/openmp/runtime/src/kmp_ftn_entry.h
@@ -21,6 +21,12 @@
#include "kmp_i18n.h"
+#if OMP_50_ENABLED
+// For affinity format functions
+#include "kmp_io.h"
+#include "kmp_str.h"
+#endif
+
#if OMPT_SUPPORT
#include "ompt-specific.h"
#endif
@@ -389,6 +395,137 @@ void FTN_STDCALL FTN_FREE(void *ptr, const omp_allocator_t *allocator) {
__kmpc_free(__kmp_entry_gtid(), ptr, allocator);
#endif
}
+
+/* OpenMP 5.0 affinity format support */
+
+#ifndef KMP_STUB
+static void __kmp_fortran_strncpy_truncate(char *buffer, size_t buf_size,
+ char const *csrc, size_t csrc_size) {
+ size_t capped_src_size = csrc_size;
+ if (csrc_size >= buf_size) {
+ capped_src_size = buf_size - 1;
+ }
+ KMP_STRNCPY_S(buffer, buf_size, csrc, capped_src_size);
+ if (csrc_size >= buf_size) {
+ KMP_DEBUG_ASSERT(buffer[buf_size - 1] == '\0');
+ buffer[buf_size - 1] = csrc[buf_size - 1];
+ } else {
+ for (size_t i = csrc_size; i < buf_size; ++i)
+ buffer[i] = ' ';
+ }
+}
+
+// Convert a Fortran string to a C string by adding null byte
+class ConvertedString {
+ char *buf;
+ kmp_info_t *th;
+
+public:
+ ConvertedString(char const *fortran_str, size_t size) {
+ th = __kmp_get_thread();
+ buf = (char *)__kmp_thread_malloc(th, size + 1);
+ KMP_STRNCPY_S(buf, size + 1, fortran_str, size);
+ buf[size] = '\0';
+ }
+ ~ConvertedString() { __kmp_thread_free(th, buf); }
+ const char *get() const { return buf; }
+};
+#endif // KMP_STUB
+
+/*
+ * Set the value of the affinity-format-var ICV on the current device to the
+ * format specified in the argument.
+*/
+void FTN_STDCALL FTN_SET_AFFINITY_FORMAT(char const *format, size_t size) {
+#ifdef KMP_STUB
+ return;
+#else
+ if (!__kmp_init_serial) {
+ __kmp_serial_initialize();
+ }
+ ConvertedString cformat(format, size);
+ // Since the __kmp_affinity_format variable is a C string, do not
+ // use the fortran strncpy function
+ __kmp_strncpy_truncate(__kmp_affinity_format, KMP_AFFINITY_FORMAT_SIZE,
+ cformat.get(), KMP_STRLEN(cformat.get()));
+#endif
+}
+
+/*
+ * Returns the number of characters required to hold the entire affinity format
+ * specification (not including null byte character) and writes the value of the
+ * affinity-format-var ICV on the current device to buffer. If the return value
+ * is larger than size, the affinity format specification is truncated.
+*/
+size_t FTN_STDCALL FTN_GET_AFFINITY_FORMAT(char *buffer, size_t size) {
+#ifdef KMP_STUB
+ return 0;
+#else
+ size_t format_size;
+ if (!__kmp_init_serial) {
+ __kmp_serial_initialize();
+ }
+ format_size = KMP_STRLEN(__kmp_affinity_format);
+ if (buffer && size) {
+ __kmp_fortran_strncpy_truncate(buffer, size, __kmp_affinity_format,
+ format_size);
+ }
+ return format_size;
+#endif
+}
+
+/*
+ * Prints the thread affinity information of the current thread in the format
+ * specified by the format argument. If the format is NULL or a zero-length
+ * string, the value of the affinity-format-var ICV is used.
+*/
+void FTN_STDCALL FTN_DISPLAY_AFFINITY(char const *format, size_t size) {
+#ifdef KMP_STUB
+ return;
+#else
+ int gtid;
+ if (!TCR_4(__kmp_init_middle)) {
+ __kmp_middle_initialize();
+ }
+ gtid = __kmp_get_gtid();
+ ConvertedString cformat(format, size);
+ __kmp_aux_display_affinity(gtid, cformat.get());
+#endif
+}
+
+/*
+ * Returns the number of characters required to hold the entire affinity format
+ * specification (not including null byte) and prints the thread affinity
+ * information of the current thread into the character string buffer with the
+ * size of size in the format specified by the format argument. If the format is
+ * NULL or a zero-length string, the value of the affinity-format-var ICV is
+ * used. The buffer must be allocated prior to calling the routine. If the
+ * return value is larger than size, the affinity format specification is
+ * truncated.
+*/
+size_t FTN_STDCALL FTN_CAPTURE_AFFINITY(char *buffer, char const *format,
+ size_t buf_size, size_t for_size) {
+#if defined(KMP_STUB)
+ return 0;
+#else
+ int gtid;
+ size_t num_required;
+ kmp_str_buf_t capture_buf;
+ if (!TCR_4(__kmp_init_middle)) {
+ __kmp_middle_initialize();
+ }
+ gtid = __kmp_get_gtid();
+ __kmp_str_buf_init(&capture_buf);
+ ConvertedString cformat(format, for_size);
+ num_required = __kmp_aux_capture_affinity(gtid, cformat.get(), &capture_buf);
+ if (buffer && buf_size) {
+ __kmp_fortran_strncpy_truncate(buffer, buf_size, capture_buf.str,
+ capture_buf.used);
+ }
+ __kmp_str_buf_free(&capture_buf);
+ return num_required;
+#endif
+}
#endif /* OMP_50_ENABLED */
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_THREAD_NUM)(void) {
@@ -778,34 +915,7 @@ int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_TEAMS)(void) {
#ifdef KMP_STUB
return 1;
#else
- kmp_info_t *thr = __kmp_entry_thread();
- if (thr->th.th_teams_microtask) {
- kmp_team_t *team = thr->th.th_team;
- int tlevel = thr->th.th_teams_level;
- int ii = team->t.t_level; // the level of the teams construct
- int dd = team->t.t_serialized;
- int level = tlevel + 1;
- KMP_DEBUG_ASSERT(ii >= tlevel);
- while (ii > level) {
- for (dd = team->t.t_serialized; (dd > 0) && (ii > level); dd--, ii--) {
- }
- if (team->t.t_serialized && (!dd)) {
- team = team->t.t_parent;
- continue;
- }
- if (ii > level) {
- team = team->t.t_parent;
- ii--;
- }
- }
- if (dd > 1) {
- return 1; // teams region is serialized ( 1 team of 1 thread ).
- } else {
- return team->t.t_parent->t.t_nproc;
- }
- } else {
- return 1;
- }
+ return __kmp_aux_get_num_teams();
#endif
}
@@ -813,34 +923,7 @@ int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_TEAM_NUM)(void) {
#ifdef KMP_STUB
return 0;
#else
- kmp_info_t *thr = __kmp_entry_thread();
- if (thr->th.th_teams_microtask) {
- kmp_team_t *team = thr->th.th_team;
- int tlevel = thr->th.th_teams_level; // the level of the teams construct
- int ii = team->t.t_level;
- int dd = team->t.t_serialized;
- int level = tlevel + 1;
- KMP_DEBUG_ASSERT(ii >= tlevel);
- while (ii > level) {
- for (dd = team->t.t_serialized; (dd > 0) && (ii > level); dd--, ii--) {
- }
- if (team->t.t_serialized && (!dd)) {
- team = team->t.t_parent;
- continue;
- }
- if (ii > level) {
- team = team->t.t_parent;
- ii--;
- }
- }
- if (dd > 1) {
- return 0; // teams region is serialized ( 1 team of 1 thread ).
- } else {
- return team->t.t_master_tid;
- }
- } else {
- return 0;
- }
+ return __kmp_aux_get_team_num();
#endif
}
diff --git a/openmp/runtime/src/kmp_ftn_os.h b/openmp/runtime/src/kmp_ftn_os.h
index 5d0aaa29697..47188fcc4d6 100644
--- a/openmp/runtime/src/kmp_ftn_os.h
+++ b/openmp/runtime/src/kmp_ftn_os.h
@@ -139,6 +139,10 @@
#define FTN_GET_DEFAULT_ALLOCATOR omp_get_default_allocator
#define FTN_ALLOC omp_alloc
#define FTN_FREE omp_free
+#define FTN_SET_AFFINITY_FORMAT omp_set_affinity_format
+#define FTN_GET_AFFINITY_FORMAT omp_get_affinity_format
+#define FTN_DISPLAY_AFFINITY omp_display_affinity
+#define FTN_CAPTURE_AFFINITY omp_capture_affinity
#endif
#endif /* KMP_FTN_PLAIN */
@@ -265,6 +269,10 @@
#define FTN_GET_DEFAULT_ALLOCATOR omp_get_default_allocator_
#define FTN_ALLOC omp_alloc_
#define FTN_FREE omp_free_
+#define FTN_SET_AFFINITY_FORMAT omp_set_affinity_format_
+#define FTN_GET_AFFINITY_FORMAT omp_get_affinity_format_
+#define FTN_DISPLAY_AFFINITY omp_display_affinity_
+#define FTN_CAPTURE_AFFINITY omp_capture_affinity_
#endif
#endif /* KMP_FTN_APPEND */
@@ -391,6 +399,10 @@
#define FTN_GET_DEFAULT_ALLOCATOR OMP_GET_DEFAULT_ALLOCATOR
#define FTN_ALLOC OMP_ALLOC
#define FTN_FREE OMP_FREE
+#define FTN_SET_AFFINITY_FORMAT OMP_SET_AFFINITY_FORMAT
+#define FTN_GET_AFFINITY_FORMAT OMP_GET_AFFINITY_FORMAT
+#define FTN_DISPLAY_AFFINITY OMP_DISPLAY_AFFINITY
+#define FTN_CAPTURE_AFFINITY OMP_CAPTURE_AFFINITY
#endif
#endif /* KMP_FTN_UPPER */
@@ -517,6 +529,10 @@
#define FTN_GET_DEFAULT_ALLOCATOR OMP_GET_DEFAULT_ALLOCATOR_
#define FTN_ALLOC OMP_ALLOC_
#define FTN_FREE OMP_FREE_
+#define FTN_SET_AFFINITY_FORMAT OMP_SET_AFFINITY_FORMAT_
+#define FTN_GET_AFFINITY_FORMAT OMP_GET_AFFINITY_FORMAT_
+#define FTN_DISPLAY_AFFINITY OMP_DISPLAY_AFFINITY_
+#define FTN_CAPTURE_AFFINITY OMP_CAPTURE_AFFINITY_
#endif
#endif /* KMP_FTN_UAPPEND */
diff --git a/openmp/runtime/src/kmp_global.cpp b/openmp/runtime/src/kmp_global.cpp
index 34465de52a3..ef8a1160a9c 100644
--- a/openmp/runtime/src/kmp_global.cpp
+++ b/openmp/runtime/src/kmp_global.cpp
@@ -282,6 +282,11 @@ kmp_nested_proc_bind_t __kmp_nested_proc_bind = {NULL, 0, 0};
int __kmp_affinity_num_places = 0;
#endif
+#if OMP_50_ENABLED
+int __kmp_display_affinity = FALSE;
+char *__kmp_affinity_format = NULL;
+#endif // OMP_50_ENABLED
+
kmp_hws_item_t __kmp_hws_socket = {0, 0};
kmp_hws_item_t __kmp_hws_node = {0, 0};
kmp_hws_item_t __kmp_hws_tile = {0, 0};
diff --git a/openmp/runtime/src/kmp_io.cpp b/openmp/runtime/src/kmp_io.cpp
index 73508330b77..24c6e725aef 100644
--- a/openmp/runtime/src/kmp_io.cpp
+++ b/openmp/runtime/src/kmp_io.cpp
@@ -46,10 +46,7 @@ kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
#if KMP_OS_WINDOWS
-#ifdef KMP_DEBUG
-/* __kmp_stdout is used only for dev build */
static HANDLE __kmp_stdout = NULL;
-#endif
static HANDLE __kmp_stderr = NULL;
static int __kmp_console_exists = FALSE;
static kmp_str_buf_t __kmp_console_buf;
@@ -76,10 +73,7 @@ void __kmp_close_console(void) {
/* wait until user presses return before closing window */
/* TODO only close if a window was opened */
if (__kmp_console_exists) {
-#ifdef KMP_DEBUG
- /* standard out is used only in dev build */
__kmp_stdout = NULL;
-#endif
__kmp_stderr = NULL;
__kmp_str_buf_free(&__kmp_console_buf);
__kmp_console_exists = FALSE;
@@ -92,21 +86,17 @@ static void __kmp_redirect_output(void) {
__kmp_acquire_bootstrap_lock(&__kmp_console_lock);
if (!__kmp_console_exists) {
-#ifdef KMP_DEBUG
- /* standard out is used only in dev build */
HANDLE ho;
-#endif
HANDLE he;
__kmp_str_buf_init(&__kmp_console_buf);
AllocConsole();
-// We do not check the result of AllocConsole because
-// 1. the call is harmless
-// 2. it is not clear how to communicate failue
-// 3. we will detect failure later when we get handle(s)
+ // We do not check the result of AllocConsole because
+ // 1. the call is harmless
+ // 2. it is not clear how to communicate failue
+ // 3. we will detect failure later when we get handle(s)
-#ifdef KMP_DEBUG
ho = GetStdHandle(STD_OUTPUT_HANDLE);
if (ho == INVALID_HANDLE_VALUE || ho == NULL) {
@@ -118,7 +108,6 @@ static void __kmp_redirect_output(void) {
__kmp_stdout = ho; // temporary code, need new global for ho
}
-#endif
he = GetStdHandle(STD_ERROR_HANDLE);
if (he == INVALID_HANDLE_VALUE || he == NULL) {
@@ -137,22 +126,22 @@ static void __kmp_redirect_output(void) {
#else
#define __kmp_stderr (stderr)
+#define __kmp_stdout (stdout)
#endif /* KMP_OS_WINDOWS */
-void __kmp_vprintf(enum kmp_io __kmp_io, char const *format, va_list ap) {
+void __kmp_vprintf(enum kmp_io out_stream, char const *format, va_list ap) {
#if KMP_OS_WINDOWS
if (!__kmp_console_exists) {
__kmp_redirect_output();
}
- if (!__kmp_stderr && __kmp_io == kmp_err) {
+ if (!__kmp_stderr && out_stream == kmp_err) {
return;
}
-#ifdef KMP_DEBUG
- if (!__kmp_stdout && __kmp_io == kmp_out) {
+ if (!__kmp_stdout && out_stream == kmp_out) {
return;
}
-#endif
#endif /* KMP_OS_WINDOWS */
+ auto stream = ((out_stream == kmp_out) ? __kmp_stdout : __kmp_stderr);
if (__kmp_debug_buf && __kmp_debug_buffer != NULL) {
@@ -174,14 +163,14 @@ void __kmp_vprintf(enum kmp_io __kmp_io, char const *format, va_list ap) {
"overflow; increase "
"KMP_DEBUG_BUF_CHARS to %d\n",
chars + 1);
- WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used,
- &count, NULL);
+ WriteFile(stream, __kmp_console_buf.str, __kmp_console_buf.used, &count,
+ NULL);
__kmp_str_buf_clear(&__kmp_console_buf);
#else
- fprintf(__kmp_stderr, "OMP warning: Debugging buffer overflow; "
- "increase KMP_DEBUG_BUF_CHARS to %d\n",
+ fprintf(stream, "OMP warning: Debugging buffer overflow; "
+ "increase KMP_DEBUG_BUF_CHARS to %d\n",
chars + 1);
- fflush(__kmp_stderr);
+ fflush(stream);
#endif
__kmp_debug_buf_warn_chars = chars + 1;
}
@@ -196,15 +185,15 @@ void __kmp_vprintf(enum kmp_io __kmp_io, char const *format, va_list ap) {
__kmp_str_buf_print(&__kmp_console_buf, "pid=%d: ", (kmp_int32)getpid());
#endif
__kmp_str_buf_vprint(&__kmp_console_buf, format, ap);
- WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used,
- &count, NULL);
+ WriteFile(stream, __kmp_console_buf.str, __kmp_console_buf.used, &count,
+ NULL);
__kmp_str_buf_clear(&__kmp_console_buf);
#else
#ifdef KMP_DEBUG_PIDS
- fprintf(__kmp_stderr, "pid=%d: ", (kmp_int32)getpid());
+ fprintf(stream, "pid=%d: ", (kmp_int32)getpid());
#endif
- vfprintf(__kmp_stderr, format, ap);
- fflush(__kmp_stderr);
+ vfprintf(stream, format, ap);
+ fflush(stream);
#endif
}
}
@@ -228,3 +217,14 @@ void __kmp_printf_no_lock(char const *format, ...) {
va_end(ap);
}
+
+void __kmp_fprintf(enum kmp_io stream, char const *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+
+ __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
+ __kmp_vprintf(stream, format, ap);
+ __kmp_release_bootstrap_lock(&__kmp_stdio_lock);
+
+ va_end(ap);
+}
diff --git a/openmp/runtime/src/kmp_io.h b/openmp/runtime/src/kmp_io.h
index 84ac67b9f4d..dac7a42e2e4 100644
--- a/openmp/runtime/src/kmp_io.h
+++ b/openmp/runtime/src/kmp_io.h
@@ -26,9 +26,10 @@ extern kmp_bootstrap_lock_t __kmp_stdio_lock; /* Control stdio functions */
extern kmp_bootstrap_lock_t
__kmp_console_lock; /* Control console initialization */
-extern void __kmp_vprintf(enum kmp_io __kmp_io, char const *format, va_list ap);
+extern void __kmp_vprintf(enum kmp_io stream, char const *format, va_list ap);
extern void __kmp_printf(char const *format, ...);
extern void __kmp_printf_no_lock(char const *format, ...);
+extern void __kmp_fprintf(enum kmp_io stream, char const *format, ...);
extern void __kmp_close_console(void);
#ifdef __cplusplus
diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h
index 54daaf51c2f..3c2426bcae4 100644
--- a/openmp/runtime/src/kmp_os.h
+++ b/openmp/runtime/src/kmp_os.h
@@ -105,6 +105,7 @@ typedef long double _Quad;
#define KMP_USE_X87CONTROL 0
#if KMP_OS_WINDOWS
+#define KMP_END_OF_LINE "\r\n"
typedef char kmp_int8;
typedef unsigned char kmp_uint8;
typedef short kmp_int16;
@@ -140,6 +141,7 @@ typedef unsigned __int64 kmp_uintptr_t;
#endif /* KMP_OS_WINDOWS */
#if KMP_OS_UNIX
+#define KMP_END_OF_LINE "\n"
typedef char kmp_int8;
typedef unsigned char kmp_uint8;
typedef short kmp_int16;
diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp
index 5fb6e2623ee..f0b81dd50c9 100644
--- a/openmp/runtime/src/kmp_runtime.cpp
+++ b/openmp/runtime/src/kmp_runtime.cpp
@@ -1092,6 +1092,19 @@ static void __kmp_fork_team_threads(kmp_root_t *root, kmp_team_t *team,
#endif
}
+#if OMP_50_ENABLED
+ if (__kmp_display_affinity && team->t.t_display_affinity != 1) {
+ for (i = 0; i < team->t.t_nproc; i++) {
+ kmp_info_t *thr = team->t.t_threads[i];
+ if (thr->th.th_prev_num_threads != team->t.t_nproc ||
+ thr->th.th_prev_level != team->t.t_level) {
+ team->t.t_display_affinity = 1;
+ break;
+ }
+ }
+ }
+#endif
+
KMP_MB();
}
@@ -1382,6 +1395,20 @@ void __kmp_serialized_parallel(ident_t *loc, kmp_int32 global_tid) {
KMP_CHECK_UPDATE(serial_team->t.t_cancel_request, cancel_noreq);
#endif
+#if OMP_50_ENABLED
+ // Perform the display affinity functionality for
+ // serialized parallel regions
+ if (__kmp_display_affinity) {
+ if (this_thr->th.th_prev_level != serial_team->t.t_level ||
+ this_thr->th.th_prev_num_threads != 1) {
+ // NULL means use the affinity-format-var ICV
+ __kmp_aux_display_affinity(global_tid, NULL);
+ this_thr->th.th_prev_level = serial_team->t.t_level;
+ this_thr->th.th_prev_num_threads = 1;
+ }
+ }
+#endif
+
if (__kmp_env_consistency_check)
__kmp_push_parallel(global_tid, NULL);
#if OMPT_SUPPORT
@@ -1948,7 +1975,7 @@ int __kmp_fork_call(ident_t *loc, int gtid,
KA_TRACE(20, ("__kmp_fork_call: T#%d serial exit\n", gtid));
KMP_MB();
return FALSE;
- }
+ } // if (nthreads == 1)
// GEH: only modify the executing flag in the case when not serialized
// serialized case is handled in kmpc_serialized_parallel
@@ -3819,6 +3846,8 @@ int __kmp_register_root(int initial_thread) {
#endif /* KMP_AFFINITY_SUPPORTED */
#if OMP_50_ENABLED
root_thread->th.th_def_allocator = __kmp_def_allocator;
+ root_thread->th.th_prev_level = 0;
+ root_thread->th.th_prev_num_threads = 1;
#endif
__kmp_root_counter++;
@@ -4360,6 +4389,8 @@ kmp_info_t *__kmp_allocate_thread(kmp_root_t *root, kmp_team_t *team,
#endif
#if OMP_50_ENABLED
new_thr->th.th_def_allocator = __kmp_def_allocator;
+ new_thr->th.th_prev_level = 0;
+ new_thr->th.th_prev_num_threads = 1;
#endif
TCW_4(new_thr->th.th_in_pool, FALSE);
@@ -4548,6 +4579,12 @@ static void __kmp_partition_places(kmp_team_t *team, int update_master_only) {
th->th.th_first_place = first_place;
th->th.th_last_place = last_place;
th->th.th_new_place = masters_place;
+#if OMP_50_ENABLED
+ if (__kmp_display_affinity && masters_place != th->th.th_current_place &&
+ team->t.t_display_affinity != 1) {
+ team->t.t_display_affinity = 1;
+ }
+#endif
KA_TRACE(100, ("__kmp_partition_places: master: T#%d(%d:%d) place %d "
"partition = [%d,%d]\n",
@@ -4581,6 +4618,12 @@ static void __kmp_partition_places(kmp_team_t *team, int update_master_only) {
th->th.th_first_place = first_place;
th->th.th_last_place = last_place;
th->th.th_new_place = place;
+#if OMP_50_ENABLED
+ if (__kmp_display_affinity && place != th->th.th_current_place &&
+ team->t.t_display_affinity != 1) {
+ team->t.t_display_affinity = 1;
+ }
+#endif
KA_TRACE(100, ("__kmp_partition_places: close: T#%d(%d:%d) place %d "
"partition = [%d,%d]\n",
@@ -4602,6 +4645,12 @@ static void __kmp_partition_places(kmp_team_t *team, int update_master_only) {
th->th.th_first_place = first_place;
th->th.th_last_place = last_place;
th->th.th_new_place = place;
+#if OMP_50_ENABLED
+ if (__kmp_display_affinity && place != th->th.th_current_place &&
+ team->t.t_display_affinity != 1) {
+ team->t.t_display_affinity = 1;
+ }
+#endif
s_count++;
if ((s_count == S) && rem && (gap_ct == gap)) {
@@ -4670,6 +4719,12 @@ static void __kmp_partition_places(kmp_team_t *team, int update_master_only) {
th->th.th_first_place = place;
th->th.th_new_place = place;
+#if OMP_50_ENABLED
+ if (__kmp_display_affinity && place != th->th.th_current_place &&
+ team->t.t_display_affinity != 1) {
+ team->t.t_display_affinity = 1;
+ }
+#endif
s_count = 1;
while (s_count < S) {
if (place == last_place) {
@@ -4761,7 +4816,12 @@ static void __kmp_partition_places(kmp_team_t *team, int update_master_only) {
th->th.th_first_place = first;
th->th.th_new_place = place;
th->th.th_last_place = last;
-
+#if OMP_50_ENABLED
+ if (__kmp_display_affinity && place != th->th.th_current_place &&
+ team->t.t_display_affinity != 1) {
+ team->t.t_display_affinity = 1;
+ }
+#endif
KA_TRACE(100,
("__kmp_partition_places: spread: T#%d(%d:%d) place %d "
"partition = [%d,%d], spacing = %.4f\n",
@@ -4790,6 +4850,12 @@ static void __kmp_partition_places(kmp_team_t *team, int update_master_only) {
th->th.th_first_place = place;
th->th.th_last_place = place;
th->th.th_new_place = place;
+#if OMP_50_ENABLED
+ if (__kmp_display_affinity && place != th->th.th_current_place &&
+ team->t.t_display_affinity != 1) {
+ team->t.t_display_affinity = 1;
+ }
+#endif
s_count++;
if ((s_count == S) && rem && (gap_ct == gap)) {
@@ -7410,6 +7476,12 @@ void __kmp_cleanup(void) {
__kmp_nested_proc_bind.bind_types = NULL;
__kmp_nested_proc_bind.size = 0;
__kmp_nested_proc_bind.used = 0;
+#if OMP_50_ENABLED
+ if (__kmp_affinity_format) {
+ KMP_INTERNAL_FREE(__kmp_affinity_format);
+ __kmp_affinity_format = NULL;
+ }
+#endif
__kmp_i18n_catclose();
@@ -7566,6 +7638,339 @@ void __kmp_aux_set_library(enum library_type arg) {
}
}
+/* Getting team information common for all team API */
+// Returns NULL if not in teams construct
+static kmp_team_t *__kmp_aux_get_team_info(int &teams_serialized) {
+ kmp_info_t *thr = __kmp_entry_thread();
+ teams_serialized = 0;
+ if (thr->th.th_teams_microtask) {
+ kmp_team_t *team = thr->th.th_team;
+ int tlevel = thr->th.th_teams_level; // the level of the teams construct
+ int ii = team->t.t_level;
+ teams_serialized = team->t.t_serialized;
+ int level = tlevel + 1;
+ KMP_DEBUG_ASSERT(ii >= tlevel);
+ while (ii > level) {
+ for (teams_serialized = team->t.t_serialized;
+ (teams_serialized > 0) && (ii > level); teams_serialized--, ii--) {
+ }
+ if (team->t.t_serialized && (!teams_serialized)) {
+ team = team->t.t_parent;
+ continue;
+ }
+ if (ii > level) {
+ team = team->t.t_parent;
+ ii--;
+ }
+ }
+ return team;
+ }
+ return NULL;
+}
+
+int __kmp_aux_get_team_num() {
+ int serialized;
+ kmp_team_t *team = __kmp_aux_get_team_info(serialized);
+ if (team) {
+ if (serialized > 1) {
+ return 0; // teams region is serialized ( 1 team of 1 thread ).
+ } else {
+ return team->t.t_master_tid;
+ }
+ }
+ return 0;
+}
+
+int __kmp_aux_get_num_teams() {
+ int serialized;
+ kmp_team_t *team = __kmp_aux_get_team_info(serialized);
+ if (team) {
+ if (serialized > 1) {
+ return 1;
+ } else {
+ return team->t.t_parent->t.t_nproc;
+ }
+ }
+ return 1;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if OMP_50_ENABLED
+/*
+ * Affinity Format Parser
+ *
+ * Field is in form of: %[[[0].]size]type
+ * % and type are required (%% means print a literal '%')
+ * type is either single char or long name surrounded by {},
+ * e.g., N or {num_threads}
+ * 0 => leading zeros
+ * . => right justified when size is specified
+ * by default output is left justified
+ * size is the *minimum* field length
+ * All other characters are printed as is
+ *
+ * Available field types:
+ * L {thread_level} - omp_get_level()
+ * n {thread_num} - omp_get_thread_num()
+ * h {host} - name of host machine
+ * P {process_id} - process id (integer)
+ * T {thread_identifier} - native thread identifier (integer)
+ * N {num_threads} - omp_get_num_threads()
+ * A {ancestor_tnum} - omp_get_ancestor_thread_num(omp_get_level()-1)
+ * a {thread_affinity} - comma separated list of integers or integer ranges
+ * (values of affinity mask)
+ *
+ * Implementation-specific field types can be added
+ * If a type is unknown, print "undefined"
+*/
+
+// Structure holding the short name, long name, and corresponding data type
+// for snprintf. A table of these will represent the entire valid keyword
+// field types.
+typedef struct kmp_affinity_format_field_t {
+ char short_name; // from spec e.g., L -> thread level
+ const char *long_name; // from spec thread_level -> thread level
+ char field_format; // data type for snprintf (typically 'd' or 's'
+ // for integer or string)
+} kmp_affinity_format_field_t;
+
+static const kmp_affinity_format_field_t __kmp_affinity_format_table[] = {
+#if KMP_AFFINITY_SUPPORTED
+ {'A', "thread_affinity", 's'},
+#endif
+ {'t', "team_num", 'd'},
+ {'T', "num_teams", 'd'},
+ {'L', "nesting_level", 'd'},
+ {'n', "thread_num", 'd'},
+ {'N', "num_threads", 'd'},
+ {'a', "ancestor_tnum", 'd'},
+ {'H', "host", 's'},
+ {'P', "process_id", 'd'},
+ {'i', "native_thread_id", 'd'}};
+
+// Return the number of characters it takes to hold field
+static int __kmp_aux_capture_affinity_field(int gtid, const kmp_info_t *th,
+ const char **ptr,
+ kmp_str_buf_t *field_buffer) {
+ int rc, format_index, field_value;
+ const char *width_left, *width_right;
+ bool pad_zeros, right_justify, parse_long_name, found_valid_name;
+ static const int FORMAT_SIZE = 20;
+ char format[FORMAT_SIZE] = {0};
+ char absolute_short_name = 0;
+
+ KMP_DEBUG_ASSERT(gtid >= 0);
+ KMP_DEBUG_ASSERT(th);
+ KMP_DEBUG_ASSERT(**ptr == '%');
+ KMP_DEBUG_ASSERT(field_buffer);
+
+ __kmp_str_buf_clear(field_buffer);
+
+ // Skip the initial %
+ (*ptr)++;
+
+ // Check for %% first
+ if (**ptr == '%') {
+ __kmp_str_buf_cat(field_buffer, "%", 1);
+ (*ptr)++; // skip over the second %
+ return 1;
+ }
+
+ // Parse field modifiers if they are present
+ pad_zeros = false;
+ if (**ptr == '0') {
+ pad_zeros = true;
+ (*ptr)++; // skip over 0
+ }
+ right_justify = false;
+ if (**ptr == '.') {
+ right_justify = true;
+ (*ptr)++; // skip over .
+ }
+ // Parse width of field: [width_left, width_right)
+ width_left = width_right = NULL;
+ if (**ptr >= '0' && **ptr <= '9') {
+ width_left = *ptr;
+ SKIP_DIGITS(*ptr);
+ width_right = *ptr;
+ }
+
+ // Create the format for KMP_SNPRINTF based on flags parsed above
+ format_index = 0;
+ format[format_index++] = '%';
+ if (!right_justify)
+ format[format_index++] = '-';
+ if (pad_zeros)
+ format[format_index++] = '0';
+ if (width_left && width_right) {
+ int i = 0;
+ // Only allow 8 digit number widths.
+ // This also prevents overflowing format variable
+ while (i < 8 && width_left < width_right) {
+ format[format_index++] = *width_left;
+ width_left++;
+ i++;
+ }
+ }
+
+ // Parse a name (long or short)
+ // Canonicalize the name into absolute_short_name
+ found_valid_name = false;
+ parse_long_name = (**ptr == '{');
+ if (parse_long_name)
+ (*ptr)++; // skip initial left brace
+ for (size_t i = 0; i < sizeof(__kmp_affinity_format_table) /
+ sizeof(__kmp_affinity_format_table[0]);
+ ++i) {
+ char short_name = __kmp_affinity_format_table[i].short_name;
+ const char *long_name = __kmp_affinity_format_table[i].long_name;
+ char field_format = __kmp_affinity_format_table[i].field_format;
+ if (parse_long_name) {
+ int length = KMP_STRLEN(long_name);
+ if (strncmp(*ptr, long_name, length) == 0) {
+ found_valid_name = true;
+ (*ptr) += length; // skip the long name
+ }
+ } else if (**ptr == short_name) {
+ found_valid_name = true;
+ (*ptr)++; // skip the short name
+ }
+ if (found_valid_name) {
+ format[format_index++] = field_format;
+ format[format_index++] = '\0';
+ absolute_short_name = short_name;
+ break;
+ }
+ }
+ if (parse_long_name) {
+ if (**ptr != '}') {
+ absolute_short_name = 0;
+ } else {
+ (*ptr)++; // skip over the right brace
+ }
+ }
+
+ // Attempt to fill the buffer with the requested
+ // value using snprintf within __kmp_str_buf_print()
+ switch (absolute_short_name) {
+ case 't':
+ rc = __kmp_str_buf_print(field_buffer, format, __kmp_aux_get_team_num());
+ break;
+ case 'T':
+ rc = __kmp_str_buf_print(field_buffer, format, __kmp_aux_get_num_teams());
+ break;
+ case 'L':
+ rc = __kmp_str_buf_print(field_buffer, format, th->th.th_team->t.t_level);
+ break;
+ case 'n':
+ rc = __kmp_str_buf_print(field_buffer, format, __kmp_tid_from_gtid(gtid));
+ break;
+ case 'H': {
+ static const int BUFFER_SIZE = 256;
+ char buf[BUFFER_SIZE];
+ __kmp_expand_host_name(buf, BUFFER_SIZE);
+ rc = __kmp_str_buf_print(field_buffer, format, buf);
+ } break;
+ case 'P':
+ rc = __kmp_str_buf_print(field_buffer, format, getpid());
+ break;
+ case 'i':
+ rc = __kmp_str_buf_print(field_buffer, format, __kmp_gettid());
+ break;
+ case 'N':
+ rc = __kmp_str_buf_print(field_buffer, format, th->th.th_team->t.t_nproc);
+ break;
+ case 'a':
+ field_value =
+ __kmp_get_ancestor_thread_num(gtid, th->th.th_team->t.t_level - 1);
+ rc = __kmp_str_buf_print(field_buffer, format, field_value);
+ break;
+#if KMP_AFFINITY_SUPPORTED
+ case 'A': {
+ kmp_str_buf_t buf;
+ __kmp_str_buf_init(&buf);
+ __kmp_affinity_str_buf_mask(&buf, th->th.th_affin_mask);
+ rc = __kmp_str_buf_print(field_buffer, format, buf.str);
+ __kmp_str_buf_free(&buf);
+ } break;
+#endif
+ default:
+ // According to spec, If an implementation does not have info for field
+ // type, then "undefined" is printed
+ rc = __kmp_str_buf_print(field_buffer, "%s", "undefined");
+ // Skip the field
+ if (parse_long_name) {
+ SKIP_TOKEN(*ptr);
+ if (**ptr == '}')
+ (*ptr)++;
+ } else {
+ (*ptr)++;
+ }
+ }
+
+ KMP_ASSERT(format_index <= FORMAT_SIZE);
+ return rc;
+}
+
+/*
+ * Return number of characters needed to hold the affinity string
+ * (not including null byte character)
+ * The resultant string is printed to buffer, which the caller can then
+ * handle afterwards
+*/
+size_t __kmp_aux_capture_affinity(int gtid, const char *format,
+ kmp_str_buf_t *buffer) {
+ const char *parse_ptr;
+ size_t retval;
+ const kmp_info_t *th;
+ kmp_str_buf_t field;
+
+ KMP_DEBUG_ASSERT(buffer);
+ KMP_DEBUG_ASSERT(gtid >= 0);
+
+ __kmp_str_buf_init(&field);
+ __kmp_str_buf_clear(buffer);
+
+ th = __kmp_threads[gtid];
+ retval = 0;
+
+ // If format is NULL or zero-length string, then we use
+ // affinity-format-var ICV
+ parse_ptr = format;
+ if (parse_ptr == NULL || *parse_ptr == '\0') {
+ parse_ptr = __kmp_affinity_format;
+ }
+ KMP_DEBUG_ASSERT(parse_ptr);
+
+ while (*parse_ptr != '\0') {
+ // Parse a field
+ if (*parse_ptr == '%') {
+ // Put field in the buffer
+ int rc = __kmp_aux_capture_affinity_field(gtid, th, &parse_ptr, &field);
+ __kmp_str_buf_catbuf(buffer, &field);
+ retval += rc;
+ } else {
+ // Put literal character in buffer
+ __kmp_str_buf_cat(buffer, parse_ptr, 1);
+ retval++;
+ parse_ptr++;
+ }
+ }
+ __kmp_str_buf_free(&field);
+ return retval;
+}
+
+// Displays the affinity string to stdout
+void __kmp_aux_display_affinity(int gtid, const char *format) {
+ kmp_str_buf_t buf;
+ __kmp_str_buf_init(&buf);
+ __kmp_aux_capture_affinity(gtid, format, &buf);
+ __kmp_fprintf(kmp_out, "%s" KMP_END_OF_LINE, buf.str);
+ __kmp_str_buf_free(&buf);
+}
+#endif // OMP_50_ENABLED
+
/* ------------------------------------------------------------------------ */
void __kmp_aux_set_blocktime(int arg, kmp_info_t *thread, int tid) {
diff --git a/openmp/runtime/src/kmp_safe_c_api.h b/openmp/runtime/src/kmp_safe_c_api.h
index 7dfd2783cb0..d894fe3e026 100644
--- a/openmp/runtime/src/kmp_safe_c_api.h
+++ b/openmp/runtime/src/kmp_safe_c_api.h
@@ -11,6 +11,9 @@
#ifndef KMP_SAFE_C_API_H
#define KMP_SAFE_C_API_H
+#include "kmp_platform.h"
+#include <string.h>
+
// Replacement for banned C API
// Not every unsafe call listed here is handled now, but keeping everything
@@ -57,4 +60,16 @@
#endif // KMP_OS_WINDOWS
+// Offer truncated version of strncpy
+static inline void __kmp_strncpy_truncate(char *buffer, size_t buf_size,
+ char const *src, size_t src_size) {
+ if (src_size >= buf_size) {
+ src_size = buf_size - 1;
+ KMP_STRNCPY_S(buffer, buf_size, src, src_size);
+ buffer[buf_size - 1] = '\0';
+ } else {
+ KMP_STRNCPY_S(buffer, buf_size, src, src_size);
+ }
+}
+
#endif // KMP_SAFE_C_API_H
diff --git a/openmp/runtime/src/kmp_settings.cpp b/openmp/runtime/src/kmp_settings.cpp
index 37690a2c9e3..6d049e4b923 100644
--- a/openmp/runtime/src/kmp_settings.cpp
+++ b/openmp/runtime/src/kmp_settings.cpp
@@ -3252,7 +3252,29 @@ static void __kmp_stg_print_proc_bind(kmp_str_buf_t *buffer, char const *name,
#endif /* OMP_40_ENABLED */
#if OMP_50_ENABLED
-
+static void __kmp_stg_parse_display_affinity(char const *name,
+ char const *value, void *data) {
+ __kmp_stg_parse_bool(name, value, &__kmp_display_affinity);
+}
+static void __kmp_stg_print_display_affinity(kmp_str_buf_t *buffer,
+ char const *name, void *data) {
+ __kmp_stg_print_bool(buffer, name, __kmp_display_affinity);
+}
+static void __kmp_stg_parse_affinity_format(char const *name, char const *value,
+ void *data) {
+ size_t length = KMP_STRLEN(value);
+ __kmp_strncpy_truncate(__kmp_affinity_format, KMP_AFFINITY_FORMAT_SIZE, value,
+ length);
+}
+static void __kmp_stg_print_affinity_format(kmp_str_buf_t *buffer,
+ char const *name, void *data) {
+ if (__kmp_env_format) {
+ KMP_STR_BUF_PRINT_NAME_EX(name);
+ } else {
+ __kmp_str_buf_print(buffer, " %s='", name);
+ }
+ __kmp_str_buf_print(buffer, "%s'\n", __kmp_affinity_format);
+}
// OMP_ALLOCATOR sets default allocator
static void __kmp_stg_parse_allocator(char const *name, char const *value,
void *data) {
@@ -4879,7 +4901,12 @@ static kmp_setting_t __kmp_stg_table[] = {
#endif
#endif // KMP_AFFINITY_SUPPORTED
-
+#if OMP_50_ENABLED
+ {"OMP_DISPLAY_AFFINITY", __kmp_stg_parse_display_affinity,
+ __kmp_stg_print_display_affinity, NULL, 0, 0},
+ {"OMP_AFFINITY_FORMAT", __kmp_stg_parse_affinity_format,
+ __kmp_stg_print_affinity_format, NULL, 0, 0},
+#endif
{"KMP_INIT_AT_FORK", __kmp_stg_parse_init_at_fork,
__kmp_stg_print_init_at_fork, NULL, 0, 0},
{"KMP_SCHEDULE", __kmp_stg_parse_schedule, __kmp_stg_print_schedule, NULL,
@@ -5409,6 +5436,21 @@ void __kmp_env_initialize(char const *string) {
}
#endif /* OMP_40_ENABLED */
+#if OMP_50_ENABLED
+ // Set up the affinity format ICV
+ // Grab the default affinity format string from the message catalog
+ kmp_msg_t m =
+ __kmp_msg_format(kmp_i18n_msg_AffFormatDefault, "%P", "%i", "%n", "%A");
+ KMP_DEBUG_ASSERT(KMP_STRLEN(m.str) < KMP_AFFINITY_FORMAT_SIZE);
+
+ if (__kmp_affinity_format == NULL) {
+ __kmp_affinity_format =
+ (char *)KMP_INTERNAL_MALLOC(sizeof(char) * KMP_AFFINITY_FORMAT_SIZE);
+ }
+ KMP_STRCPY_S(__kmp_affinity_format, KMP_AFFINITY_FORMAT_SIZE, m.str);
+ __kmp_str_free(&m.str);
+#endif
+
// Now process all of the settings.
for (i = 0; i < block.count; ++i) {
__kmp_stg_parse(block.vars[i].name, block.vars[i].value);
diff --git a/openmp/runtime/src/kmp_str.cpp b/openmp/runtime/src/kmp_str.cpp
index 04c4056a563..5338edf7243 100644
--- a/openmp/runtime/src/kmp_str.cpp
+++ b/openmp/runtime/src/kmp_str.cpp
@@ -143,13 +143,28 @@ void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, int len) {
KMP_STR_BUF_INVARIANT(buffer);
} // __kmp_str_buf_cat
-void __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
- va_list args) {
+void __kmp_str_buf_catbuf(kmp_str_buf_t *dest, const kmp_str_buf_t *src) {
+ KMP_DEBUG_ASSERT(dest);
+ KMP_DEBUG_ASSERT(src);
+ KMP_STR_BUF_INVARIANT(dest);
+ KMP_STR_BUF_INVARIANT(src);
+ if (!src->str || !src->used)
+ return;
+ __kmp_str_buf_reserve(dest, dest->used + src->used + 1);
+ KMP_MEMCPY(dest->str + dest->used, src->str, src->used);
+ dest->str[dest->used + src->used] = 0;
+ dest->used += src->used;
+ KMP_STR_BUF_INVARIANT(dest);
+} // __kmp_str_buf_catbuf
+
+// Return the number of characters written
+int __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
+ va_list args) {
+ int rc;
KMP_STR_BUF_INVARIANT(buffer);
for (;;) {
int const free = buffer->size - buffer->used;
- int rc;
int size;
// Try to format string.
@@ -198,13 +213,17 @@ void __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
KMP_DEBUG_ASSERT(buffer->size > 0);
KMP_STR_BUF_INVARIANT(buffer);
+ return rc;
} // __kmp_str_buf_vprint
-void __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...) {
+// Return the number of characters written
+int __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...) {
+ int rc;
va_list args;
va_start(args, format);
- __kmp_str_buf_vprint(buffer, format, args);
+ rc = __kmp_str_buf_vprint(buffer, format, args);
va_end(args);
+ return rc;
} // __kmp_str_buf_print
/* The function prints specified size to buffer. Size is expressed using biggest
diff --git a/openmp/runtime/src/kmp_str.h b/openmp/runtime/src/kmp_str.h
index 02a2032b580..c30255db9f5 100644
--- a/openmp/runtime/src/kmp_str.h
+++ b/openmp/runtime/src/kmp_str.h
@@ -51,9 +51,10 @@ void __kmp_str_buf_reserve(kmp_str_buf_t *buffer, int size);
void __kmp_str_buf_detach(kmp_str_buf_t *buffer);
void __kmp_str_buf_free(kmp_str_buf_t *buffer);
void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, int len);
-void __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
- va_list args);
-void __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...);
+void __kmp_str_buf_catbuf(kmp_str_buf_t *dest, const kmp_str_buf_t *src);
+int __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
+ va_list args);
+int __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...);
void __kmp_str_buf_print_size(kmp_str_buf_t *buffer, size_t size);
/* File name parser.
diff --git a/openmp/runtime/src/kmp_stub.cpp b/openmp/runtime/src/kmp_stub.cpp
index e26e0847985..c1f3bf38755 100644
--- a/openmp/runtime/src/kmp_stub.cpp
+++ b/openmp/runtime/src/kmp_stub.cpp
@@ -35,6 +35,10 @@
#define omp_set_num_threads ompc_set_num_threads
#define omp_set_dynamic ompc_set_dynamic
#define omp_set_nested ompc_set_nested
+#define omp_set_affinity_format ompc_set_affinity_format
+#define omp_get_affinity_format ompc_get_affinity_format
+#define omp_display_affinity ompc_display_affinity
+#define omp_capture_affinity ompc_capture_affinity
#define kmp_set_stacksize kmpc_set_stacksize
#define kmp_set_stacksize_s kmpc_set_stacksize_s
#define kmp_set_blocktime kmpc_set_blocktime
@@ -350,6 +354,17 @@ const omp_allocator_t *omp_low_lat_mem_alloc = (const omp_allocator_t *)5;
const omp_allocator_t *omp_cgroup_mem_alloc = (const omp_allocator_t *)6;
const omp_allocator_t *omp_pteam_mem_alloc = (const omp_allocator_t *)7;
const omp_allocator_t *omp_thread_mem_alloc = (const omp_allocator_t *)8;
+/* OpenMP 5.0 Affinity Format */
+void omp_set_affinity_format(char const *format) { i; }
+size_t omp_get_affinity_format(char *buffer, size_t size) {
+ i;
+ return 0;
+}
+void omp_display_affinity(char const *format) { i; }
+size_t omp_capture_affinity(char *buffer, size_t buf_size, char const *format) {
+ i;
+ return 0;
+}
#endif /* OMP_50_ENABLED */
// end of file //
diff --git a/openmp/runtime/test/lit.cfg b/openmp/runtime/test/lit.cfg
index 7196d379c09..82c3fd46c1d 100644
--- a/openmp/runtime/test/lit.cfg
+++ b/openmp/runtime/test/lit.cfg
@@ -94,6 +94,9 @@ if config.has_ompt:
if 'Linux' in config.operating_system:
config.available_features.add("linux")
+if config.operating_system in ['Linux', 'Windows']:
+ config.available_features.add('affinity')
+
# to run with icc INTEL_LICENSE_FILE must be set
if 'INTEL_LICENSE_FILE' in os.environ:
config.environment['INTEL_LICENSE_FILE'] = os.environ['INTEL_LICENSE_FILE']
OpenPOWER on IntegriCloud