+2020-05-19 Jakub Jelinek <jakub@redhat.com>
+
+ * omp.h.in (omp_uintptr_t): New typedef.
+ (__GOMP_UINTPTR_T_ENUM): Define.
+ (omp_memspace_handle_t, omp_allocator_handle_t, omp_alloctrait_key_t,
+ omp_alloctrait_value_t, omp_alloctrait_t): New typedefs.
+ (__GOMP_DEFAULT_NULL_ALLOCATOR): Define.
+ (omp_init_allocator, omp_destroy_allocator, omp_set_default_allocator,
+ omp_get_default_allocator, omp_alloc, omp_free): Declare.
+ * libgomp.h (struct gomp_team_state): Add def_allocator field.
+ (gomp_def_allocator): Declare.
+ * libgomp.map (OMP_5.0.1): Export omp_set_default_allocator,
+ omp_get_default_allocator, omp_init_allocator, omp_destroy_allocator,
+ omp_alloc and omp_free.
+ * team.c (gomp_team_start): Copy over ts.def_allocator.
+ * env.c (gomp_def_allocator): New variable.
+ (parse_wait_policy): Adjust function comment.
+ (parse_allocator): New function.
+ (handle_omp_display_env): Print OMP_ALLOCATOR.
+ (initialize_env): Call parse_allocator.
+ * Makefile.am (libgomp_la_SOURCES): Add allocator.c.
+ * allocator.c: New file.
+ * icv.c (omp_set_default_allocator, omp_get_default_allocator): New
+ functions.
+ * testsuite/libgomp.c-c++-common/alloc-1.c: New test.
+ * testsuite/libgomp.c-c++-common/alloc-2.c: New test.
+ * testsuite/libgomp.c-c++-common/alloc-3.c: New test.
+ * Makefile.in: Regenerated.
+
2020-05-15 H.J. Lu <hongjiu.lu@intel.com>
PR bootstrap/95147
proc.c sem.c bar.c ptrlock.c time.c fortran.c affinity.c target.c \
splay-tree.c libgomp-plugin.c oacc-parallel.c oacc-host.c oacc-init.c \
oacc-mem.c oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c \
- affinity-fmt.c teams.c oacc-profiling.c oacc-target.c
+ affinity-fmt.c teams.c allocator.c oacc-profiling.c oacc-target.c
include $(top_srcdir)/plugin/Makefrag.am
target.lo splay-tree.lo libgomp-plugin.lo oacc-parallel.lo \
oacc-host.lo oacc-init.lo oacc-mem.lo oacc-async.lo \
oacc-plugin.lo oacc-cuda.lo priority_queue.lo affinity-fmt.lo \
- teams.lo oacc-profiling.lo oacc-target.lo $(am__objects_1)
+ teams.lo allocator.lo oacc-profiling.lo oacc-target.lo \
+ $(am__objects_1)
libgomp_la_OBJECTS = $(am_libgomp_la_OBJECTS)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
affinity.c target.c splay-tree.c libgomp-plugin.c \
oacc-parallel.c oacc-host.c oacc-init.c oacc-mem.c \
oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c \
- affinity-fmt.c teams.c oacc-profiling.c oacc-target.c \
+ affinity-fmt.c teams.c allocator.c oacc-profiling.c oacc-target.c \
$(am__append_4)
# Nvidia PTX OpenACC plugin.
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affinity-fmt.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affinity.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/allocator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bar.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/barrier.Plo@am__quote@
unsigned long gomp_bind_var_list_len;
void **gomp_places_list;
unsigned long gomp_places_list_len;
+uintptr_t gomp_def_allocator = omp_default_mem_alloc;
int gomp_debug_var;
unsigned int gomp_num_teams_var;
bool gomp_display_affinity_var;
gomp_error ("Invalid value for environment variable %s", name);
}
-/* Parse the OMP_WAIT_POLICY environment variable and store the
- result in gomp_active_wait_policy. */
+/* Parse the OMP_WAIT_POLICY environment variable and return the value. */
static int
parse_wait_policy (void)
return false;
}
+/* Parse the OMP_ALLOCATOR environment variable and return the value. */
+
+static uintptr_t
+parse_allocator (void)
+{
+ const char *env;
+ uintptr_t ret = omp_default_mem_alloc;
+
+ env = getenv ("OMP_ALLOCATOR");
+ if (env == NULL)
+ return ret;
+
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (0)
+ ;
+#define C(v) \
+ else if (strncasecmp (env, #v, sizeof (#v) - 1) == 0) \
+ { \
+ ret = v; \
+ env += sizeof (#v) - 1; \
+ }
+ C (omp_default_mem_alloc)
+ C (omp_large_cap_mem_alloc)
+ C (omp_const_mem_alloc)
+ C (omp_high_bw_mem_alloc)
+ C (omp_low_lat_mem_alloc)
+ C (omp_cgroup_mem_alloc)
+ C (omp_pteam_mem_alloc)
+ C (omp_thread_mem_alloc)
+#undef C
+ else
+ env = "X";
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == '\0')
+ return ret;
+ gomp_error ("Invalid value for environment variable OMP_ALLOCATOR");
+ return omp_default_mem_alloc;
+}
+
static void
parse_acc_device_type (void)
{
gomp_display_affinity_var ? "TRUE" : "FALSE");
fprintf (stderr, " OMP_AFFINITY_FORMAT = '%s'\n",
gomp_affinity_format_var);
+ fprintf (stderr, " OMP_ALLOCATOR = '");
+ switch (gomp_def_allocator)
+ {
+#define C(v) case v: fputs (#v, stderr); break;
+ C (omp_default_mem_alloc)
+ C (omp_large_cap_mem_alloc)
+ C (omp_const_mem_alloc)
+ C (omp_high_bw_mem_alloc)
+ C (omp_low_lat_mem_alloc)
+ C (omp_cgroup_mem_alloc)
+ C (omp_pteam_mem_alloc)
+ C (omp_thread_mem_alloc)
+#undef C
+ default: break;
+ }
+ fputs ("'\n", stderr);
if (verbose)
{
parse_int ("OMP_MAX_TASK_PRIORITY", &gomp_max_task_priority_var, true);
parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
true);
+ gomp_def_allocator = parse_allocator ();
if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
{
gomp_global_icv.thread_limit_var
*place_nums++ = thr->ts.place_partition_off + i;
}
+void
+omp_set_default_allocator (omp_allocator_handle_t allocator)
+{
+ struct gomp_thread *thr = gomp_thread ();
+ if (allocator == omp_null_allocator)
+ allocator = omp_default_mem_alloc;
+ thr->ts.def_allocator = (uintptr_t) allocator;
+}
+
+omp_allocator_handle_t
+omp_get_default_allocator (void)
+{
+ struct gomp_thread *thr = gomp_thread ();
+ if (thr->ts.def_allocator == omp_null_allocator)
+ return (omp_allocator_handle_t) gomp_def_allocator;
+ else
+ return (omp_allocator_handle_t) thr->ts.def_allocator;
+}
+
ialias (omp_set_dynamic)
ialias (omp_set_nested)
ialias (omp_set_num_threads)
unsigned place_partition_off;
unsigned place_partition_len;
+ /* Def-allocator-var ICV. */
+ uintptr_t def_allocator;
+
#ifdef HAVE_SYNC_BUILTINS
/* Number of single stmts encountered. */
unsigned long single_count;
extern bool gomp_display_affinity_var;
extern char *gomp_affinity_format_var;
extern size_t gomp_affinity_format_len;
+extern uintptr_t gomp_def_allocator;
extern int goacc_device_num;
extern char *goacc_device_type;
extern int goacc_default_dims[GOMP_DIM_MAX];
omp_pause_resource_all_;
} OMP_4.5;
+OMP_5.0.1 {
+ global:
+ omp_set_default_allocator;
+ omp_get_default_allocator;
+ omp_init_allocator;
+ omp_destroy_allocator;
+ omp_alloc;
+ omp_free;
+} OMP_5.0;
+
GOMP_1.0 {
global:
GOMP_atomic_end;
omp_pause_hard = 2
} omp_pause_resource_t;
+typedef __UINTPTR_TYPE__ omp_uintptr_t;
+
+#if __cplusplus >= 201103L
+# define __GOMP_UINTPTR_T_ENUM : omp_uintptr_t
+#else
+# define __GOMP_UINTPTR_T_ENUM
+#endif
+
+typedef enum omp_memspace_handle_t __GOMP_UINTPTR_T_ENUM
+{
+ omp_default_mem_space = 0,
+ omp_large_cap_mem_space = 1,
+ omp_const_mem_space = 2,
+ omp_high_bw_mem_space = 3,
+ omp_low_lat_mem_space = 4,
+ __omp_memspace_handle_t_max__ = __UINTPTR_MAX__
+} omp_memspace_handle_t;
+
+typedef enum omp_allocator_handle_t __GOMP_UINTPTR_T_ENUM
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+typedef enum omp_alloctrait_key_t
+{
+ omp_atk_sync_hint = 1,
+ omp_atk_alignment = 2,
+ omp_atk_access = 3,
+ omp_atk_pool_size = 4,
+ omp_atk_fallback = 5,
+ omp_atk_fb_data = 6,
+ omp_atk_pinned = 7,
+ omp_atk_partition = 8
+} omp_alloctrait_key_t;
+
+typedef enum omp_alloctrait_value_t
+{
+ omp_atv_false = 0,
+ omp_atv_true = 1,
+ omp_atv_default = 2,
+ omp_atv_contended = 3,
+ omp_atv_uncontended = 4,
+ omp_atv_sequential = 5,
+ omp_atv_private = 6,
+ omp_atv_all = 7,
+ omp_atv_thread = 8,
+ omp_atv_pteam = 9,
+ omp_atv_cgroup = 10,
+ omp_atv_default_mem_fb = 11,
+ omp_atv_null_fb = 12,
+ omp_atv_abort_fb = 13,
+ omp_atv_allocator_fb = 14,
+ omp_atv_environment = 15,
+ omp_atv_nearest = 16,
+ omp_atv_blocked = 17,
+ omp_atv_interleaved = 18,
+ __omp_alloctrait_value_max__ = __UINTPTR_MAX__
+} omp_alloctrait_value_t;
+
+typedef struct omp_alloctrait_t
+{
+ omp_alloctrait_key_t key;
+ omp_uintptr_t value;
+} omp_alloctrait_t;
+
#ifdef __cplusplus
extern "C" {
# define __GOMP_NOTHROW throw ()
+# define __GOMP_DEFAULT_NULL_ALLOCATOR = omp_null_allocator
#else
# define __GOMP_NOTHROW __attribute__((__nothrow__))
+# define __GOMP_DEFAULT_NULL_ALLOCATOR
#endif
extern void omp_set_num_threads (int) __GOMP_NOTHROW;
extern int omp_pause_resource (omp_pause_resource_t, int) __GOMP_NOTHROW;
extern int omp_pause_resource_all (omp_pause_resource_t) __GOMP_NOTHROW;
+extern omp_allocator_handle_t omp_init_allocator (omp_memspace_handle_t,
+ int,
+ const omp_alloctrait_t [])
+ __GOMP_NOTHROW;
+extern void omp_destroy_allocator (omp_allocator_handle_t) __GOMP_NOTHROW;
+extern void omp_set_default_allocator (omp_allocator_handle_t) __GOMP_NOTHROW;
+extern omp_allocator_handle_t omp_get_default_allocator (void) __GOMP_NOTHROW;
+extern void *omp_alloc (__SIZE_TYPE__,
+ omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
+ __GOMP_NOTHROW;
+extern void omp_free (void *,
+ omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
+ __GOMP_NOTHROW;
+
#ifdef __cplusplus
}
#endif
nthr->ts.active_level = thr->ts.active_level;
nthr->ts.place_partition_off = place_partition_off;
nthr->ts.place_partition_len = place_partition_len;
+ nthr->ts.def_allocator = thr->ts.def_allocator;
#ifdef HAVE_SYNC_BUILTINS
nthr->ts.single_count = 0;
#endif
start_data->ts.team_id = i;
start_data->ts.level = team->prev_ts.level + 1;
start_data->ts.active_level = thr->ts.active_level;
+ start_data->ts.def_allocator = thr->ts.def_allocator;
#ifdef HAVE_SYNC_BUILTINS
start_data->ts.single_count = 0;
#endif
--- /dev/null
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+const omp_alloctrait_t traits2[]
+= { { omp_atk_alignment, 16 },
+ { omp_atk_sync_hint, omp_atv_default },
+ { omp_atk_access, omp_atv_default },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_default_mem_fb },
+ { omp_atk_partition, omp_atv_environment } };
+omp_alloctrait_t traits3[]
+= { { omp_atk_sync_hint, omp_atv_uncontended },
+ { omp_atk_alignment, 32 },
+ { omp_atk_access, omp_atv_all },
+ { omp_atk_pool_size, 512 },
+ { omp_atk_fallback, omp_atv_allocator_fb },
+ { omp_atk_fb_data, 0 },
+ { omp_atk_partition, omp_atv_default } };
+const omp_alloctrait_t traits4[]
+= { { omp_atk_alignment, 128 },
+ { omp_atk_pool_size, 1024 },
+ { omp_atk_fallback, omp_atv_null_fb } };
+
+int
+main ()
+{
+ int *volatile p = (int *) omp_alloc (3 * sizeof (int), omp_default_mem_alloc);
+ int *volatile q;
+ int *volatile r;
+ omp_alloctrait_t traits[3]
+ = { { omp_atk_alignment, 64 },
+ { omp_atk_fallback, omp_atv_null_fb },
+ { omp_atk_pool_size, 4096 } };
+ omp_allocator_handle_t a, a2;
+
+ if ((((uintptr_t) p) % __alignof (int)) != 0)
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ p[2] = 3;
+ omp_free (p, omp_default_mem_alloc);
+ p = (int *) omp_alloc (2 * sizeof (int), omp_default_mem_alloc);
+ if ((((uintptr_t) p) % __alignof (int)) != 0)
+ abort ();
+ p[0] = 1;
+ p[1] = 2;
+ omp_free (p, omp_null_allocator);
+ omp_set_default_allocator (omp_default_mem_alloc);
+ p = (int *) omp_alloc (sizeof (int), omp_null_allocator);
+ if ((((uintptr_t) p) % __alignof (int)) != 0)
+ abort ();
+ p[0] = 3;
+ omp_free (p, omp_get_default_allocator ());
+
+ a = omp_init_allocator (omp_default_mem_space, 3, traits);
+ if (a == omp_null_allocator)
+ abort ();
+ p = (int *) omp_alloc (3072, a);
+ if ((((uintptr_t) p) % 64) != 0)
+ abort ();
+ p[0] = 1;
+ p[3071 / sizeof (int)] = 2;
+ if (omp_alloc (3072, a) != NULL)
+ abort ();
+ omp_free (p, a);
+ p = (int *) omp_alloc (3072, a);
+ p[0] = 3;
+ p[3071 / sizeof (int)] = 4;
+ omp_free (p, omp_null_allocator);
+ omp_set_default_allocator (a);
+ if (omp_get_default_allocator () != a)
+ abort ();
+ p = (int *) omp_alloc (3072, omp_null_allocator);
+ if (omp_alloc (3072, omp_null_allocator) != NULL)
+ abort ();
+ omp_free (p, a);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits2) / sizeof (traits2[0]),
+ traits2);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ p = (int *) omp_alloc (420, a2);
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_alloc (768, a2);
+ if ((((uintptr_t) q) % 16) != 0)
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ r = (int *) omp_alloc (512, a2);
+ if ((((uintptr_t) r) % __alignof (int)) != 0)
+ abort ();
+ r[0] = 9;
+ r[511 / sizeof (int)] = 10;
+ omp_free (p, omp_null_allocator);
+ omp_free (q, a2);
+ omp_free (r, omp_null_allocator);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+
+ a = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits4) / sizeof (traits4[0]),
+ traits4);
+ if (a == omp_null_allocator)
+ abort ();
+ if (traits3[5].key != omp_atk_fb_data)
+ abort ();
+ traits3[5].value = (uintptr_t) a;
+ a2 = omp_init_allocator (omp_default_mem_space,
+ sizeof (traits3) / sizeof (traits3[0]),
+ traits3);
+ if (a2 == omp_null_allocator)
+ abort ();
+ omp_set_default_allocator (a2);
+#ifdef __cplusplus
+ p = static_cast <int *> (omp_alloc (420));
+#else
+ p = (int *) omp_alloc (420, omp_null_allocator);
+#endif
+ if ((((uintptr_t) p) % 32) != 0)
+ abort ();
+ p[0] = 5;
+ p[419 / sizeof (int)] = 6;
+ q = (int *) omp_alloc (768, omp_null_allocator);
+ if ((((uintptr_t) q) % 128) != 0)
+ abort ();
+ q[0] = 7;
+ q[767 / sizeof (int)] = 8;
+ if (omp_alloc (768, omp_null_allocator) != NULL)
+ abort ();
+#ifdef __cplusplus
+ omp_free (p);
+ omp_free (q);
+ omp_free (NULL);
+#else
+ omp_free (p, omp_null_allocator);
+ omp_free (q, omp_null_allocator);
+ omp_free (NULL, omp_null_allocator);
+#endif
+ omp_free (NULL, omp_null_allocator);
+ omp_destroy_allocator (a2);
+ omp_destroy_allocator (a);
+ return 0;
+}
--- /dev/null
+#include <omp.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ omp_alloctrait_t traits[3]
+ = { { omp_atk_alignment, 64 },
+ { omp_atk_fallback, omp_atv_null_fb },
+ { omp_atk_pool_size, 4096 } };
+ omp_allocator_handle_t a
+ = omp_init_allocator (omp_default_mem_space, 3, traits);
+ if (a == omp_null_allocator)
+ abort ();
+
+ #pragma omp parallel num_threads(4)
+ {
+ int n = omp_get_thread_num ();
+ double *volatile p, *volatile q;
+ omp_set_default_allocator ((n & 1) ? a : omp_default_mem_alloc);
+ p = (double *) omp_alloc (1696, omp_null_allocator);
+ if (p == NULL)
+ abort ();
+ p[0] = 1.0;
+ p[1695 / sizeof (double *)] = 2.0;
+ #pragma omp barrier
+ omp_set_default_allocator ((n & 1) ? omp_default_mem_alloc : a);
+ q = (double *) omp_alloc (1696, omp_null_allocator);
+ if (n & 1)
+ {
+ if (q == NULL)
+ abort ();
+ q[0] = 3.0;
+ q[1695 / sizeof (double *)] = 4.0;
+ }
+ else if (q != NULL)
+ abort ();
+ #pragma omp barrier
+ omp_free (p, omp_null_allocator);
+ omp_free (q, omp_null_allocator);
+ omp_set_default_allocator (omp_default_mem_alloc);
+ }
+ omp_destroy_allocator (a);
+ return 0;
+}
--- /dev/null
+/* { dg-set-target-env-var OMP_ALLOCATOR "omp_cgroup_mem_alloc" } */
+/* { dg-set-target-env-var OMP_DISPLAY_ENV "true" } */
+
+#include <string.h>
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+ const char *p = getenv ("OMP_ALLOCATOR");
+ if (p && strcmp (p, "omp_cgroup_mem_alloc") == 0)
+ {
+ if (omp_get_default_allocator () != omp_cgroup_mem_alloc)
+ abort ();
+ #pragma omp parallel num_threads (2)
+ {
+ if (omp_get_default_allocator () != omp_cgroup_mem_alloc)
+ abort ();
+ #pragma omp parallel num_threads (2)
+ {
+ if (omp_get_default_allocator () != omp_cgroup_mem_alloc)
+ abort ();
+ }
+ }
+ }
+ return 0;
+}