https://gcc.gnu.org/g:2f8f383036d28226723a2e08d105e94c6b2d74d6
commit r17-5648-g2f8f383036d28226723a2e08d105e94c6b2d74d6 Author: Tobias Burnus <[email protected]> Date: Tue Oct 27 19:06:25 2026 +0100 libgomp: Add omp_get_gprivate_limit API routine This API routine returns the maximally possible limit of for groupprivate variables, be it via the directive or using the dyn_groupprivate clause. GCC still has to support dyn_groupprivate, however, 'groupprivate' is supported on some offload devices. Note that for simplicity, the added API routines currently always return 0. For some reasons, there is a 'omp_access_pteam' named constant, even if it is nowhere specified for what it can be used. The API routines and the 'dyn_groupprivate' clause technically accept other values, but, effectively, only 'omp_access_cgroup' is specified. gcc/fortran/ChangeLog: * intrinsic.texi (OpenMP intrinsic modules): Update list of kind value and parameters. gcc/ChangeLog: * omp-general.cc (omp_runtime_api_procname): Add omp_get_gprivate_limit. libgomp/ChangeLog: * fortran.c (omp_get_gprivate_limit_): Add. * libgomp-plugin.h (GOMP_OFFLOAD_get_gprivate_limit): Add. * libgomp.h (struct gomp_device_descr): Add get_gprivate_limit_func. * libgomp.map: Add omp_get_gprivate_limit_. * libgomp.texi (omp_get_gprivate_limit): Document new routine. * omp.h.in (omp_access_t, omp_get_gprivate_limit): Add. * omp_lib.f90.in (omp_access_kind, omp_get_gprivate_limit): Add. * omp_lib.h.in (omp_access_kind, omp_get_gprivate_limit): Add. * plugin/plugin-gcn.c (GOMP_OFFLOAD_get_gprivate_limit): Add. * plugin/plugin-nvptx.c (GOMP_OFFLOAD_get_gprivate_limit): Add. * target.c (omp_get_gprivate_limit): Add. * testsuite/libgomp.c-c++-common/gprivate-1.c: New test. * testsuite/libgomp.fortran/gprivate-1.f90: New test. Diff: --- gcc/fortran/intrinsic.texi | 72 +++++++++++++++++++++- gcc/omp-general.cc | 1 + libgomp/fortran.c | 9 +++ libgomp/libgomp-plugin.h | 1 + libgomp/libgomp.h | 1 + libgomp/libgomp.map | 2 + libgomp/libgomp.texi | 45 +++++++++++++- libgomp/omp.h.in | 9 +++ libgomp/omp_lib.f90.in | 13 ++++ libgomp/omp_lib.h.in | 16 +++++ libgomp/plugin/plugin-gcn.c | 12 ++++ libgomp/plugin/plugin-nvptx.c | 12 ++++ libgomp/target.c | 23 +++++++ .../testsuite/libgomp.c-c++-common/gprivate-1.c | 49 +++++++++++++++ libgomp/testsuite/libgomp.fortran/gprivate-1.f90 | 54 ++++++++++++++++ 15 files changed, 317 insertions(+), 2 deletions(-) diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index bce59971e4bc..53c6baed0b6d 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -16410,15 +16410,23 @@ OpenMP Application Program Interface v6.0}. named constants: @table @asis +@item @code{omp_access_kind} @item @code{omp_allocator_handle_kind} @item @code{omp_alloctrait_key_kind} @item @code{omp_alloctrait_val_kind} +@item @code{omp_control_tool_kind} +@item @code{omp_control_tool_result_kind} @item @code{omp_depend_kind} +@item @code{omp_event_handle_kind} +@item @code{omp_interop_fr_kind} +@item @code{omp_interop_kind} +@item @code{omp_interop_property_kind} +@item @code{omp_interop_rc_kind} @item @code{omp_lock_kind} @item @code{omp_lock_hint_kind} +@item @code{omp_memspace_handle_kind} @item @code{omp_nest_lock_kind} @item @code{omp_pause_resource_kind} -@item @code{omp_memspace_handle_kind} @item @code{omp_proc_bind_kind} @item @code{omp_sched_kind} @item @code{omp_sync_hint_kind} @@ -16543,6 +16551,8 @@ The following scalar integer named constants are of the kind @item @code{omp_cgroup_mem_alloc} @item @code{omp_pteam_mem_alloc} @item @code{omp_thread_mem_alloc} +@item @code{ompx_gnu_pinned_mem_alloc} (GCC specific) +@item @code{ompx_gnu_managed_mem_alloc} (GCC specific) @end table The following scalar integer named constants are of the kind @@ -16554,6 +16564,66 @@ The following scalar integer named constants are of the kind @item @code{omp_const_mem_space} @item @code{omp_high_bw_mem_space} @item @code{omp_low_lat_mem_space} +@item @code{ompx_gnu_managed_mem_space} (GCC specific) +@end table + +The following scalar integer named constant is of the kind +@code{omp_interop_kind}: + +@table @asis +@item @code{omp_interop_none} +@end table + +The following scalar integer named constants are of the kind +@code{omp_interop_fr_kind}: + +@table @asis +@item @code{omp_ifr_cuda} +@item @code{omp_ifr_cuda_driver} +@item @code{omp_ifr_opencl} +@item @code{omp_ifr_sycl} +@item @code{omp_ifr_hip} +@item @code{omp_ifr_level_zero} +@item @code{omp_ifr_hsa} +@item @code{omp_ifr_last} +@end table + +The following scalar integer named constants are of the kind +@code{omp_interop_property_kind}: + +@table @asis +@item @code{omp_ipr_fr_id} +@item @code{omp_ipr_fr_name} +@item @code{omp_ipr_vendor} +@item @code{omp_ipr_vendor_name} +@item @code{omp_ipr_device_num} +@item @code{omp_ipr_platform} +@item @code{omp_ipr_device} +@item @code{omp_ipr_device_context} +@item @code{omp_ipr_targetsync} +@item @code{omp_ipr_first} +@end table + +The following scalar integer named constants are of the kind +@code{omp_interop_rc_kind}: + +@table @asis +@item @code{omp_irc_no_value} +@item @code{omp_irc_success} +@item @code{omp_irc_empty} +@item @code{omp_irc_out_of_range} +@item @code{omp_irc_type_int} +@item @code{omp_irc_type_ptr} +@item @code{omp_irc_type_str} +@item @code{omp_irc_other} +@end table + +The following scalar integer named constants are of the kind +@code{omp_access_kind}: + +@table @asis +@item @code{omp_access_cgroup} +@item @code{omp_access_pteam} @end table The following scalar integer named constants are of the kind diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index 5d0bd02f3a3e..9162972dc88d 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -4021,6 +4021,7 @@ omp_runtime_api_procname (const char *name) "get_device_from_uid", "get_device_num", "get_dynamic", + "get_gprivate_limit", "get_initial_device", "get_interop_name", "get_interop_rc_desc", diff --git a/libgomp/fortran.c b/libgomp/fortran.c index a28b86ae666e..3af77c6c7ba8 100644 --- a/libgomp/fortran.c +++ b/libgomp/fortran.c @@ -104,6 +104,7 @@ ialias_redirect (omp_get_interop_name) ialias_redirect (omp_get_interop_type_desc) ialias_redirect (omp_get_interop_rc_desc) ialias_redirect (omp_control_tool) +ialias_redirect (omp_get_gprivate_limit) ialias_redirect (omp_get_supported_active_team_dims) ialias_redirect (omp_get_supported_active_league_dims) #endif @@ -875,6 +876,14 @@ omp_get_supported_active_league_dims_ (int *device_num, int *native_support) return omp_get_supported_active_league_dims (*device_num, *native_support); } +size_t +omp_get_gprivate_limit_ (int device_num, int access_group, bool present_agrp) +{ + if (!present_agrp) + access_group = omp_access_cgroup; + return omp_get_gprivate_limit (device_num, access_group); +} + void omp_display_env_ (const int32_t *verbose) { diff --git a/libgomp/libgomp-plugin.h b/libgomp/libgomp-plugin.h index a01873131fb1..c67eeec6978f 100644 --- a/libgomp/libgomp-plugin.h +++ b/libgomp/libgomp-plugin.h @@ -169,6 +169,7 @@ extern const char *GOMP_OFFLOAD_get_uid (int); extern int GOMP_OFFLOAD_get_numa_node (int); extern int GOMP_OFFLOAD_supported_teams_dim (int, int); extern int GOMP_OFFLOAD_supported_threads_dim (int, int); +extern size_t GOMP_OFFLOAD_get_gprivate_limit (int, omp_access_t); extern unsigned int GOMP_OFFLOAD_get_caps (void); extern unsigned int GOMP_OFFLOAD_get_dev_caps (int); diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h index c4bab1097368..fed3da2e6624 100644 --- a/libgomp/libgomp.h +++ b/libgomp/libgomp.h @@ -1460,6 +1460,7 @@ struct gomp_device_descr __typeof (GOMP_OFFLOAD_get_numa_node) *get_numa_node_func; __typeof (GOMP_OFFLOAD_supported_teams_dim) *supported_teams_dim_func; __typeof (GOMP_OFFLOAD_supported_threads_dim) *supported_threads_dim_func; + __typeof (GOMP_OFFLOAD_get_gprivate_limit) *get_gprivate_limit_func; __typeof (GOMP_OFFLOAD_get_caps) *get_caps_func; __typeof (GOMP_OFFLOAD_get_dev_caps) *get_dev_caps_func; __typeof (GOMP_OFFLOAD_get_type) *get_type_func; diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map index 00e47d65d4c6..19890c05c76c 100644 --- a/libgomp/libgomp.map +++ b/libgomp/libgomp.map @@ -250,6 +250,8 @@ OMP_6.0 { OMP_6.1 { global: omp_get_device_distances; + omp_get_gprivate_limit; + omp_get_gprivate_limit_; omp_get_num_teams_dim; omp_get_num_threads_dim; omp_get_supported_active_league_dims; diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index f3f95df0c8b3..d323078494e7 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -3955,7 +3955,7 @@ They have C linkage and do not throw exceptions. @c * omp_get_dyn_gprivate_nofb_ptr:: <fixme>/TR15 @c * omp_get_dyn_gprivate_size:: <fixme>/TR15 @c * omp_get_dyn_gprivate_memspace:: <fixme>/TR15 -@c * omp_get_gprivate_limit:: <fixme>/TR15 +* omp_get_gprivate_limit:: Absolute limit of groupprivate memory @end menu @@ -4418,6 +4418,49 @@ was already deallocated or when the used allocator has already been destroyed. +@node omp_get_gprivate_limit +@subsection @code{omp_get_gprivate_limit} -- Absolute limit of groupprivate memory +@table @asis +@item @emph{Description}: +The @code{omp_get_gprivate_limit} routine returns the maximally possible limit +on groupprivate memory, which consists of memory allocatable via the +@code{dyn_groupprivate} clause and of variables that appear in the +@code{groupprivate} directive. @var{device_num} must be a conforming device +number and @var{access_group} takes @code{omp_access_cgroup} as argument. The +effect of running this routine in a @code{target} region is unspecified. + +@item @emph{C}: +@multitable @columnfractions .20 .80 +@item @emph{Prototype}: @tab @code{size_t omp_get_gprivate_limit(int *dev_num,} +@item @tab @code{ omp_access_t access_group)} +@end multitable + +@item @emph{C++}: +@multitable @columnfractions .20 .80 +@item @emph{Prototype}: @tab @code{size_t omp_get_gprivate_limit(int *dev_num,} +@item @tab @code{ omp_access_t access_group = omp_access_cgroup)} +@end multitable + +@item @emph{Fortran}: +@multitable @columnfractions .20 .80 +@item @emph{Interface}: @tab @code{integer (kind=c_size_t) function omp_get_gprivate_limit( &} +@item @tab @code{ device_num, access_group)} +@item @tab @code{use, intrinsic :: iso_c_binding, only : c_size_t, c_int} +@item @tab @code{integer (kind=c_int), value :: device_num} +@item @tab @code{integer (kind=omp_access_kind), value, optional :: access_group} +@end multitable + +@c @item @emph{See also}: +@c @ref{omp_alloc}, @ref{omp_aligned_alloc}, @ref{omp_calloc}, +@c @ref{omp_aligned_calloc}, @ref{omp_realloc} + +@item @emph{Reference}: +@c TODO: Update once OpenMP 6.1 is released +@uref{https://www.openmp.org, OpenMP Technical Report 15}, Section 34.13.5 +@end table + + + @node Tool Control Routine @section Tool Control Routine diff --git a/libgomp/omp.h.in b/libgomp/omp.h.in index 605ea9bb5a6b..6ffec871fd0e 100644 --- a/libgomp/omp.h.in +++ b/libgomp/omp.h.in @@ -115,6 +115,11 @@ typedef __UINTPTR_TYPE__ omp_uintptr_t; # define __GOMP_UINTPTR_T_ENUM #endif +typedef enum omp_access_t { + omp_access_cgroup = 0, + omp_access_pteam = 1 +} omp_access_t; + typedef enum omp_memspace_handle_t __GOMP_UINTPTR_T_ENUM { omp_default_mem_space = 0, @@ -259,6 +264,7 @@ typedef enum omp_control_tool_result_t { #ifdef __cplusplus extern "C" { # define __GOMP_NOTHROW throw () +# define __GOMP_DEFAULT_ACCESS = omp_access_cgroup # define __GOMP_DEFAULT_NULL_ALLOCATOR = omp_null_allocator # define __GOMP_DEFAULT_NULL = __null #else @@ -343,6 +349,9 @@ extern int omp_is_initial_device (void) __GOMP_NOTHROW; extern int omp_get_initial_device (void) __GOMP_NOTHROW; extern int omp_get_max_task_priority (void) __GOMP_NOTHROW; +extern __SIZE_TYPE__ omp_get_gprivate_limit (int, + omp_access_t __GOMP_DEFAULT_ACCESS) __GOMP_NOTHROW; + extern void omp_fulfill_event (omp_event_handle_t) __GOMP_NOTHROW; extern void omp_set_num_teams (int) __GOMP_NOTHROW; diff --git a/libgomp/omp_lib.f90.in b/libgomp/omp_lib.f90.in index 740b5a886410..598ae10fbdf2 100644 --- a/libgomp/omp_lib.f90.in +++ b/libgomp/omp_lib.f90.in @@ -34,6 +34,7 @@ integer, parameter :: omp_sync_hint_kind = 4 integer, parameter :: omp_lock_hint_kind = omp_sync_hint_kind integer, parameter :: omp_pause_resource_kind = 4 + integer, parameter :: omp_access_kind = c_int integer, parameter :: omp_allocator_handle_kind = c_intptr_t integer, parameter :: omp_alloctrait_key_kind = c_int integer, parameter :: omp_alloctrait_val_kind = c_intptr_t @@ -219,6 +220,8 @@ integer (omp_interop_rc_kind), parameter :: omp_irc_type_ptr = -4 integer (omp_interop_rc_kind), parameter :: omp_irc_type_str = -5 integer (omp_interop_rc_kind), parameter :: omp_irc_other = -6 + integer (omp_access_kind), parameter :: omp_access_cgroup = 0 + integer (omp_access_kind), parameter :: omp_access_pteam = 1 integer (omp_control_tool_kind), parameter :: omp_control_tool_start = 1 integer (omp_control_tool_kind), parameter :: omp_control_tool_pause = 2 integer (omp_control_tool_kind), parameter :: omp_control_tool_flush = 3 @@ -710,6 +713,16 @@ end function omp_get_teams_thread_limit end interface + interface + integer (kind=c_size_t) function omp_get_gprivate_limit (& + device_num, access_group) + use, intrinsic :: iso_c_binding, only : c_size_t, c_int + import :: omp_access_kind + integer (kind=c_int), value :: device_num + integer (kind=omp_access_kind), value, optional :: access_group + end function omp_get_gprivate_limit + end interface + interface subroutine omp_fulfill_event (event) use omp_lib_kinds diff --git a/libgomp/omp_lib.h.in b/libgomp/omp_lib.h.in index cce424eaa350..70ebca71a9b7 100644 --- a/libgomp/omp_lib.h.in +++ b/libgomp/omp_lib.h.in @@ -89,6 +89,13 @@ integer omp_event_handle_kind integer omp_interop_kind, omp_interop_fr_kind integer omp_interop_property_kind, omp_interop_rc_kind + + integer omp_access_kind + parameter (omp_access_kind = 4) + integer (omp_access_kind) omp_access_cgroup + integer (omp_access_kind) omp_access_pteam + parameter (omp_access_cgroup = 0) + parameter (omp_access_pteam = 1) integer omp_control_tool_kind integer omp_control_tool_result_kind parameter (omp_allocator_handle_kind = @INTPTR_T_KIND@) @@ -771,6 +778,15 @@ end function omp_get_supported_threads_dim end interface + interface + integer (kind=c_size_t) function omp_get_gprivate_limit ( & + & device_num, access_group) + use, intrinsic :: iso_c_binding, only : c_size_t, c_int + import :: omp_access_kind + integer (kind=c_int), value :: device_num + integer (kind=omp_access_kind),value,optional :: access_group + end function omp_get_gprivate_limit + end interface interface ! This function only supports integer(4) for simplicity. diff --git a/libgomp/plugin/plugin-gcn.c b/libgomp/plugin/plugin-gcn.c index 4aad9532183c..9d36178f33f1 100644 --- a/libgomp/plugin/plugin-gcn.c +++ b/libgomp/plugin/plugin-gcn.c @@ -3744,6 +3744,18 @@ GOMP_OFFLOAD_supported_threads_dim (int ord, int dim) return limit_worker_threads (__INT_MAX__); } +/* The maximum amount of memory available in a groupprivate memory space, + inclusive of groupprivate variables and any groupprivate copy of an + instantiated dynamic groupprivate block. */ + +size_t +GOMP_OFFLOAD_get_gprivate_limit (int ord, omp_access_t access) +{ + if (access != omp_access_cgroup) + return 0; + return 0; /* FIXME. dyn_groupprivate unsupported, but otherwise supported. */ +} + /* Return the specific capabilities the HSA accelerator have. */ unsigned int diff --git a/libgomp/plugin/plugin-nvptx.c b/libgomp/plugin/plugin-nvptx.c index 4a559877c9e8..62c43e7bd7a5 100644 --- a/libgomp/plugin/plugin-nvptx.c +++ b/libgomp/plugin/plugin-nvptx.c @@ -1428,6 +1428,18 @@ GOMP_OFFLOAD_supported_threads_dim (int ord, int dim) return max_warps_block; } +/* The maximum amount of memory available in a groupprivate memory space, + inclusive of groupprivate variables and any groupprivate copy of an + instantiated dynamic groupprivate block. */ + +size_t +GOMP_OFFLOAD_get_gprivate_limit (int ord, omp_access_t access) +{ + if (access != omp_access_cgroup) + return 0; + return 0; /* FIXME. dyn_groupprivate unsupported, but otherwise supported. */ +} + unsigned int GOMP_OFFLOAD_get_caps (void) { diff --git a/libgomp/target.c b/libgomp/target.c index f508040e0cad..f09e4ef38550 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -6387,6 +6387,27 @@ omp_get_device_from_uid (const char *uid) return omp_invalid_device; } +/* The maximum amount of memory available in a groupprivate memory space, + inclusive of groupprivate variables and any groupprivate copy of an + instantiated dynamic groupprivate block. */ + +size_t +omp_get_gprivate_limit (int device_num, omp_access_t access_group) +{ + if (device_num == omp_default_device) + device_num = gomp_get_default_device (); + + if (device_num == omp_initial_device + || device_num == omp_get_initial_device ()) + /* FIXME - update once dyn_groupprivate is supported on the host. */ + return access_group != omp_access_cgroup ? 0 : 0; + + struct gomp_device_descr *devicep = resolve_device (device_num, false); + if (devicep == NULL || !devicep->get_gprivate_limit_func) + return 0; + return devicep->get_gprivate_limit_func (devicep->target_id, access_group); +} + /* Return the numa distance between the numa node of the calling host thread and each of the NDEV devices in DEVICES. Special values: @@ -6447,6 +6468,7 @@ ialias (omp_get_supported_active_team_dims) ialias (omp_get_supported_active_league_dims) ialias (omp_get_supported_threads_dim) ialias (omp_get_supported_teams_dim) +ialias (omp_get_gprivate_limit) ialias (omp_get_uid_from_device) ialias (omp_get_device_from_uid) ialias (omp_get_device_distances) @@ -6497,6 +6519,7 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device, DLSYM_OPT (get_numa_node, get_numa_node); DLSYM_OPT (supported_threads_dim, supported_threads_dim); DLSYM_OPT (supported_teams_dim, supported_teams_dim); + DLSYM_OPT (get_gprivate_limit, get_gprivate_limit); DLSYM (get_caps); DLSYM_OPT (get_dev_caps, get_dev_caps); DLSYM (get_type); diff --git a/libgomp/testsuite/libgomp.c-c++-common/gprivate-1.c b/libgomp/testsuite/libgomp.c-c++-common/gprivate-1.c new file mode 100644 index 000000000000..e8ea66324992 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/gprivate-1.c @@ -0,0 +1,49 @@ +#include <omp.h> + +void +test_it (int dev) +{ + // Invalid access argument - expect 0 + if (omp_get_gprivate_limit (dev, (omp_access_t) -1) != 0) + __builtin_abort (); + + // Invalid access argument - expect 0 + if (omp_get_gprivate_limit (dev, (omp_access_t) 99) != 0) + __builtin_abort (); + + // FIXME: cgroup - should be valid in principle: + // - offload: groupprivate permitted for offloading, + // even if dyn_groupprivate is not implemented. + // - host: dyn_groupprivate implementable, but not implemented. + // + if (dev == omp_invalid_device + && omp_get_gprivate_limit (dev, omp_access_cgroup) != 0) + __builtin_abort (); + else if (dev != omp_invalid_device // For now, expect 0 + && omp_get_gprivate_limit (dev, omp_access_cgroup) != 0) + __builtin_abort (); + + // pteam - enum value defined but otherwise not specified at all! + // but in principle the limit question could be answered. + // + // Still, for now assume == 0. + if (omp_get_gprivate_limit (dev, omp_access_pteam) != 0) + __builtin_abort (); + +#if __cplusplus + // access is optional and defaults to 'omp_access_cgroup'. + if (omp_get_gprivate_limit (dev, omp_access_cgroup) + != omp_get_gprivate_limit (dev)) + __builtin_abort (); +#endif +} + +int main () +{ + // avoid - will exit after printing: libgomp: omp_invalid_device encountered + // test_it (omp_invalid_device); + test_it (omp_default_device); + + for (int dev = omp_initial_device; dev <= omp_get_num_devices (); dev++) + test_it (dev); +} diff --git a/libgomp/testsuite/libgomp.fortran/gprivate-1.f90 b/libgomp/testsuite/libgomp.fortran/gprivate-1.f90 new file mode 100644 index 000000000000..c171a2422a86 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/gprivate-1.f90 @@ -0,0 +1,54 @@ +module m + use omp_lib + implicit none (type, external) +contains +subroutine test_it (dev) + integer, value :: dev + + ! Invalid access argument - expect 0 + if (omp_get_gprivate_limit (dev, -1_omp_access_kind) /= 0) & + stop 1 + + ! Invalid access argument - expect 0 + if (omp_get_gprivate_limit (dev, 99_omp_access_kind) /= 0) & + stop 2 + + ! FIXME: cgroup - should be valid in principle: + ! - offload: groupprivate permitted for offloading, + ! even if dyn_groupprivate is not implemented. + ! - host: dyn_groupprivate implementable, but not implemented. + ! + if (dev == omp_invalid_device & + .and. omp_get_gprivate_limit (dev, omp_access_cgroup) /= 0) then + stop 3 + else if (dev /= omp_invalid_device & ! For now, expect 0 + .and. omp_get_gprivate_limit (dev, omp_access_cgroup) /= 0) then + stop 4 + end if + + ! pteam - enum value defined but otherwise not specified at all! + ! but in principle the limit question could be answered. + ! + ! Still, for now assume == 0. + if (omp_get_gprivate_limit (dev, omp_access_pteam) /= 0) & + stop 5 + + ! access is optional and defaults to 'omp_access_cgroup'. + if (omp_get_gprivate_limit (dev, omp_access_cgroup) & + /= omp_get_gprivate_limit (dev)) & + stop 6 +end +end + +program main + use m + implicit none (type, external) + integer :: dev + ! avoid - will exit after printing: libgomp: omp_invalid_device encountered + ! call test_it (omp_invalid_device) + call test_it (omp_default_device) + + do dev = omp_initial_device, omp_get_num_devices () + call test_it (dev) + end do +end
