Home | History | Annotate | Line # | Download | only in libgomp
oacc-parallel.c revision 1.1.1.2.4.2
      1  1.1.1.2.4.2    martin /* Copyright (C) 2013-2018 Free Software Foundation, Inc.
      2          1.1       mrg 
      3          1.1       mrg    Contributed by Mentor Embedded.
      4          1.1       mrg 
      5          1.1       mrg    This file is part of the GNU Offloading and Multi Processing Library
      6          1.1       mrg    (libgomp).
      7          1.1       mrg 
      8          1.1       mrg    Libgomp is free software; you can redistribute it and/or modify it
      9          1.1       mrg    under the terms of the GNU General Public License as published by
     10          1.1       mrg    the Free Software Foundation; either version 3, or (at your option)
     11          1.1       mrg    any later version.
     12          1.1       mrg 
     13          1.1       mrg    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
     14          1.1       mrg    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     15          1.1       mrg    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     16          1.1       mrg    more details.
     17          1.1       mrg 
     18          1.1       mrg    Under Section 7 of GPL version 3, you are granted additional
     19          1.1       mrg    permissions described in the GCC Runtime Library Exception, version
     20          1.1       mrg    3.1, as published by the Free Software Foundation.
     21          1.1       mrg 
     22          1.1       mrg    You should have received a copy of the GNU General Public License and
     23          1.1       mrg    a copy of the GCC Runtime Library Exception along with this program;
     24          1.1       mrg    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25          1.1       mrg    <http://www.gnu.org/licenses/>.  */
     26          1.1       mrg 
     27          1.1       mrg /* This file handles OpenACC constructs.  */
     28          1.1       mrg 
     29          1.1       mrg #include "openacc.h"
     30          1.1       mrg #include "libgomp.h"
     31          1.1       mrg #include "libgomp_g.h"
     32          1.1       mrg #include "gomp-constants.h"
     33          1.1       mrg #include "oacc-int.h"
     34          1.1       mrg #ifdef HAVE_INTTYPES_H
     35          1.1       mrg # include <inttypes.h>  /* For PRIu64.  */
     36          1.1       mrg #endif
     37          1.1       mrg #include <string.h>
     38          1.1       mrg #include <stdarg.h>
     39          1.1       mrg #include <assert.h>
     40          1.1       mrg 
     41          1.1       mrg static int
     42          1.1       mrg find_pset (int pos, size_t mapnum, unsigned short *kinds)
     43          1.1       mrg {
     44          1.1       mrg   if (pos + 1 >= mapnum)
     45          1.1       mrg     return 0;
     46          1.1       mrg 
     47          1.1       mrg   unsigned char kind = kinds[pos+1] & 0xff;
     48          1.1       mrg 
     49          1.1       mrg   return kind == GOMP_MAP_TO_PSET;
     50          1.1       mrg }
     51          1.1       mrg 
     52      1.1.1.2       mrg static void goacc_wait (int async, int num_waits, va_list *ap);
     53      1.1.1.2       mrg 
     54      1.1.1.2       mrg 
     55      1.1.1.2       mrg /* Launch a possibly offloaded function on DEVICE.  FN is the host fn
     56      1.1.1.2       mrg    address.  MAPNUM, HOSTADDRS, SIZES & KINDS  describe the memory
     57      1.1.1.2       mrg    blocks to be copied to/from the device.  Varadic arguments are
     58      1.1.1.2       mrg    keyed optional parameters terminated with a zero.  */
     59          1.1       mrg 
     60          1.1       mrg void
     61      1.1.1.2       mrg GOACC_parallel_keyed (int device, void (*fn) (void *),
     62      1.1.1.2       mrg 		      size_t mapnum, void **hostaddrs, size_t *sizes,
     63      1.1.1.2       mrg 		      unsigned short *kinds, ...)
     64          1.1       mrg {
     65          1.1       mrg   bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK;
     66          1.1       mrg   va_list ap;
     67          1.1       mrg   struct goacc_thread *thr;
     68          1.1       mrg   struct gomp_device_descr *acc_dev;
     69          1.1       mrg   struct target_mem_desc *tgt;
     70          1.1       mrg   void **devaddrs;
     71          1.1       mrg   unsigned int i;
     72          1.1       mrg   struct splay_tree_key_s k;
     73          1.1       mrg   splay_tree_key tgt_fn_key;
     74          1.1       mrg   void (*tgt_fn);
     75      1.1.1.2       mrg   int async = GOMP_ASYNC_SYNC;
     76      1.1.1.2       mrg   unsigned dims[GOMP_DIM_MAX];
     77      1.1.1.2       mrg   unsigned tag;
     78          1.1       mrg 
     79          1.1       mrg #ifdef HAVE_INTTYPES_H
     80      1.1.1.2       mrg   gomp_debug (0, "%s: mapnum=%"PRIu64", hostaddrs=%p, size=%p, kinds=%p\n",
     81      1.1.1.2       mrg 	      __FUNCTION__, (uint64_t) mapnum, hostaddrs, sizes, kinds);
     82          1.1       mrg #else
     83      1.1.1.2       mrg   gomp_debug (0, "%s: mapnum=%lu, hostaddrs=%p, sizes=%p, kinds=%p\n",
     84      1.1.1.2       mrg 	      __FUNCTION__, (unsigned long) mapnum, hostaddrs, sizes, kinds);
     85          1.1       mrg #endif
     86          1.1       mrg   goacc_lazy_initialize ();
     87          1.1       mrg 
     88          1.1       mrg   thr = goacc_thread ();
     89          1.1       mrg   acc_dev = thr->dev;
     90          1.1       mrg 
     91          1.1       mrg   /* Host fallback if "if" clause is false or if the current device is set to
     92          1.1       mrg      the host.  */
     93          1.1       mrg   if (host_fallback)
     94          1.1       mrg     {
     95          1.1       mrg       goacc_save_and_set_bind (acc_device_host);
     96          1.1       mrg       fn (hostaddrs);
     97          1.1       mrg       goacc_restore_bind ();
     98          1.1       mrg       return;
     99          1.1       mrg     }
    100          1.1       mrg   else if (acc_device_type (acc_dev->type) == acc_device_host)
    101          1.1       mrg     {
    102          1.1       mrg       fn (hostaddrs);
    103          1.1       mrg       return;
    104          1.1       mrg     }
    105          1.1       mrg 
    106      1.1.1.2       mrg   /* Default: let the runtime choose.  */
    107      1.1.1.2       mrg   for (i = 0; i != GOMP_DIM_MAX; i++)
    108      1.1.1.2       mrg     dims[i] = 0;
    109      1.1.1.2       mrg 
    110      1.1.1.2       mrg   va_start (ap, kinds);
    111      1.1.1.2       mrg   /* TODO: This will need amending when device_type is implemented.  */
    112      1.1.1.2       mrg   while ((tag = va_arg (ap, unsigned)) != 0)
    113      1.1.1.2       mrg     {
    114      1.1.1.2       mrg       if (GOMP_LAUNCH_DEVICE (tag))
    115      1.1.1.2       mrg 	gomp_fatal ("device_type '%d' offload parameters, libgomp is too old",
    116      1.1.1.2       mrg 		    GOMP_LAUNCH_DEVICE (tag));
    117          1.1       mrg 
    118      1.1.1.2       mrg       switch (GOMP_LAUNCH_CODE (tag))
    119      1.1.1.2       mrg 	{
    120      1.1.1.2       mrg 	case GOMP_LAUNCH_DIM:
    121      1.1.1.2       mrg 	  {
    122      1.1.1.2       mrg 	    unsigned mask = GOMP_LAUNCH_OP (tag);
    123      1.1.1.2       mrg 
    124      1.1.1.2       mrg 	    for (i = 0; i != GOMP_DIM_MAX; i++)
    125      1.1.1.2       mrg 	      if (mask & GOMP_DIM_MASK (i))
    126      1.1.1.2       mrg 		dims[i] = va_arg (ap, unsigned);
    127      1.1.1.2       mrg 	  }
    128      1.1.1.2       mrg 	  break;
    129      1.1.1.2       mrg 
    130      1.1.1.2       mrg 	case GOMP_LAUNCH_ASYNC:
    131      1.1.1.2       mrg 	  {
    132      1.1.1.2       mrg 	    /* Small constant values are encoded in the operand.  */
    133      1.1.1.2       mrg 	    async = GOMP_LAUNCH_OP (tag);
    134      1.1.1.2       mrg 
    135      1.1.1.2       mrg 	    if (async == GOMP_LAUNCH_OP_MAX)
    136      1.1.1.2       mrg 	      async = va_arg (ap, unsigned);
    137      1.1.1.2       mrg 	    break;
    138      1.1.1.2       mrg 	  }
    139          1.1       mrg 
    140      1.1.1.2       mrg 	case GOMP_LAUNCH_WAIT:
    141      1.1.1.2       mrg 	  {
    142      1.1.1.2       mrg 	    unsigned num_waits = GOMP_LAUNCH_OP (tag);
    143      1.1.1.2       mrg 
    144      1.1.1.2       mrg 	    if (num_waits)
    145      1.1.1.2       mrg 	      goacc_wait (async, num_waits, &ap);
    146      1.1.1.2       mrg 	    break;
    147      1.1.1.2       mrg 	  }
    148      1.1.1.2       mrg 
    149      1.1.1.2       mrg 	default:
    150      1.1.1.2       mrg 	  gomp_fatal ("unrecognized offload code '%d',"
    151      1.1.1.2       mrg 		      " libgomp is too old", GOMP_LAUNCH_CODE (tag));
    152      1.1.1.2       mrg 	}
    153      1.1.1.2       mrg     }
    154      1.1.1.2       mrg   va_end (ap);
    155      1.1.1.2       mrg 
    156          1.1       mrg   acc_dev->openacc.async_set_async_func (async);
    157          1.1       mrg 
    158          1.1       mrg   if (!(acc_dev->capabilities & GOMP_OFFLOAD_CAP_NATIVE_EXEC))
    159          1.1       mrg     {
    160          1.1       mrg       k.host_start = (uintptr_t) fn;
    161          1.1       mrg       k.host_end = k.host_start + 1;
    162          1.1       mrg       gomp_mutex_lock (&acc_dev->lock);
    163          1.1       mrg       tgt_fn_key = splay_tree_lookup (&acc_dev->mem_map, &k);
    164          1.1       mrg       gomp_mutex_unlock (&acc_dev->lock);
    165          1.1       mrg 
    166          1.1       mrg       if (tgt_fn_key == NULL)
    167          1.1       mrg 	gomp_fatal ("target function wasn't mapped");
    168          1.1       mrg 
    169          1.1       mrg       tgt_fn = (void (*)) tgt_fn_key->tgt_offset;
    170          1.1       mrg     }
    171          1.1       mrg   else
    172          1.1       mrg     tgt_fn = (void (*)) fn;
    173          1.1       mrg 
    174          1.1       mrg   tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, NULL, sizes, kinds, true,
    175      1.1.1.2       mrg 		       GOMP_MAP_VARS_OPENACC);
    176          1.1       mrg 
    177          1.1       mrg   devaddrs = gomp_alloca (sizeof (void *) * mapnum);
    178          1.1       mrg   for (i = 0; i < mapnum; i++)
    179      1.1.1.2       mrg     devaddrs[i] = (void *) (tgt->list[i].key->tgt->tgt_start
    180      1.1.1.2       mrg 			    + tgt->list[i].key->tgt_offset);
    181          1.1       mrg 
    182      1.1.1.2       mrg   acc_dev->openacc.exec_func (tgt_fn, mapnum, hostaddrs, devaddrs,
    183      1.1.1.2       mrg 			      async, dims, tgt);
    184          1.1       mrg 
    185          1.1       mrg   /* If running synchronously, unmap immediately.  */
    186          1.1       mrg   if (async < acc_async_noval)
    187          1.1       mrg     gomp_unmap_vars (tgt, true);
    188          1.1       mrg   else
    189  1.1.1.2.4.1  christos     tgt->device_descr->openacc.register_async_cleanup_func (tgt, async);
    190          1.1       mrg 
    191          1.1       mrg   acc_dev->openacc.async_set_async_func (acc_async_sync);
    192          1.1       mrg }
    193          1.1       mrg 
    194      1.1.1.2       mrg /* Legacy entry point, only provide host execution.  */
    195      1.1.1.2       mrg 
    196      1.1.1.2       mrg void
    197      1.1.1.2       mrg GOACC_parallel (int device, void (*fn) (void *),
    198      1.1.1.2       mrg 		size_t mapnum, void **hostaddrs, size_t *sizes,
    199      1.1.1.2       mrg 		unsigned short *kinds,
    200      1.1.1.2       mrg 		int num_gangs, int num_workers, int vector_length,
    201      1.1.1.2       mrg 		int async, int num_waits, ...)
    202      1.1.1.2       mrg {
    203      1.1.1.2       mrg   goacc_save_and_set_bind (acc_device_host);
    204      1.1.1.2       mrg   fn (hostaddrs);
    205      1.1.1.2       mrg   goacc_restore_bind ();
    206      1.1.1.2       mrg }
    207      1.1.1.2       mrg 
    208          1.1       mrg void
    209          1.1       mrg GOACC_data_start (int device, size_t mapnum,
    210          1.1       mrg 		  void **hostaddrs, size_t *sizes, unsigned short *kinds)
    211          1.1       mrg {
    212          1.1       mrg   bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK;
    213          1.1       mrg   struct target_mem_desc *tgt;
    214          1.1       mrg 
    215          1.1       mrg #ifdef HAVE_INTTYPES_H
    216          1.1       mrg   gomp_debug (0, "%s: mapnum=%"PRIu64", hostaddrs=%p, size=%p, kinds=%p\n",
    217          1.1       mrg 	      __FUNCTION__, (uint64_t) mapnum, hostaddrs, sizes, kinds);
    218          1.1       mrg #else
    219          1.1       mrg   gomp_debug (0, "%s: mapnum=%lu, hostaddrs=%p, sizes=%p, kinds=%p\n",
    220          1.1       mrg 	      __FUNCTION__, (unsigned long) mapnum, hostaddrs, sizes, kinds);
    221          1.1       mrg #endif
    222          1.1       mrg 
    223          1.1       mrg   goacc_lazy_initialize ();
    224          1.1       mrg 
    225          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    226          1.1       mrg   struct gomp_device_descr *acc_dev = thr->dev;
    227          1.1       mrg 
    228          1.1       mrg   /* Host fallback or 'do nothing'.  */
    229          1.1       mrg   if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
    230          1.1       mrg       || host_fallback)
    231          1.1       mrg     {
    232      1.1.1.2       mrg       tgt = gomp_map_vars (NULL, 0, NULL, NULL, NULL, NULL, true,
    233      1.1.1.2       mrg 			   GOMP_MAP_VARS_OPENACC);
    234          1.1       mrg       tgt->prev = thr->mapped_data;
    235          1.1       mrg       thr->mapped_data = tgt;
    236          1.1       mrg 
    237          1.1       mrg       return;
    238          1.1       mrg     }
    239          1.1       mrg 
    240          1.1       mrg   gomp_debug (0, "  %s: prepare mappings\n", __FUNCTION__);
    241          1.1       mrg   tgt = gomp_map_vars (acc_dev, mapnum, hostaddrs, NULL, sizes, kinds, true,
    242      1.1.1.2       mrg 		       GOMP_MAP_VARS_OPENACC);
    243          1.1       mrg   gomp_debug (0, "  %s: mappings prepared\n", __FUNCTION__);
    244          1.1       mrg   tgt->prev = thr->mapped_data;
    245          1.1       mrg   thr->mapped_data = tgt;
    246          1.1       mrg }
    247          1.1       mrg 
    248          1.1       mrg void
    249          1.1       mrg GOACC_data_end (void)
    250          1.1       mrg {
    251          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    252          1.1       mrg   struct target_mem_desc *tgt = thr->mapped_data;
    253          1.1       mrg 
    254          1.1       mrg   gomp_debug (0, "  %s: restore mappings\n", __FUNCTION__);
    255          1.1       mrg   thr->mapped_data = tgt->prev;
    256          1.1       mrg   gomp_unmap_vars (tgt, true);
    257          1.1       mrg   gomp_debug (0, "  %s: mappings restored\n", __FUNCTION__);
    258          1.1       mrg }
    259          1.1       mrg 
    260          1.1       mrg void
    261          1.1       mrg GOACC_enter_exit_data (int device, size_t mapnum,
    262          1.1       mrg 		       void **hostaddrs, size_t *sizes, unsigned short *kinds,
    263          1.1       mrg 		       int async, int num_waits, ...)
    264          1.1       mrg {
    265          1.1       mrg   struct goacc_thread *thr;
    266          1.1       mrg   struct gomp_device_descr *acc_dev;
    267          1.1       mrg   bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK;
    268          1.1       mrg   bool data_enter = false;
    269          1.1       mrg   size_t i;
    270          1.1       mrg 
    271          1.1       mrg   goacc_lazy_initialize ();
    272          1.1       mrg 
    273          1.1       mrg   thr = goacc_thread ();
    274          1.1       mrg   acc_dev = thr->dev;
    275          1.1       mrg 
    276          1.1       mrg   if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
    277          1.1       mrg       || host_fallback)
    278          1.1       mrg     return;
    279          1.1       mrg 
    280      1.1.1.2       mrg   if (num_waits)
    281          1.1       mrg     {
    282          1.1       mrg       va_list ap;
    283          1.1       mrg 
    284          1.1       mrg       va_start (ap, num_waits);
    285      1.1.1.2       mrg       goacc_wait (async, num_waits, &ap);
    286          1.1       mrg       va_end (ap);
    287          1.1       mrg     }
    288          1.1       mrg 
    289          1.1       mrg   acc_dev->openacc.async_set_async_func (async);
    290          1.1       mrg 
    291          1.1       mrg   /* Determine if this is an "acc enter data".  */
    292          1.1       mrg   for (i = 0; i < mapnum; ++i)
    293          1.1       mrg     {
    294          1.1       mrg       unsigned char kind = kinds[i] & 0xff;
    295          1.1       mrg 
    296          1.1       mrg       if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
    297          1.1       mrg 	continue;
    298          1.1       mrg 
    299          1.1       mrg       if (kind == GOMP_MAP_FORCE_ALLOC
    300          1.1       mrg 	  || kind == GOMP_MAP_FORCE_PRESENT
    301          1.1       mrg 	  || kind == GOMP_MAP_FORCE_TO)
    302          1.1       mrg 	{
    303          1.1       mrg 	  data_enter = true;
    304          1.1       mrg 	  break;
    305          1.1       mrg 	}
    306          1.1       mrg 
    307      1.1.1.2       mrg       if (kind == GOMP_MAP_DELETE
    308          1.1       mrg 	  || kind == GOMP_MAP_FORCE_FROM)
    309          1.1       mrg 	break;
    310          1.1       mrg 
    311          1.1       mrg       gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
    312          1.1       mrg 		      kind);
    313          1.1       mrg     }
    314          1.1       mrg 
    315          1.1       mrg   if (data_enter)
    316          1.1       mrg     {
    317          1.1       mrg       for (i = 0; i < mapnum; i++)
    318          1.1       mrg 	{
    319          1.1       mrg 	  unsigned char kind = kinds[i] & 0xff;
    320          1.1       mrg 
    321          1.1       mrg 	  /* Scan for PSETs.  */
    322          1.1       mrg 	  int psets = find_pset (i, mapnum, kinds);
    323          1.1       mrg 
    324          1.1       mrg 	  if (!psets)
    325          1.1       mrg 	    {
    326          1.1       mrg 	      switch (kind)
    327          1.1       mrg 		{
    328          1.1       mrg 		case GOMP_MAP_POINTER:
    329          1.1       mrg 		  gomp_acc_insert_pointer (1, &hostaddrs[i], &sizes[i],
    330          1.1       mrg 					&kinds[i]);
    331          1.1       mrg 		  break;
    332          1.1       mrg 		case GOMP_MAP_FORCE_ALLOC:
    333          1.1       mrg 		  acc_create (hostaddrs[i], sizes[i]);
    334          1.1       mrg 		  break;
    335          1.1       mrg 		case GOMP_MAP_FORCE_PRESENT:
    336          1.1       mrg 		  acc_present_or_copyin (hostaddrs[i], sizes[i]);
    337          1.1       mrg 		  break;
    338          1.1       mrg 		case GOMP_MAP_FORCE_TO:
    339          1.1       mrg 		  acc_present_or_copyin (hostaddrs[i], sizes[i]);
    340          1.1       mrg 		  break;
    341          1.1       mrg 		default:
    342          1.1       mrg 		  gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
    343          1.1       mrg 			      kind);
    344          1.1       mrg 		  break;
    345          1.1       mrg 		}
    346          1.1       mrg 	    }
    347          1.1       mrg 	  else
    348          1.1       mrg 	    {
    349          1.1       mrg 	      gomp_acc_insert_pointer (3, &hostaddrs[i], &sizes[i], &kinds[i]);
    350          1.1       mrg 	      /* Increment 'i' by two because OpenACC requires fortran
    351          1.1       mrg 		 arrays to be contiguous, so each PSET is associated with
    352          1.1       mrg 		 one of MAP_FORCE_ALLOC/MAP_FORCE_PRESET/MAP_FORCE_TO, and
    353          1.1       mrg 		 one MAP_POINTER.  */
    354          1.1       mrg 	      i += 2;
    355          1.1       mrg 	    }
    356          1.1       mrg 	}
    357          1.1       mrg     }
    358          1.1       mrg   else
    359          1.1       mrg     for (i = 0; i < mapnum; ++i)
    360          1.1       mrg       {
    361          1.1       mrg 	unsigned char kind = kinds[i] & 0xff;
    362          1.1       mrg 
    363          1.1       mrg 	int psets = find_pset (i, mapnum, kinds);
    364          1.1       mrg 
    365          1.1       mrg 	if (!psets)
    366          1.1       mrg 	  {
    367          1.1       mrg 	    switch (kind)
    368          1.1       mrg 	      {
    369          1.1       mrg 	      case GOMP_MAP_POINTER:
    370          1.1       mrg 		gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff)
    371          1.1       mrg 					 == GOMP_MAP_FORCE_FROM,
    372          1.1       mrg 					 async, 1);
    373          1.1       mrg 		break;
    374      1.1.1.2       mrg 	      case GOMP_MAP_DELETE:
    375          1.1       mrg 		acc_delete (hostaddrs[i], sizes[i]);
    376          1.1       mrg 		break;
    377          1.1       mrg 	      case GOMP_MAP_FORCE_FROM:
    378          1.1       mrg 		acc_copyout (hostaddrs[i], sizes[i]);
    379          1.1       mrg 		break;
    380          1.1       mrg 	      default:
    381          1.1       mrg 		gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
    382          1.1       mrg 			    kind);
    383          1.1       mrg 		break;
    384          1.1       mrg 	      }
    385          1.1       mrg 	  }
    386          1.1       mrg 	else
    387          1.1       mrg 	  {
    388          1.1       mrg 	    gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff)
    389          1.1       mrg 				     == GOMP_MAP_FORCE_FROM, async, 3);
    390          1.1       mrg 	    /* See the above comment.  */
    391          1.1       mrg 	    i += 2;
    392          1.1       mrg 	  }
    393          1.1       mrg       }
    394          1.1       mrg 
    395          1.1       mrg   acc_dev->openacc.async_set_async_func (acc_async_sync);
    396          1.1       mrg }
    397          1.1       mrg 
    398          1.1       mrg static void
    399      1.1.1.2       mrg goacc_wait (int async, int num_waits, va_list *ap)
    400          1.1       mrg {
    401          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    402          1.1       mrg   struct gomp_device_descr *acc_dev = thr->dev;
    403          1.1       mrg 
    404      1.1.1.2       mrg   while (num_waits--)
    405          1.1       mrg     {
    406      1.1.1.2       mrg       int qid = va_arg (*ap, int);
    407      1.1.1.2       mrg 
    408          1.1       mrg       if (acc_async_test (qid))
    409          1.1       mrg 	continue;
    410          1.1       mrg 
    411      1.1.1.2       mrg       if (async == acc_async_sync)
    412      1.1.1.2       mrg 	acc_wait (qid);
    413      1.1.1.2       mrg       else if (qid == async)
    414      1.1.1.2       mrg 	;/* If we're waiting on the same asynchronous queue as we're
    415      1.1.1.2       mrg 	    launching on, the queue itself will order work as
    416      1.1.1.2       mrg 	    required, so there's no need to wait explicitly.  */
    417      1.1.1.2       mrg       else
    418          1.1       mrg 	acc_dev->openacc.async_wait_async_func (qid, async);
    419          1.1       mrg     }
    420          1.1       mrg }
    421          1.1       mrg 
    422          1.1       mrg void
    423          1.1       mrg GOACC_update (int device, size_t mapnum,
    424          1.1       mrg 	      void **hostaddrs, size_t *sizes, unsigned short *kinds,
    425          1.1       mrg 	      int async, int num_waits, ...)
    426          1.1       mrg {
    427          1.1       mrg   bool host_fallback = device == GOMP_DEVICE_HOST_FALLBACK;
    428          1.1       mrg   size_t i;
    429          1.1       mrg 
    430          1.1       mrg   goacc_lazy_initialize ();
    431          1.1       mrg 
    432          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    433          1.1       mrg   struct gomp_device_descr *acc_dev = thr->dev;
    434          1.1       mrg 
    435          1.1       mrg   if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
    436          1.1       mrg       || host_fallback)
    437          1.1       mrg     return;
    438          1.1       mrg 
    439      1.1.1.2       mrg   if (num_waits)
    440          1.1       mrg     {
    441          1.1       mrg       va_list ap;
    442          1.1       mrg 
    443          1.1       mrg       va_start (ap, num_waits);
    444      1.1.1.2       mrg       goacc_wait (async, num_waits, &ap);
    445          1.1       mrg       va_end (ap);
    446          1.1       mrg     }
    447          1.1       mrg 
    448          1.1       mrg   acc_dev->openacc.async_set_async_func (async);
    449          1.1       mrg 
    450          1.1       mrg   for (i = 0; i < mapnum; ++i)
    451          1.1       mrg     {
    452          1.1       mrg       unsigned char kind = kinds[i] & 0xff;
    453          1.1       mrg 
    454          1.1       mrg       switch (kind)
    455          1.1       mrg 	{
    456          1.1       mrg 	case GOMP_MAP_POINTER:
    457          1.1       mrg 	case GOMP_MAP_TO_PSET:
    458          1.1       mrg 	  break;
    459          1.1       mrg 
    460          1.1       mrg 	case GOMP_MAP_FORCE_TO:
    461          1.1       mrg 	  acc_update_device (hostaddrs[i], sizes[i]);
    462          1.1       mrg 	  break;
    463          1.1       mrg 
    464          1.1       mrg 	case GOMP_MAP_FORCE_FROM:
    465          1.1       mrg 	  acc_update_self (hostaddrs[i], sizes[i]);
    466          1.1       mrg 	  break;
    467          1.1       mrg 
    468          1.1       mrg 	default:
    469          1.1       mrg 	  gomp_fatal (">>>> GOACC_update UNHANDLED kind 0x%.2x", kind);
    470          1.1       mrg 	  break;
    471          1.1       mrg 	}
    472          1.1       mrg     }
    473          1.1       mrg 
    474          1.1       mrg   acc_dev->openacc.async_set_async_func (acc_async_sync);
    475          1.1       mrg }
    476          1.1       mrg 
    477          1.1       mrg void
    478          1.1       mrg GOACC_wait (int async, int num_waits, ...)
    479          1.1       mrg {
    480      1.1.1.2       mrg   if (num_waits)
    481      1.1.1.2       mrg     {
    482      1.1.1.2       mrg       va_list ap;
    483          1.1       mrg 
    484      1.1.1.2       mrg       va_start (ap, num_waits);
    485      1.1.1.2       mrg       goacc_wait (async, num_waits, &ap);
    486      1.1.1.2       mrg       va_end (ap);
    487      1.1.1.2       mrg     }
    488      1.1.1.2       mrg   else if (async == acc_async_sync)
    489      1.1.1.2       mrg     acc_wait_all ();
    490      1.1.1.2       mrg   else if (async == acc_async_noval)
    491      1.1.1.2       mrg     goacc_thread ()->dev->openacc.async_wait_all_async_func (acc_async_noval);
    492          1.1       mrg }
    493          1.1       mrg 
    494          1.1       mrg int
    495          1.1       mrg GOACC_get_num_threads (void)
    496          1.1       mrg {
    497          1.1       mrg   return 1;
    498          1.1       mrg }
    499          1.1       mrg 
    500          1.1       mrg int
    501          1.1       mrg GOACC_get_thread_num (void)
    502          1.1       mrg {
    503          1.1       mrg   return 0;
    504          1.1       mrg }
    505      1.1.1.2       mrg 
    506      1.1.1.2       mrg void
    507      1.1.1.2       mrg GOACC_declare (int device, size_t mapnum,
    508      1.1.1.2       mrg 	       void **hostaddrs, size_t *sizes, unsigned short *kinds)
    509      1.1.1.2       mrg {
    510      1.1.1.2       mrg   int i;
    511      1.1.1.2       mrg 
    512      1.1.1.2       mrg   for (i = 0; i < mapnum; i++)
    513      1.1.1.2       mrg     {
    514      1.1.1.2       mrg       unsigned char kind = kinds[i] & 0xff;
    515      1.1.1.2       mrg 
    516      1.1.1.2       mrg       if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
    517      1.1.1.2       mrg 	continue;
    518      1.1.1.2       mrg 
    519      1.1.1.2       mrg       switch (kind)
    520      1.1.1.2       mrg 	{
    521      1.1.1.2       mrg 	  case GOMP_MAP_FORCE_ALLOC:
    522      1.1.1.2       mrg 	  case GOMP_MAP_FORCE_FROM:
    523      1.1.1.2       mrg 	  case GOMP_MAP_FORCE_TO:
    524      1.1.1.2       mrg 	  case GOMP_MAP_POINTER:
    525      1.1.1.2       mrg 	  case GOMP_MAP_DELETE:
    526      1.1.1.2       mrg 	    GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
    527      1.1.1.2       mrg 				   &kinds[i], 0, 0);
    528      1.1.1.2       mrg 	    break;
    529      1.1.1.2       mrg 
    530      1.1.1.2       mrg 	  case GOMP_MAP_FORCE_DEVICEPTR:
    531      1.1.1.2       mrg 	    break;
    532      1.1.1.2       mrg 
    533      1.1.1.2       mrg 	  case GOMP_MAP_ALLOC:
    534      1.1.1.2       mrg 	    if (!acc_is_present (hostaddrs[i], sizes[i]))
    535      1.1.1.2       mrg 	      GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
    536      1.1.1.2       mrg 				     &kinds[i], 0, 0);
    537      1.1.1.2       mrg 	    break;
    538      1.1.1.2       mrg 
    539      1.1.1.2       mrg 	  case GOMP_MAP_TO:
    540      1.1.1.2       mrg 	    GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
    541      1.1.1.2       mrg 				   &kinds[i], 0, 0);
    542      1.1.1.2       mrg 
    543      1.1.1.2       mrg 	    break;
    544      1.1.1.2       mrg 
    545      1.1.1.2       mrg 	  case GOMP_MAP_FROM:
    546      1.1.1.2       mrg 	    kinds[i] = GOMP_MAP_FORCE_FROM;
    547      1.1.1.2       mrg 	    GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
    548      1.1.1.2       mrg 				   &kinds[i], 0, 0);
    549      1.1.1.2       mrg 	    break;
    550      1.1.1.2       mrg 
    551      1.1.1.2       mrg 	  case GOMP_MAP_FORCE_PRESENT:
    552      1.1.1.2       mrg 	    if (!acc_is_present (hostaddrs[i], sizes[i]))
    553      1.1.1.2       mrg 	      gomp_fatal ("[%p,%ld] is not mapped", hostaddrs[i],
    554      1.1.1.2       mrg 			  (unsigned long) sizes[i]);
    555      1.1.1.2       mrg 	    break;
    556      1.1.1.2       mrg 
    557      1.1.1.2       mrg 	  default:
    558      1.1.1.2       mrg 	    assert (0);
    559      1.1.1.2       mrg 	    break;
    560      1.1.1.2       mrg 	}
    561      1.1.1.2       mrg     }
    562      1.1.1.2       mrg }
    563