Add OpenACC 2.6 `acc_get_property' support
authorMaciej W. Rozycki <macro@codesourcery.com>
Sun, 22 Dec 2019 19:54:09 +0000 (19:54 +0000)
committerFrederik Harwath <frederik@gcc.gnu.org>
Sun, 22 Dec 2019 19:54:09 +0000 (19:54 +0000)
Add generic support for the OpenACC 2.6 `acc_get_property' and
`acc_get_property_string' routines, as well as full handlers for the
host and the NVPTX offload targets and minimal handlers for the HSA,
Intel MIC, and AMD GCN offload targets.

Included are C/C++ and Fortran tests that, in particular, print
the property values for acc_property_vendor, acc_property_memory,
acc_property_free_memory, acc_property_name, and acc_property_driver.
The output looks as follows:

Vendor: GNU
Name: GOMP
Total memory: 0
Free memory: 0
Driver: 1.0

with the host driver (where the memory related properties are not
supported for the host device and yield 0, conforming to the standard)
and output like:

Vendor: Nvidia
Total memory: 12651462656
Free memory: 12202737664
Name: TITAN V
Driver: CUDA Driver 9.1

with the NVPTX driver.

2019-12-22  Maciej W. Rozycki  <macro@codesourcery.com>
    Frederik Harwath  <frederik@codesourcery.com>
    Thomas Schwinge  <tschwinge@codesourcery.com>

include/
* gomp-constants.h (gomp_device_property): New enum.

libgomp/
* libgomp.h (gomp_device_descr): Add `get_property_func' member.
* libgomp-plugin.h (gomp_device_property_value): New union.
(gomp_device_property_value): New prototype.
* openacc.h (acc_device_t): Add `acc_device_current' enumeration
constant.
(acc_device_property_t): New enum.
(acc_get_property, acc_get_property_string): New prototypes.
* oacc-init.c (acc_get_device_type): Also assert that result
is not `acc_device_current'.
(get_property_any, acc_get_property, acc_get_property_string):
New functions.
* openacc.f90 (openacc_kinds): Add `acc_device_current' and
`acc_property_memory', `acc_property_free_memory',
`acc_property_name', `acc_property_vendor' and
`acc_property_driver' constants.  Add `acc_device_property' data
type.
(openacc_internal): Add `acc_get_property' and
`acc_get_property_string' interfaces.  Add `acc_get_property_h',
`acc_get_property_string_h', `acc_get_property_l' and
`acc_get_property_string_l'.
* oacc-host.c (host_get_property): New function.
(host_dispatch): Wire it.
* target.c (gomp_load_plugin_for_device): Handle `get_property'.
* libgomp.map (OACC_2.6): Add `acc_get_property', `acc_get_property_h_',
`acc_get_property_string' and `acc_get_property_string_h_' symbols.
* libgomp.texi (OpenACC Runtime Library Routines): Add
`acc_get_property'.
(acc_get_property): New node.
* plugin/plugin-gcn.c (GOMP_OFFLOAD_get_property): New
function (stub).
* plugin/plugin-hsa.c (GOMP_OFFLOAD_get_property): New function.
* plugin/plugin-nvptx.c (CUDA_CALLS): Add `cuDeviceGetName',
`cuDeviceTotalMem', `cuDriverGetVersion' and `cuMemGetInfo'
calls.
(GOMP_OFFLOAD_get_property): New function.
(struct ptx_device): Add new field "name".
(cuda_driver_version_s): Add new static variable ...
(nvptx_init): ... and init from here.

* testsuite/libgomp.oacc-c-c++-common/acc_get_property.c: New test.
* testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c: New test.
* testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c: New test.
* testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c: New file
with test helper functions.

* testsuite/libgomp.oacc-fortran/acc_get_property.f90: New test.

liboffloadmic/
* plugin/libgomp-plugin-intelmic.cpp (GOMP_OFFLOAD_get_property):
New function.

Reviewed-by: Thomas Schwinge <thomas@codesourcery.com>
Co-Authored-By: Frederik Harwath <frederik@codesourcery.com>
Co-Authored-By: Thomas Schwinge <tschwinge@codesourcery.com>
From-SVN: r279710

23 files changed:
include/ChangeLog
include/gomp-constants.h
libgomp/ChangeLog
libgomp/libgomp-plugin.h
libgomp/libgomp.h
libgomp/libgomp.map
libgomp/libgomp.texi
libgomp/oacc-host.c
libgomp/oacc-init.c
libgomp/openacc.f90
libgomp/openacc.h
libgomp/plugin/cuda-lib.def
libgomp/plugin/plugin-gcn.c
libgomp/plugin/plugin-hsa.c
libgomp/plugin/plugin-nvptx.c
libgomp/target.c
libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c [new file with mode: 0644]
libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c [new file with mode: 0644]
libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c [new file with mode: 0644]
libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property.c [new file with mode: 0644]
libgomp/testsuite/libgomp.oacc-fortran/acc_get_property.f90 [new file with mode: 0644]
liboffloadmic/ChangeLog
liboffloadmic/plugin/libgomp-plugin-intelmic.cpp

index 3d44a944680990749876159b0b02f8df0a29f17e..60d9f207cbd3b0e642759ac893e89fc626a20b21 100644 (file)
@@ -1,3 +1,9 @@
+2019-12-22  Maciej W. Rozycki  <macro@codesourcery.com>
+           Frederik Harwath  <frederik@codesourcery.com>
+           Thomas Schwinge  <tschwinge@codesourcery.com>
+
+       * gomp-constants.h (gomp_device_property): New enum.
+
 2019-12-19  Julian Brown  <julian@codesourcery.com>
 
        * gomp-constants.h (gomp_map_kind): Add GOMP_MAP_ATTACH_DETACH.
index fdae6ccc870126f62a72d6956589f17ee843ceb4..d14e8b0394a92cb1992a6b74d9bbea3865131468 100644 (file)
@@ -195,6 +195,21 @@ enum gomp_map_kind
 #define GOMP_DEVICE_ICV                        -1
 #define GOMP_DEVICE_HOST_FALLBACK      -2
 
+/* Device property codes.  Keep in sync with
+   libgomp/{openacc.h,openacc.f90}:acc_device_property_t */
+/* Start from 1 to catch uninitialized use.  */
+enum gomp_device_property
+  {
+   GOMP_DEVICE_PROPERTY_MEMORY =       1,
+   GOMP_DEVICE_PROPERTY_FREE_MEMORY =  2,
+   GOMP_DEVICE_PROPERTY_NAME =         0x10001,
+   GOMP_DEVICE_PROPERTY_VENDOR =       0x10002,
+   GOMP_DEVICE_PROPERTY_DRIVER =       0x10003
+  };
+
+/* Internal property mask to tell numeric and string values apart.  */
+#define GOMP_DEVICE_PROPERTY_STRING_MASK       0x10000
+
 /* GOMP_task/GOMP_taskloop* flags argument.  */
 #define GOMP_TASK_FLAG_UNTIED          (1 << 0)
 #define GOMP_TASK_FLAG_FINAL           (1 << 1)
index c557aa436f29e6169304a1f6c2c8056facb034fa..deaff15c4e4f4d416253b8abc8c0f61d7b8fa6fd 100644 (file)
@@ -1,3 +1,54 @@
+2019-12-22  Maciej W. Rozycki  <macro@codesourcery.com>
+           Frederik Harwath  <frederik@codesourcery.com>
+           Thomas Schwinge  <tschwinge@codesourcery.com>
+
+       * libgomp.h (gomp_device_descr): Add `get_property_func' member.
+       * libgomp-plugin.h (gomp_device_property_value): New union.
+       (gomp_device_property_value): New prototype.
+       * openacc.h (acc_device_t): Add `acc_device_current' enumeration
+       constant.
+       (acc_device_property_t): New enum.
+       (acc_get_property, acc_get_property_string): New prototypes.
+       * oacc-init.c (acc_get_device_type): Also assert that result
+       is not `acc_device_current'.
+       (get_property_any, acc_get_property, acc_get_property_string):
+       New functions.
+       * openacc.f90 (openacc_kinds): Add `acc_device_current' and
+       `acc_property_memory', `acc_property_free_memory',
+       `acc_property_name', `acc_property_vendor' and
+       `acc_property_driver' constants.  Add `acc_device_property' data
+       type.
+       (openacc_internal): Add `acc_get_property' and
+       `acc_get_property_string' interfaces.  Add `acc_get_property_h',
+       `acc_get_property_string_h', `acc_get_property_l' and
+       `acc_get_property_string_l'.
+       * oacc-host.c (host_get_property): New function.
+       (host_dispatch): Wire it.
+       * target.c (gomp_load_plugin_for_device): Handle `get_property'.
+       * libgomp.map (OACC_2.6): Add `acc_get_property', `acc_get_property_h_',
+       `acc_get_property_string' and `acc_get_property_string_h_' symbols.
+       * libgomp.texi (OpenACC Runtime Library Routines): Add
+       `acc_get_property'.
+       (acc_get_property): New node.
+       * plugin/plugin-gcn.c (GOMP_OFFLOAD_get_property): New
+       function (stub).
+       * plugin/plugin-hsa.c (GOMP_OFFLOAD_get_property): New function.
+       * plugin/plugin-nvptx.c (CUDA_CALLS): Add `cuDeviceGetName',
+       `cuDeviceTotalMem', `cuDriverGetVersion' and `cuMemGetInfo'
+       calls.
+       (GOMP_OFFLOAD_get_property): New function.
+       (struct ptx_device): Add new field "name".
+       (cuda_driver_version_s): Add new static variable ...
+       (nvptx_init): ... and init from here.
+
+       * testsuite/libgomp.oacc-c-c++-common/acc_get_property.c: New test.
+       * testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c: New test.
+       * testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c: New test.
+       * testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c: New file
+       with test helper functions.
+
+       * testsuite/libgomp.oacc-fortran/acc_get_property.f90: New test.
+
 2019-12-22  Maciej W. Rozycki  <macro@wdc.com>
 
        * testsuite/libgomp-test-support.exp.in (GCC_UNDER_TEST): New
index 037558c43f5641dbf7492b8c53afe711e8c9ea95..d3c6dc36276586646365489aa009b357c66ada40 100644 (file)
@@ -54,6 +54,13 @@ enum offload_target_type
   OFFLOAD_TARGET_TYPE_GCN = 8
 };
 
+/* Container type for passing device properties.  */
+union gomp_device_property_value
+{
+  const char *ptr;
+  size_t val;
+};
+
 /* Opaque type to represent plugin-dependent implementation of an
    OpenACC asynchronous queue.  */
 struct goacc_asyncqueue;
@@ -94,6 +101,7 @@ extern const char *GOMP_OFFLOAD_get_name (void);
 extern unsigned int GOMP_OFFLOAD_get_caps (void);
 extern int GOMP_OFFLOAD_get_type (void);
 extern int GOMP_OFFLOAD_get_num_devices (void);
+extern union gomp_device_property_value GOMP_OFFLOAD_get_property (int, int);
 extern bool GOMP_OFFLOAD_init_device (int);
 extern bool GOMP_OFFLOAD_fini_device (int);
 extern unsigned GOMP_OFFLOAD_version (void);
index c9653575208876064dfaf284d9ccdbafb3f0d84e..24c76698c4e170caf740448004dfcd76ca996cff 100644 (file)
@@ -1113,6 +1113,7 @@ struct gomp_device_descr
   __typeof (GOMP_OFFLOAD_get_caps) *get_caps_func;
   __typeof (GOMP_OFFLOAD_get_type) *get_type_func;
   __typeof (GOMP_OFFLOAD_get_num_devices) *get_num_devices_func;
+  __typeof (GOMP_OFFLOAD_get_property) *get_property_func;
   __typeof (GOMP_OFFLOAD_init_device) *init_device_func;
   __typeof (GOMP_OFFLOAD_fini_device) *fini_device_func;
   __typeof (GOMP_OFFLOAD_version) *version_func;
index 63276f7d29be81e93b803e71defe0c36fd351246..c7268bfc8e76cd66041107090a651b6b940a069a 100644 (file)
@@ -492,6 +492,10 @@ OACC_2.6 {
        acc_detach_async;
        acc_detach_finalize;
        acc_detach_finalize_async;
+       acc_get_property;
+       acc_get_property_h_;
+       acc_get_property_string;
+       acc_get_property_string_h_;
 } OACC_2.5.1;
 
 GOACC_2.0 {
index ac9d38e01d756496044f07b71efcb95909495b90..5f8f1beedaffe3028284f2c40c4b8f700cea743e 100644 (file)
@@ -1849,6 +1849,7 @@ acceleration device.
 * acc_get_device_type::         Get type of device accelerator to be used.
 * acc_set_device_num::          Set device number to use.
 * acc_get_device_num::          Get device number to be used.
+* acc_get_property::            Get device property.
 * acc_async_test::              Tests for completion of a specific asynchronous
                                 operation.
 * acc_async_test_all::          Tests for completion of all asychronous
@@ -2038,6 +2039,44 @@ region.
 
 
 
+@node acc_get_property
+@section @code{acc_get_property} -- Get device property.
+@cindex acc_get_property
+@cindex acc_get_property_string
+@table @asis
+@item @emph{Description}
+These routines return the value of the specified @var{property} for the
+device being queried according to @var{devicenum} and @var{devicetype}.
+Integer-valued and string-valued properties are returned by
+@code{acc_get_property} and @code{acc_get_property_string} respectively.
+The Fortran @code{acc_get_property_string} subroutine returns the string
+retrieved in its fourth argument while the remaining entry points are
+functions, which pass the return value as their result.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{size_t acc_get_property(int devicenum, acc_device_t devicetype, acc_device_property_t property);}
+@item @emph{Prototype}: @tab @code{const char *acc_get_property_string(int devicenum, acc_device_t devicetype, acc_device_property_t property);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{function acc_get_property(devicenum, devicetype, property)}
+@item @emph{Interface}: @tab @code{subroutine acc_get_property_string(devicenum, devicetype, property, string)}
+@item                   @tab @code{integer devicenum}
+@item                   @tab @code{integer(kind=acc_device_kind) devicetype}
+@item                   @tab @code{integer(kind=acc_device_property) property}
+@item                   @tab @code{integer(kind=acc_device_property) acc_get_property}
+@item                   @tab @code{character(*) string}
+@end multitable
+
+@item @emph{Reference}:
+@uref{https://www.openacc.org, OpenACC specification v2.6}, section
+3.2.6.
+@end table
+
+
+
 @node acc_async_test
 @section @code{acc_async_test} -- Test for completion of a specific asynchronous operation.
 @table @asis
index 845140f04f52b6ac4898b096452f4cfa2fff5c0e..ec9e3247a1afc8911e6d6d6358bfaa6378fe6959 100644 (file)
@@ -59,6 +59,27 @@ host_get_num_devices (void)
   return 1;
 }
 
+static union gomp_device_property_value
+host_get_property (int n, int prop)
+{
+  union gomp_device_property_value nullval = { .val = 0 };
+
+  if (n >= host_get_num_devices ())
+    return nullval;
+
+  switch (prop)
+    {
+    case GOMP_DEVICE_PROPERTY_NAME:
+      return (union gomp_device_property_value) { .ptr = "GOMP" };
+    case GOMP_DEVICE_PROPERTY_VENDOR:
+      return (union gomp_device_property_value) { .ptr = "GNU" };
+    case GOMP_DEVICE_PROPERTY_DRIVER:
+      return (union gomp_device_property_value) { .ptr = VERSION };
+    default:
+      return nullval;
+    }
+}
+
 static bool
 host_init_device (int n __attribute__ ((unused)))
 {
@@ -248,6 +269,7 @@ static struct gomp_device_descr host_dispatch =
     .get_caps_func = host_get_caps,
     .get_type_func = host_get_type,
     .get_num_devices_func = host_get_num_devices,
+    .get_property_func = host_get_property,
     .init_device_func = host_init_device,
     .fini_device_func = host_fini_device,
     .version_func = host_version,
index dd88b58a379cc85a892dfab59774a9c0a4527fa6..487a2cca61f8779f4b93fb6361c175e5c6afae5c 100644 (file)
@@ -670,7 +670,8 @@ acc_get_device_type (void)
     }
 
   assert (res != acc_device_default
-         && res != acc_device_not_host);
+         && res != acc_device_not_host
+         && res != acc_device_current);
 
   return res;
 }
@@ -759,6 +760,66 @@ acc_set_device_num (int ord, acc_device_t d)
 
 ialias (acc_set_device_num)
 
+static union gomp_device_property_value
+get_property_any (int ord, acc_device_t d, acc_device_property_t prop)
+{
+  goacc_lazy_initialize ();
+  struct goacc_thread *thr = goacc_thread ();
+
+  if (d == acc_device_current && thr && thr->dev)
+    return thr->dev->get_property_func (thr->dev->target_id, prop);
+
+  gomp_mutex_lock (&acc_device_lock);
+
+  struct gomp_device_descr *dev = resolve_device (d, true);
+
+  int num_devices = dev->get_num_devices_func ();
+
+  if (num_devices <= 0 || ord >= num_devices)
+    acc_dev_num_out_of_range (d, ord, num_devices);
+
+  dev += ord;
+
+  gomp_mutex_lock (&dev->lock);
+  if (dev->state == GOMP_DEVICE_UNINITIALIZED)
+    gomp_init_device (dev);
+  gomp_mutex_unlock (&dev->lock);
+
+  gomp_mutex_unlock (&acc_device_lock);
+
+  assert (dev);
+
+  return dev->get_property_func (dev->target_id, prop);
+}
+
+size_t
+acc_get_property (int ord, acc_device_t d, acc_device_property_t prop)
+{
+  if (!known_device_type_p (d))
+    unknown_device_type_error(d);
+
+  if (prop & GOMP_DEVICE_PROPERTY_STRING_MASK)
+    return 0;
+  else
+    return get_property_any (ord, d, prop).val;
+}
+
+ialias (acc_get_property)
+
+const char *
+acc_get_property_string (int ord, acc_device_t d, acc_device_property_t prop)
+{
+  if (!known_device_type_p (d))
+    unknown_device_type_error(d);
+
+  if (prop & GOMP_DEVICE_PROPERTY_STRING_MASK)
+    return get_property_any (ord, d, prop).ptr;
+  else
+    return NULL;
+}
+
+ialias (acc_get_property_string)
+
 /* For -O and higher, the compiler always attempts to expand acc_on_device, but
    if the user disables the builtin, or calls it via a pointer, we'll need this
    version.
index fb7fc6e6d77e70fb55a106dbfc4e7096ef4fb5a8..e5b4b40c3cce2daaee1b0b73d5e68dc4202202fa 100644 (file)
 
 module openacc_kinds
   use iso_fortran_env, only: int32
+  use iso_c_binding, only: c_size_t
   implicit none
 
   public
-  private :: int32
+  private :: int32, c_size_t
 
   ! When adding items, also update 'public' setting in 'module openacc' below.
 
   integer, parameter :: acc_device_kind = int32
 
   ! Keep in sync with include/gomp-constants.h.
+  integer (acc_device_kind), parameter :: acc_device_current = -3
   integer (acc_device_kind), parameter :: acc_device_none = 0
   integer (acc_device_kind), parameter :: acc_device_default = 1
   integer (acc_device_kind), parameter :: acc_device_host = 2
@@ -49,6 +51,15 @@ module openacc_kinds
   integer (acc_device_kind), parameter :: acc_device_nvidia = 5
   integer (acc_device_kind), parameter :: acc_device_gcn = 8
 
+  integer, parameter :: acc_device_property = c_size_t
+
+  ! Keep in sync with include/gomp-constants.h.
+  integer (acc_device_property), parameter :: acc_property_memory = 1
+  integer (acc_device_property), parameter :: acc_property_free_memory = 2
+  integer (acc_device_property), parameter :: acc_property_name = int(Z'10001')
+  integer (acc_device_property), parameter :: acc_property_vendor = int(Z'10002')
+  integer (acc_device_property), parameter :: acc_property_driver = int(Z'10003')
+
   integer, parameter :: acc_handle_kind = int32
 
   ! Keep in sync with include/gomp-constants.h.
@@ -89,6 +100,24 @@ module openacc_internal
       integer (acc_device_kind) d
     end function
 
+    function acc_get_property_h (n, d, p)
+      import
+      implicit none (type, external)
+      integer (acc_device_property) :: acc_get_property_h
+      integer, value :: n
+      integer (acc_device_kind), value :: d
+      integer (acc_device_property), value :: p
+    end function
+
+    subroutine acc_get_property_string_h (n, d, p, s)
+      import
+      implicit none (type, external)
+      integer, value :: n
+      integer (acc_device_kind), value :: d
+      integer (acc_device_property), value :: p
+      character (*) :: s
+    end subroutine
+
     function acc_async_test_h (a)
       logical acc_async_test_h
       integer a
@@ -508,6 +537,26 @@ module openacc_internal
       integer (c_int), value :: d
     end function
 
+    function acc_get_property_l (n, d, p) &
+        bind (C, name = "acc_get_property")
+      use iso_c_binding, only: c_int, c_size_t
+      implicit none (type, external)
+      integer (c_size_t) :: acc_get_property_l
+      integer (c_int), value :: n
+      integer (c_int), value :: d
+      integer (c_int), value :: p
+    end function
+
+    function acc_get_property_string_l (n, d, p) &
+        bind (C, name = "acc_get_property_string")
+      use iso_c_binding, only: c_int, c_ptr
+      implicit none (type, external)
+      type (c_ptr) :: acc_get_property_string_l
+      integer (c_int), value :: n
+      integer (c_int), value :: d
+      integer (c_int), value :: p
+    end function
+
     function acc_async_test_l (a) &
         bind (C, name = "acc_async_test")
       use iso_c_binding, only: c_int
@@ -716,16 +765,23 @@ module openacc
   private
 
   ! From openacc_kinds
-  public :: acc_device_kind, acc_handle_kind
+  public :: acc_device_kind
   public :: acc_device_none, acc_device_default, acc_device_host
   public :: acc_device_not_host, acc_device_nvidia, acc_device_gcn
+
+  public :: acc_device_property
+  public :: acc_property_memory, acc_property_free_memory
+  public :: acc_property_name, acc_property_vendor, acc_property_driver
+
+  public :: acc_handle_kind
   public :: acc_async_noval, acc_async_sync
 
   public :: openacc_version
 
   public :: acc_get_num_devices, acc_set_device_type, acc_get_device_type
-  public :: acc_set_device_num, acc_get_device_num, acc_async_test
-  public :: acc_async_test_all
+  public :: acc_set_device_num, acc_get_device_num
+  public :: acc_get_property, acc_get_property_string
+  public :: acc_async_test, acc_async_test_all
   public :: acc_wait, acc_async_wait, acc_wait_async
   public :: acc_wait_all, acc_async_wait_all, acc_wait_all_async
   public :: acc_init, acc_shutdown, acc_on_device
@@ -758,6 +814,14 @@ module openacc
     procedure :: acc_get_device_num_h
   end interface
 
+  interface acc_get_property
+    procedure :: acc_get_property_h
+  end interface
+
+  interface acc_get_property_string
+    procedure :: acc_get_property_string_h
+  end interface
+
   interface acc_async_test
     procedure :: acc_async_test_h
   end interface
@@ -976,6 +1040,63 @@ function acc_get_device_num_h (d)
   acc_get_device_num_h = acc_get_device_num_l (d)
 end function
 
+function acc_get_property_h (n, d, p)
+  use iso_c_binding, only: c_int, c_size_t
+  use openacc_internal, only: acc_get_property_l
+  use openacc_kinds
+  implicit none (type, external)
+  integer (acc_device_property) :: acc_get_property_h
+  integer, value :: n
+  integer (acc_device_kind), value :: d
+  integer (acc_device_property), value :: p
+
+  integer (c_int) :: pint
+
+  pint = int (p, c_int)
+  acc_get_property_h = acc_get_property_l (n, d, pint)
+end function
+
+subroutine acc_get_property_string_h (n, d, p, s)
+  use iso_c_binding, only: c_char, c_int, c_ptr, c_f_pointer, c_associated
+  use openacc_internal, only: acc_get_property_string_l
+  use openacc_kinds
+  implicit none (type, external)
+  integer, value :: n
+  integer (acc_device_kind), value :: d
+  integer (acc_device_property), value :: p
+  character (*) :: s
+
+  integer (c_int) :: pint
+  type (c_ptr) :: cptr
+  integer :: clen
+  character (kind=c_char, len=1), pointer, contiguous :: sptr (:)
+  integer :: slen
+  integer :: i
+
+  interface
+     function strlen (s) bind (C, name = "strlen")
+       use iso_c_binding, only: c_ptr, c_size_t
+       type (c_ptr), intent(in), value :: s
+       integer (c_size_t) :: strlen
+     end function strlen
+  end interface
+
+  pint = int (p, c_int)
+  cptr = acc_get_property_string_l (n, d, pint)
+  s = ""
+  if (.not. c_associated (cptr)) then
+     return
+  end if
+
+  clen = int (strlen (cptr))
+  call c_f_pointer (cptr, sptr, [clen])
+
+  slen = min (clen, len (s))
+  do i = 1, slen
+    s (i:i) = sptr (i)
+  end do
+end subroutine
+
 function acc_async_test_h (a)
   use openacc_internal, only: acc_async_test_l
   logical acc_async_test_h
index d2e5c101f7f6f11d483e37e753075e47ca2f95e0..9b143064b7d4e04ba1998e3011285ed7d45ebb80 100644 (file)
@@ -49,6 +49,7 @@ extern "C" {
 /* Types */
 typedef enum acc_device_t {
   /* Keep in sync with include/gomp-constants.h.  */
+  acc_device_current = -3,
   acc_device_none = 0,
   acc_device_default = 1,
   acc_device_host = 2,
@@ -62,6 +63,16 @@ typedef enum acc_device_t {
   _ACC_neg = -1
 } acc_device_t;
 
+typedef enum acc_device_property_t {
+  /* Keep in sync with include/gomp-constants.h.  */
+  /* Start from 1 to catch uninitialized use.  */
+  acc_property_memory = 1,
+  acc_property_free_memory = 2,
+  acc_property_name = 0x10001,
+  acc_property_vendor = 0x10002,
+  acc_property_driver = 0x10003
+} acc_device_property_t;
+
 typedef enum acc_async_t {
   /* Keep in sync with include/gomp-constants.h.  */
   acc_async_noval = -1,
@@ -73,6 +84,10 @@ void acc_set_device_type (acc_device_t) __GOACC_NOTHROW;
 acc_device_t acc_get_device_type (void) __GOACC_NOTHROW;
 void acc_set_device_num (int, acc_device_t) __GOACC_NOTHROW;
 int acc_get_device_num (acc_device_t) __GOACC_NOTHROW;
+size_t acc_get_property
+  (int, acc_device_t, acc_device_property_t) __GOACC_NOTHROW;
+const char *acc_get_property_string
+  (int, acc_device_t, acc_device_property_t) __GOACC_NOTHROW;
 int acc_async_test (int) __GOACC_NOTHROW;
 int acc_async_test_all (void) __GOACC_NOTHROW;
 void acc_wait (int) __GOACC_NOTHROW;
index a16badcfa9de0329c3d8bb757ff5dc516341f1a4..cd91b39b1d2721ebf131813bf78b0aa0c3094fc3 100644 (file)
@@ -8,6 +8,9 @@ CUDA_ONE_CALL (cuCtxSynchronize)
 CUDA_ONE_CALL (cuDeviceGet)
 CUDA_ONE_CALL (cuDeviceGetAttribute)
 CUDA_ONE_CALL (cuDeviceGetCount)
+CUDA_ONE_CALL (cuDeviceGetName)
+CUDA_ONE_CALL (cuDeviceTotalMem)
+CUDA_ONE_CALL (cuDriverGetVersion)
 CUDA_ONE_CALL (cuEventCreate)
 CUDA_ONE_CALL (cuEventDestroy)
 CUDA_ONE_CALL (cuEventElapsedTime)
@@ -35,6 +38,7 @@ CUDA_ONE_CALL (cuMemcpyHtoDAsync)
 CUDA_ONE_CALL (cuMemFree)
 CUDA_ONE_CALL (cuMemFreeHost)
 CUDA_ONE_CALL (cuMemGetAddressRange)
+CUDA_ONE_CALL (cuMemGetInfo)
 CUDA_ONE_CALL (cuMemHostGetDevicePointer)
 CUDA_ONE_CALL (cuModuleGetFunction)
 CUDA_ONE_CALL (cuModuleGetGlobal)
index 04fe472a70dc25f503824b2c6faf3c1dc68f5582..32239c71c61b81651ffbabe2be764b3e6d8023fe 100644 (file)
@@ -3236,6 +3236,17 @@ GOMP_OFFLOAD_get_num_devices (void)
   return hsa_context.agent_count;
 }
 
+union gomp_device_property_value
+GOMP_OFFLOAD_get_property (int device, int prop)
+{
+  /* Stub. Check device and return default value for unsupported properties. */
+  /* TODO: Implement this function. */
+  get_agent_info (device);
+
+  union gomp_device_property_value nullval = { .val = 0 };
+  return nullval;
+}
+
 /* Initialize device (agent) number N so that it can be used for computation.
    Return TRUE on success.  */
 
index 409e138aaca39a0f6cd8e4ec3b3f7abcd9d41842..259f704b2e955d85cde83347d09b0296e405b3e8 100644 (file)
@@ -699,6 +699,32 @@ GOMP_OFFLOAD_get_num_devices (void)
   return hsa_context.agent_count;
 }
 
+/* Part of the libgomp plugin interface.  Return the value of property
+   PROP of agent number N.  */
+
+union gomp_device_property_value
+GOMP_OFFLOAD_get_property (int n, int prop)
+{
+  union gomp_device_property_value nullval = { .val = 0 };
+
+  if (!init_hsa_context ())
+    return nullval;
+  if (n >= hsa_context.agent_count)
+    {
+      GOMP_PLUGIN_error
+       ("Request for a property of a non-existing HSA device %i", n);
+      return nullval;
+    }
+
+  switch (prop)
+    {
+    case GOMP_DEVICE_PROPERTY_VENDOR:
+      return (union gomp_device_property_value) { .ptr = "HSA" };
+    default:
+      return nullval;
+    }
+}
+
 /* Part of the libgomp plugin interface.  Initialize agent number N so that it
    can be used for computation.  Return TRUE on success.  */
 
index 911d0f66a6e4dad9108061d98886dae234cd2f04..80e547541e33622d90e78e1a86684ee8fbd64649 100644 (file)
@@ -189,6 +189,10 @@ cuda_error (CUresult r)
   return fallback;
 }
 
+/* Version of the CUDA Toolkit in the same MAJOR.MINOR format that is used by
+   Nvidia, such as in the 'deviceQuery' program (Nvidia's CUDA samples). */
+static char cuda_driver_version_s[30];
+
 static unsigned int instantiated_devices = 0;
 static pthread_mutex_t ptx_dev_lock = PTHREAD_MUTEX_INITIALIZER;
 
@@ -284,7 +288,7 @@ struct ptx_device
   bool map;
   bool concur;
   bool mkern;
-  int  mode;
+  int mode;
   int clock_khz;
   int num_sms;
   int regs_per_block;
@@ -294,6 +298,9 @@ struct ptx_device
   int max_threads_per_multiprocessor;
   int default_dims[GOMP_DIM_MAX];
 
+  /* Length as used by the CUDA Runtime API ('struct cudaDeviceProp').  */
+  char name[256];
+
   struct ptx_image_data *images;  /* Images loaded on device.  */
   pthread_mutex_t image_lock;     /* Lock for above list.  */
 
@@ -327,9 +334,16 @@ nvptx_init (void)
 
   CUDA_CALL (cuInit, 0);
 
+  int cuda_driver_version;
+  CUDA_CALL_ERET (NULL, cuDriverGetVersion, &cuda_driver_version);
+  snprintf (cuda_driver_version_s, sizeof cuda_driver_version_s,
+           "CUDA Driver %u.%u",
+           cuda_driver_version / 1000, cuda_driver_version % 1000 / 10);
+
   CUDA_CALL (cuDeviceGetCount, &ndevs);
   ptx_devices = GOMP_PLUGIN_malloc_cleared (sizeof (struct ptx_device *)
                                            * ndevs);
+
   return true;
 }
 
@@ -491,6 +505,9 @@ nvptx_open_device (int n)
   for (int i = 0; i != GOMP_DIM_MAX; i++)
     ptx_dev->default_dims[i] = 0;
 
+  CUDA_CALL_ERET (NULL, cuDeviceGetName, ptx_dev->name, sizeof ptx_dev->name,
+                 dev);
+
   ptx_dev->images = NULL;
   pthread_mutex_init (&ptx_dev->image_lock, NULL);
 
@@ -1104,6 +1121,74 @@ GOMP_OFFLOAD_get_num_devices (void)
   return nvptx_get_num_devices ();
 }
 
+union gomp_device_property_value
+GOMP_OFFLOAD_get_property (int n, int prop)
+{
+  union gomp_device_property_value propval = { .val = 0 };
+
+  pthread_mutex_lock (&ptx_dev_lock);
+
+  if (n >= nvptx_get_num_devices () || n < 0 || ptx_devices[n] == NULL)
+    {
+      pthread_mutex_unlock (&ptx_dev_lock);
+      return propval;
+    }
+
+  struct ptx_device *ptx_dev = ptx_devices[n];
+  switch (prop)
+    {
+    case GOMP_DEVICE_PROPERTY_MEMORY:
+      {
+       size_t total_mem;
+
+       CUDA_CALL_ERET (propval, cuDeviceTotalMem, &total_mem, ptx_dev->dev);
+       propval.val = total_mem;
+      }
+      break;
+    case GOMP_DEVICE_PROPERTY_FREE_MEMORY:
+      {
+       size_t total_mem;
+       size_t free_mem;
+       CUdevice ctxdev;
+
+       CUDA_CALL_ERET (propval, cuCtxGetDevice, &ctxdev);
+       if (ptx_dev->dev == ctxdev)
+         CUDA_CALL_ERET (propval, cuMemGetInfo, &free_mem, &total_mem);
+       else if (ptx_dev->ctx)
+         {
+           CUcontext old_ctx;
+
+           CUDA_CALL_ERET (propval, cuCtxPushCurrent, ptx_dev->ctx);
+           CUDA_CALL_ERET (propval, cuMemGetInfo, &free_mem, &total_mem);
+           CUDA_CALL_ASSERT (cuCtxPopCurrent, &old_ctx);
+         }
+       else
+         {
+           CUcontext new_ctx;
+
+           CUDA_CALL_ERET (propval, cuCtxCreate, &new_ctx, CU_CTX_SCHED_AUTO,
+                           ptx_dev->dev);
+           CUDA_CALL_ERET (propval, cuMemGetInfo, &free_mem, &total_mem);
+           CUDA_CALL_ASSERT (cuCtxDestroy, new_ctx);
+         }
+       propval.val = free_mem;
+      }
+      break;
+    case GOMP_DEVICE_PROPERTY_NAME:
+      propval.ptr = ptx_dev->name;
+      break;
+    case GOMP_DEVICE_PROPERTY_VENDOR:
+      propval.ptr = "Nvidia";
+      break;
+    case GOMP_DEVICE_PROPERTY_DRIVER:
+      propval.ptr = cuda_driver_version_s;
+      break;
+    }
+
+  pthread_mutex_unlock (&ptx_dev_lock);
+  return propval;
+}
+
 bool
 GOMP_OFFLOAD_init_device (int n)
 {
index bf30716cd855945e70cf7399c8d2af457276837c..3562c3790f10703c76b591a0d37e5c3e18fb28dd 100644 (file)
@@ -3001,6 +3001,7 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
   DLSYM (get_caps);
   DLSYM (get_type);
   DLSYM (get_num_devices);
+  DLSYM (get_property);
   DLSYM (init_device);
   DLSYM (fini_device);
   DLSYM (load_image);
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c
new file mode 100644 (file)
index 0000000..4dd13c4
--- /dev/null
@@ -0,0 +1,68 @@
+/* Test the `acc_get_property' and '`acc_get_property_string' library
+   functions on Nvidia devices by comparing property values with
+   those obtained through the CUDA API. */
+/* { dg-additional-sources acc_get_property-aux.c } */
+/* { dg-additional-options "-lcuda -lcudart" } */
+/* { dg-do run { target openacc_nvidia_accel_selected } } */
+
+#include <openacc.h>
+#include <cuda.h>
+#include <cuda_runtime_api.h>
+#include <string.h>
+#include <stdio.h>
+
+void expect_device_properties
+(acc_device_t dev_type, int dev_num,
+ int expected_total_mem, int expected_free_mem,
+ const char* expected_vendor, const char* expected_name,
+ const char* expected_driver);
+
+int main ()
+{
+  int dev_count;
+  cudaGetDeviceCount (&dev_count);
+
+  for (int dev_num = 0; dev_num < dev_count; ++dev_num)
+    {
+      if (cudaSetDevice (dev_num) != cudaSuccess)
+       {
+         fprintf (stderr, "cudaSetDevice failed.\n");
+         abort ();
+       }
+
+      printf("Checking device %d\n", dev_num);
+
+      const char *vendor = "Nvidia";
+      size_t free_mem;
+      size_t total_mem;
+      if (cudaMemGetInfo(&free_mem, &total_mem) != cudaSuccess)
+       {
+         fprintf (stderr, "cudaMemGetInfo failed.\n");
+         abort ();
+       }
+
+      struct cudaDeviceProp p;
+      if (cudaGetDeviceProperties(&p, dev_num) != cudaSuccess)
+       {
+         fprintf (stderr, "cudaGetDeviceProperties failed.\n");
+         abort ();
+       }
+
+      int driver_version;
+      if (cudaDriverGetVersion(&driver_version) != cudaSuccess)
+       {
+         fprintf (stderr, "cudaDriverGetVersion failed.\n");
+         abort ();
+       }
+      /* The version string should contain the version of the CUDA Toolkit
+        in the same MAJOR.MINOR format that is used by Nvidia.
+        The format string below is the same that is used by the deviceQuery
+        program, which belongs to Nvidia's CUDA samples, to print the version. */
+      char driver[30];
+      snprintf (driver, sizeof driver, "CUDA Driver %u.%u",
+               driver_version / 1000, driver_version % 1000 / 10);
+
+      expect_device_properties(acc_device_nvidia, dev_num,
+                              total_mem, free_mem, vendor, p.name, driver);
+    }
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c
new file mode 100644 (file)
index 0000000..9256500
--- /dev/null
@@ -0,0 +1,19 @@
+/* Test the `acc_get_property' and '`acc_get_property_string' library
+   functions for the host device. */
+/* { dg-additional-sources acc_get_property-aux.c } */
+/* { dg-do run } */
+
+#include <openacc.h>
+#include <stdio.h>
+
+void expect_device_properties
+(acc_device_t dev_type, int dev_num,
+ int expected_total_mem, int expected_free_mem,
+ const char* expected_vendor, const char* expected_name,
+ const char* expected_driver);
+
+int main()
+{
+  printf ("Checking acc_device_host device properties\n");
+  expect_device_properties (acc_device_host, 0, 0, 0, "GNU", "GOMP", "1.0");
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c
new file mode 100644 (file)
index 0000000..952bdbf
--- /dev/null
@@ -0,0 +1,80 @@
+/* Auxiliary functions for acc_get_property tests */
+/* { dg-do compile  { target skip-all-targets } } */
+
+#include <openacc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+void expect_device_properties
+(acc_device_t dev_type, int dev_num,
+ int expected_total_mem, int expected_free_mem,
+ const char* expected_vendor, const char* expected_name,
+ const char* expected_driver)
+{
+  const char *vendor = acc_get_property_string (dev_num, dev_type,
+                                               acc_property_vendor);
+  if (strcmp (vendor, expected_vendor))
+    {
+      fprintf (stderr, "Expected acc_property_vendor to equal \"%s\", "
+              "but was \"%s\".\n", expected_vendor, vendor);
+      abort ();
+    }
+
+  int total_mem = acc_get_property (dev_num, dev_type,
+                                   acc_property_memory);
+  if (total_mem != expected_total_mem)
+    {
+      fprintf (stderr, "Expected acc_property_memory to equal %d, "
+              "but was %d.\n", expected_total_mem, total_mem);
+      abort ();
+
+    }
+
+  int free_mem = acc_get_property (dev_num, dev_type,
+                                  acc_property_free_memory);
+  if (free_mem != expected_free_mem)
+    {
+      fprintf (stderr, "Expected acc_property_free_memory to equal %d, "
+              "but was %d.\n", expected_free_mem, free_mem);
+      abort ();
+    }
+
+  const char *name = acc_get_property_string (dev_num, dev_type,
+                                             acc_property_name);
+  if (strcmp (name, expected_name))
+    {
+      fprintf(stderr, "Expected acc_property_name to equal \"%s\", "
+             "but was \"%s\".\n", expected_name, name);
+      abort ();
+    }
+
+  const char *driver = acc_get_property_string (dev_num, dev_type,
+                                               acc_property_driver);
+  if (strcmp (expected_driver, driver))
+    {
+      fprintf (stderr, "Expected acc_property_driver to equal %s, "
+              "but was %s.\n", expected_driver, driver);
+      abort ();
+    }
+
+  int unknown_property = 16058;
+  int v = acc_get_property (dev_num, dev_type, (acc_device_property_t)unknown_property);
+  if (v != 0)
+    {
+      fprintf (stderr, "Expected value of unknown numeric property to equal 0, "
+              "but was %d.\n", v);
+      abort ();
+    }
+
+  int unknown_property2 = -16058;
+  const char *s = acc_get_property_string (dev_num, dev_type, (acc_device_property_t)unknown_property2);
+  if (s != NULL)
+    {
+      fprintf (stderr, "Expected value of unknown string property to be NULL, "
+              "but was %d.\n", s);
+      abort ();
+    }
+
+
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property.c
new file mode 100644 (file)
index 0000000..289d1ba
--- /dev/null
@@ -0,0 +1,76 @@
+/* Test the `acc_get_property' and '`acc_get_property_string' library
+   functions by printing the results of those functions for all devices
+   of all device types mentioned in the OpenACC standard.
+
+   See also acc_get_property.f90. */
+/* { dg-do run { target { { ! { openacc_host_selected } } && { ! { openacc_amdgcn_accel_selected } } } } } */
+/* FIXME: This test does not work with the GCN implementation stub yet.  */
+
+#include <openacc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Print the values of the properties of all devices of the given type
+   and do basic device independent validation. */
+
+void
+print_device_properties(acc_device_t type)
+{
+  const char *s;
+  size_t v;
+
+  int dev_count = acc_get_num_devices(type);
+
+  for (int i = 0; i < dev_count; ++i)
+    {
+      printf("  Device %d:\n", i+1);
+
+      s = acc_get_property_string (i, type, acc_property_vendor);
+      printf ("    Vendor: %s\n", s);
+      if (s == NULL || *s == 0)
+       {
+         fprintf (stderr, "acc_property_vendor should not be null or empty.\n");
+         abort ();
+       }
+
+      v = acc_get_property (i, type,  acc_property_memory);
+      printf ("    Total memory: %zd\n", v);
+
+      v = acc_get_property (i, type, acc_property_free_memory);
+      printf ("    Free memory: %zd\n", v);
+
+      s = acc_get_property_string (i, type, acc_property_name);
+      printf ("    Name: %s\n", s);
+      if (s == NULL || *s == 0)
+       {
+         fprintf (stderr, "acc_property_name should not be null or empty.\n");
+         abort ();
+       }
+
+      s = acc_get_property_string (i, type, acc_property_driver);
+      printf ("    Driver: %s\n", s);
+      if (s == NULL || *s == 0)
+       {
+         fprintf (stderr, "acc_property_string should not be null or empty.\n");
+         abort ();
+       }
+    }
+}
+
+int main ()
+{
+  printf("acc_device_none:\n");
+  /* For completness; not expected to print anything since there
+     should be no devices of this type. */
+  print_device_properties(acc_device_none);
+
+  printf("acc_device_default:\n");
+  print_device_properties(acc_device_default);
+
+  printf("acc_device_host:\n");
+  print_device_properties(acc_device_host);
+
+  printf("acc_device_not_host:\n");
+  print_device_properties(acc_device_not_host);
+}
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/acc_get_property.f90 b/libgomp/testsuite/libgomp.oacc-fortran/acc_get_property.f90
new file mode 100644 (file)
index 0000000..ce69547
--- /dev/null
@@ -0,0 +1,93 @@
+! Test the `acc_get_property' and '`acc_get_property_string' library
+! functions by printing the results of those functions for all devices
+! of all device types mentioned in the OpenACC standard.
+!
+! See also acc_get_property.c
+! { dg-do run { target { { ! { openacc_host_selected } } && { ! { openacc_amdgcn_accel_selected } } } } }
+! FIXME: This test does not work with the GCN implementation stub yet.
+
+program test
+  use openacc
+  implicit none
+
+  print *, "acc_device_none:"
+  ! For completeness; not expected to print anything
+  call print_device_properties (acc_device_none)
+
+  print *, "acc_device_default:"
+  call print_device_properties (acc_device_default)
+
+  print *, "acc_device_host:"
+  call print_device_properties (acc_device_host)
+
+  print *, "acc_device_not_host:"
+  call print_device_properties (acc_device_not_host)
+end program test
+
+! Print the values of the properties of all devices of the given type
+! and do basic device independent validation.
+subroutine print_device_properties (device_type)
+  use openacc
+  implicit none
+
+  integer, intent(in) :: device_type
+
+  integer :: device_count
+  integer :: device
+  integer(acc_device_property) :: v
+  character*256 :: s
+
+  device_count = acc_get_num_devices(device_type)
+
+  do device = 0, device_count - 1
+     print "(a, i0)", "  Device ", device
+
+     call acc_get_property_string (device, device_type, acc_property_vendor, s)
+     print "(a, a)", "    Vendor: ", trim (s)
+     if (s == "") then
+        print *, "acc_property_vendor should not be empty."
+        stop 1
+     end if
+
+     v = acc_get_property (device, device_type, acc_property_memory)
+     print "(a, i0)", "    Total memory: ", v
+     if (v < 0) then
+        print *, "acc_property_memory should not be negative."
+        stop 1
+     end if
+
+     v = acc_get_property (device, device_type, acc_property_free_memory)
+     print "(a, i0)", "    Free memory: ", v
+     if (v < 0) then
+        print *, "acc_property_free_memory should not to be negative."
+        stop 1
+     end if
+
+     v = acc_get_property (device, device_type, int(2360, kind = acc_device_property))
+     if (v /= 0) then
+        print *, "Value of unknown numeric property should be 0."
+        stop 1
+     end if
+
+     call acc_get_property_string (device, device_type, acc_property_name, s)
+     print "(a, a)", "    Name: ", trim (s)
+     if (s == "") then
+        print *, "acc_property_name should not be empty."
+        stop 1
+     end if
+
+     call acc_get_property_string (device, device_type, acc_property_driver, s)
+     print "(a, a)", "    Driver: ", trim (s)
+     if (s == "") then
+        print *, "acc_property_driver should not be empty."
+        stop 1
+     end if
+
+     call acc_get_property_string (device, device_type, int(4060, kind = acc_device_property), s)
+     if (s /= "") then
+        print *, "Value of unknown string property should be empty string."
+        stop 1
+     end if
+
+  end do
+end subroutine print_device_properties
index 5a51615852703a5096976ad5ab2d53c7d385e8ee..b5fae878e9d55a7a8fa0d56838d42b29a9b2dbdf 100644 (file)
@@ -1,3 +1,11 @@
+2019-12-22  Maciej W. Rozycki  <macro@codesourcery.com>
+           Frederik Harwath  <frederik@codesourcery.com>
+           Thomas Schwinge  <tschwinge@codesourcery.com>
+
+       liboffloadmic/
+       * plugin/libgomp-plugin-intelmic.cpp (GOMP_OFFLOAD_get_property):
+       New function.
+
 2019-10-01  Maciej W. Rozycki  <macro@wdc.com>
 
        * plugin/configure: Regenerate.
index d1678d0514e91e775fff7fe361b861f706b53782..40d97702b87e108fef1b4e181dee8a30971103d4 100644 (file)
@@ -174,6 +174,27 @@ GOMP_OFFLOAD_get_num_devices (void)
   return num_devices;
 }
 
+extern "C" union gomp_device_property_value
+GOMP_OFFLOAD_get_property (int n, int prop)
+{
+  union gomp_device_property_value nullval = { .val = 0 };
+
+  if (n >= num_devices)
+    {
+      GOMP_PLUGIN_error
+       ("Request for a property of a non-existing Intel MIC device %i", n);
+      return nullval;
+    }
+
+  switch (prop)
+    {
+    case GOMP_DEVICE_PROPERTY_VENDOR:
+      return (union gomp_device_property_value) { .ptr =  "Intel" };
+    default:
+      return nullval;
+    }
+}
+
 static bool
 offload (const char *file, uint64_t line, int device, const char *name,
         int num_vars, VarDesc *vars, const void **async_data)