public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [gomp4.1] Support #pragma omp target {enter,exit} data
@ 2015-06-30 12:25 Ilya Verbin
  2015-06-30 12:57 ` Jakub Jelinek
  0 siblings, 1 reply; 18+ messages in thread
From: Ilya Verbin @ 2015-06-30 12:25 UTC (permalink / raw)
  To: Jakub Jelinek, gcc-patches; +Cc: Kirill Yukhin, Thomas Schwinge

Hi!

This patch implements GOMP_target_enter_exit_data in libgomp, also it fixes a
bug in gomp_map_vars_existing.
make check-target-libgomp passed.
However, I am afraid that there may be some hard-to-find issues (like memory
leaks) in cases of mixed (structured+unstructured) data mappings...
OK for gomp-4_1-branch?


libgomp/
	* target.c (gomp_map_vars_existing): Fix target address for 'always to'
	array sections.
	(gomp_unmap_vars): Decrement k->refcount when it's 1 and
	k->async_refcount is 0.
	(GOMP_target_enter_exit_data): Add mapping/unmapping.
	* testsuite/libgomp.c/target-11.c: Extend for testing 'always to' array
	sections.
	* testsuite/libgomp.c/target-12.c: New test.


diff --git a/libgomp/target.c b/libgomp/target.c
index a394e95..83ca827 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -171,7 +171,8 @@ gomp_map_vars_existing (struct gomp_device_descr *devicep, splay_tree_key oldn,
 
   if (GOMP_MAP_ALWAYS_TO_P (kind))
     devicep->host2dev_func (devicep->target_id,
-			    (void *) (oldn->tgt->tgt_start + oldn->tgt_offset),
+			    (void *) (oldn->tgt->tgt_start + oldn->tgt_offset
+				      + newn->host_start - oldn->host_start),
 			    (void *) newn->host_start,
 			    newn->host_end - newn->host_start);
   oldn->refcount++;
@@ -580,10 +581,16 @@ gomp_unmap_vars (struct target_mem_desc *tgt, bool do_copyfrom)
       bool do_unmap = false;
       if (k->refcount > 1)
 	k->refcount--;
-      else if (k->async_refcount > 0)
-	k->async_refcount--;
-      else
-	do_unmap = true;
+      else if (k->refcount == 1)
+	{
+	  if (k->async_refcount > 0)
+	    k->async_refcount--;
+	  else
+	    {
+	      k->refcount--;
+	      do_unmap = true;
+	    }
+	}
 
       if ((do_unmap && do_copyfrom && tgt->list[i].copy_from)
 	  || tgt->list[i].always_copy_from)
@@ -1160,13 +1167,61 @@ GOMP_target_enter_exit_data (int device, size_t mapnum, void **hostaddrs,
     }
 
   if (is_enter_data)
-    {
-      /* TODO  */
-    }
+    gomp_map_vars (devicep, mapnum, hostaddrs, NULL, sizes, kinds, true, false);
   else
-    {
-      /* TODO  */
-    }
+    for (i = 0; i < mapnum; i++)
+      {
+	struct splay_tree_key_s cur_node;
+	unsigned char kind = kinds[i] & typemask;
+	switch (kind)
+	  {
+	  case GOMP_MAP_FROM:
+	  case GOMP_MAP_ALWAYS_FROM:
+	  case GOMP_MAP_DELETE:
+	  case GOMP_MAP_RELEASE:
+	    cur_node.host_start = (uintptr_t) hostaddrs[i];
+	    cur_node.host_end = cur_node.host_start + sizes[i];
+	    gomp_mutex_lock (&devicep->lock);
+	    splay_tree_key k = splay_tree_lookup (&devicep->mem_map, &cur_node);
+	    if (!k)
+	      {
+		gomp_mutex_unlock (&devicep->lock);
+		continue;
+	      }
+
+	    if (k->refcount > 0)
+	      k->refcount--;
+	    if (kind == GOMP_MAP_DELETE)
+	      k->refcount = 0;
+
+	    if ((kind == GOMP_MAP_FROM && k->refcount == 0)
+		|| kind == GOMP_MAP_ALWAYS_FROM)
+	      devicep->dev2host_func (devicep->target_id,
+				      (void *) cur_node.host_start,
+				      (void *) (k->tgt->tgt_start
+						+ k->tgt_offset
+						+ cur_node.host_start
+						- k->host_start),
+				      cur_node.host_end - cur_node.host_start);
+	    if (k->refcount == 0)
+	      {
+		splay_tree_remove (&devicep->mem_map, k);
+		if (k->tgt->refcount > 1)
+		  k->tgt->refcount--;
+		else
+		  gomp_unmap_tgt (k->tgt);
+	      }
+
+	    gomp_mutex_unlock (&devicep->lock);
+	    break;
+	  case GOMP_MAP_POINTER:
+	  case GOMP_MAP_TO_PSET:
+	    break;
+	  default:
+	    gomp_fatal ("GOMP_target_enter_exit_data unhandled kind 0x%.2x",
+			kind);
+	  }
+      }
 }
 
 void
diff --git a/libgomp/testsuite/libgomp.c/target-11.c b/libgomp/testsuite/libgomp.c/target-11.c
index b86097a..98882f0 100644
--- a/libgomp/testsuite/libgomp.c/target-11.c
+++ b/libgomp/testsuite/libgomp.c/target-11.c
@@ -9,6 +9,17 @@ void test_array_section (int *p)
 {
   #pragma omp target data map(alloc: p[0:N])
     {
+      int ok = 1;
+      for (int i = 10; i < 10 + 4; i++)
+	p[i] = 997 * i;
+
+      #pragma omp target map(always to:p[10:4]) map(tofrom: ok)
+	for (int i = 10; i < 10 + 4; i++)
+	  if (p[i] != 997 * i)
+	    ok = 0;
+
+      assert (ok);
+
       #pragma omp target map(always from:p[7:9])
 	for (int i = 0; i < N; i++)
 	  p[i] = i;
diff --git a/libgomp/testsuite/libgomp.c/target-12.c b/libgomp/testsuite/libgomp.c/target-12.c
new file mode 100644
index 0000000..e22f765
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-12.c
@@ -0,0 +1,98 @@
+/* { dg-require-effective-target offload_device } */
+
+#include <stdlib.h>
+#include <assert.h>
+
+#define N 32
+
+int sum;
+int var1 = 1;
+int var2 = 2;
+
+void enter_data (int *X)
+{
+  #pragma omp target enter data map(to: var1, var2, X[:N]) map(alloc: sum)
+}
+
+void exit_data_1 ()
+{
+  #pragma omp target exit data map(from: var1)
+}
+
+void exit_data_2 ()
+{
+  #pragma omp target exit data map(from: var2)
+}
+
+void test_nested ()
+{
+  int X = 0, Y = 0, Z = 0;
+
+  #pragma omp target data map(from: X, Y, Z)
+    {
+      #pragma omp target data map(from: X, Y, Z)
+	{
+	  #pragma omp target map(from: X, Y, Z)
+	    X = Y = Z = 1337;
+	  assert (X == 0);
+	  assert (Y == 0);
+	  assert (Z == 0);
+
+	  #pragma omp target exit data map(from: X) map(release: Y)
+	  assert (X == 0);
+	  assert (Y == 0);
+
+	  #pragma omp target exit data map(release: Y) map(delete: Z)
+	  assert (Y == 0);
+	  assert (Z == 0);
+	}
+      assert (X == 1337);
+      assert (Y == 0);
+      assert (Z == 0);
+
+      #pragma omp target map(from: X)
+	X = 2448;
+      assert (X == 2448);
+      assert (Y == 0);
+      assert (Z == 0);
+
+      X = 4896;
+    }
+  assert (X == 4896);
+  assert (Y == 0);
+  assert (Z == 0);
+}
+
+int main ()
+{
+  int *X = malloc (N * sizeof (int));
+  int *Y = malloc (N * sizeof (int));
+  X[10] = 10;
+  Y[20] = 20;
+  enter_data (X);
+
+  #pragma omp target map(alloc: X[:N]) map(to: Y[:N]) map(always from: sum)
+    {
+      var1 += X[10];
+      var2 += Y[20];
+      sum = var1 + var2;
+    }
+
+  free (X);
+  free (Y);
+
+  assert (var1 == 1);
+  assert (var2 == 2);
+  assert (sum == 33);
+
+  exit_data_1 ();
+  assert (var1 == 11);
+  assert (var2 == 2);
+
+  exit_data_2 ();
+  assert (var2 == 22);
+
+  test_nested ();
+
+  return 0;
+}


    -- Ilya

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2019-11-14 11:57 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-30 12:25 [gomp4.1] Support #pragma omp target {enter,exit} data Ilya Verbin
2015-06-30 12:57 ` Jakub Jelinek
2015-06-30 15:47   ` Ilya Verbin
2015-06-30 16:24     ` Jakub Jelinek
2015-07-01 21:07       ` Ilya Verbin
2015-07-06 15:34         ` Ilya Verbin
2015-07-06 17:25           ` Jakub Jelinek
2015-07-06 18:45             ` Ilya Verbin
2015-07-06 20:42               ` Jakub Jelinek
2015-07-29 19:24                 ` Ilya Verbin
2015-07-30  8:27                   ` Jakub Jelinek
2015-07-30 14:46                     ` Ilya Verbin
2015-07-30 15:09                       ` Jakub Jelinek
2015-07-30 20:30                     ` Ilya Verbin
2015-07-30 21:37                       ` Jakub Jelinek
2019-11-14 11:09                       ` Thomas Schwinge
2019-11-14 11:28                         ` Jakub Jelinek
2019-11-14 12:00                         ` Julian Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).