Home | History | Annotate | Line # | Download | only in libgomp
oacc-init.c revision 1.1.1.2.4.2
      1          1.1       mrg /* OpenACC Runtime initialization routines
      2          1.1       mrg 
      3  1.1.1.2.4.1  christos    Copyright (C) 2013-2017 Free Software Foundation, Inc.
      4          1.1       mrg 
      5          1.1       mrg    Contributed by Mentor Embedded.
      6          1.1       mrg 
      7          1.1       mrg    This file is part of the GNU Offloading and Multi Processing Library
      8          1.1       mrg    (libgomp).
      9          1.1       mrg 
     10          1.1       mrg    Libgomp is free software; you can redistribute it and/or modify it
     11          1.1       mrg    under the terms of the GNU General Public License as published by
     12          1.1       mrg    the Free Software Foundation; either version 3, or (at your option)
     13          1.1       mrg    any later version.
     14          1.1       mrg 
     15          1.1       mrg    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
     16          1.1       mrg    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     17          1.1       mrg    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     18          1.1       mrg    more details.
     19          1.1       mrg 
     20          1.1       mrg    Under Section 7 of GPL version 3, you are granted additional
     21          1.1       mrg    permissions described in the GCC Runtime Library Exception, version
     22          1.1       mrg    3.1, as published by the Free Software Foundation.
     23          1.1       mrg 
     24          1.1       mrg    You should have received a copy of the GNU General Public License and
     25          1.1       mrg    a copy of the GCC Runtime Library Exception along with this program;
     26          1.1       mrg    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     27          1.1       mrg    <http://www.gnu.org/licenses/>.  */
     28          1.1       mrg 
     29          1.1       mrg #include "libgomp.h"
     30          1.1       mrg #include "oacc-int.h"
     31          1.1       mrg #include "openacc.h"
     32          1.1       mrg #include <assert.h>
     33          1.1       mrg #include <stdlib.h>
     34          1.1       mrg #include <strings.h>
     35          1.1       mrg #include <stdbool.h>
     36          1.1       mrg #include <string.h>
     37          1.1       mrg 
     38      1.1.1.2       mrg /* This lock is used to protect access to cached_base_dev, dispatchers and
     39      1.1.1.2       mrg    the (abstract) initialisation state of attached offloading devices.  */
     40      1.1.1.2       mrg 
     41          1.1       mrg static gomp_mutex_t acc_device_lock;
     42          1.1       mrg 
     43          1.1       mrg /* A cached version of the dispatcher for the global "current" accelerator type,
     44          1.1       mrg    e.g. used as the default when creating new host threads.  This is the
     45          1.1       mrg    device-type equivalent of goacc_device_num (which specifies which device to
     46          1.1       mrg    use out of potentially several of the same type).  If there are several
     47          1.1       mrg    devices of a given type, this points at the first one.  */
     48          1.1       mrg 
     49          1.1       mrg static struct gomp_device_descr *cached_base_dev = NULL;
     50          1.1       mrg 
     51          1.1       mrg #if defined HAVE_TLS || defined USE_EMUTLS
     52          1.1       mrg __thread struct goacc_thread *goacc_tls_data;
     53          1.1       mrg #else
     54          1.1       mrg pthread_key_t goacc_tls_key;
     55          1.1       mrg #endif
     56          1.1       mrg static pthread_key_t goacc_cleanup_key;
     57          1.1       mrg 
     58          1.1       mrg static struct goacc_thread *goacc_threads;
     59          1.1       mrg static gomp_mutex_t goacc_thread_lock;
     60          1.1       mrg 
     61          1.1       mrg /* An array of dispatchers for device types, indexed by the type.  This array
     62          1.1       mrg    only references "base" devices, and other instances of the same type are
     63          1.1       mrg    found by simply indexing from each such device (which are stored linearly,
     64          1.1       mrg    grouped by device in target.c:devices).  */
     65          1.1       mrg static struct gomp_device_descr *dispatchers[_ACC_device_hwm] = { 0 };
     66          1.1       mrg 
     67          1.1       mrg attribute_hidden void
     68          1.1       mrg goacc_register (struct gomp_device_descr *disp)
     69          1.1       mrg {
     70          1.1       mrg   /* Only register the 0th device here.  */
     71          1.1       mrg   if (disp->target_id != 0)
     72          1.1       mrg     return;
     73          1.1       mrg 
     74          1.1       mrg   gomp_mutex_lock (&acc_device_lock);
     75          1.1       mrg 
     76          1.1       mrg   assert (acc_device_type (disp->type) != acc_device_none
     77          1.1       mrg 	  && acc_device_type (disp->type) != acc_device_default
     78          1.1       mrg 	  && acc_device_type (disp->type) != acc_device_not_host);
     79          1.1       mrg   assert (!dispatchers[disp->type]);
     80          1.1       mrg   dispatchers[disp->type] = disp;
     81          1.1       mrg 
     82          1.1       mrg   gomp_mutex_unlock (&acc_device_lock);
     83          1.1       mrg }
     84          1.1       mrg 
     85          1.1       mrg /* OpenACC names some things a little differently.  */
     86          1.1       mrg 
     87          1.1       mrg static const char *
     88          1.1       mrg get_openacc_name (const char *name)
     89          1.1       mrg {
     90          1.1       mrg   if (strcmp (name, "nvptx") == 0)
     91          1.1       mrg     return "nvidia";
     92          1.1       mrg   else
     93          1.1       mrg     return name;
     94          1.1       mrg }
     95          1.1       mrg 
     96          1.1       mrg static const char *
     97          1.1       mrg name_of_acc_device_t (enum acc_device_t type)
     98          1.1       mrg {
     99          1.1       mrg   switch (type)
    100          1.1       mrg     {
    101          1.1       mrg     case acc_device_none: return "none";
    102          1.1       mrg     case acc_device_default: return "default";
    103          1.1       mrg     case acc_device_host: return "host";
    104          1.1       mrg     case acc_device_not_host: return "not_host";
    105          1.1       mrg     case acc_device_nvidia: return "nvidia";
    106          1.1       mrg     default: gomp_fatal ("unknown device type %u", (unsigned) type);
    107          1.1       mrg     }
    108          1.1       mrg }
    109          1.1       mrg 
    110      1.1.1.2       mrg /* ACC_DEVICE_LOCK must be held before calling this function.  If FAIL_IS_ERROR
    111      1.1.1.2       mrg    is true, this function raises an error if there are no devices of type D,
    112      1.1.1.2       mrg    otherwise it returns NULL in that case.  */
    113      1.1.1.2       mrg 
    114          1.1       mrg static struct gomp_device_descr *
    115      1.1.1.2       mrg resolve_device (acc_device_t d, bool fail_is_error)
    116          1.1       mrg {
    117          1.1       mrg   acc_device_t d_arg = d;
    118          1.1       mrg 
    119          1.1       mrg   switch (d)
    120          1.1       mrg     {
    121          1.1       mrg     case acc_device_default:
    122          1.1       mrg       {
    123          1.1       mrg 	if (goacc_device_type)
    124          1.1       mrg 	  {
    125          1.1       mrg 	    /* Lookup the named device.  */
    126          1.1       mrg 	    while (++d != _ACC_device_hwm)
    127          1.1       mrg 	      if (dispatchers[d]
    128          1.1       mrg 		  && !strcasecmp (goacc_device_type,
    129          1.1       mrg 				  get_openacc_name (dispatchers[d]->name))
    130          1.1       mrg 		  && dispatchers[d]->get_num_devices_func () > 0)
    131          1.1       mrg 		goto found;
    132          1.1       mrg 
    133      1.1.1.2       mrg 	    if (fail_is_error)
    134      1.1.1.2       mrg 	      {
    135      1.1.1.2       mrg 		gomp_mutex_unlock (&acc_device_lock);
    136      1.1.1.2       mrg 		gomp_fatal ("device type %s not supported", goacc_device_type);
    137      1.1.1.2       mrg 	      }
    138      1.1.1.2       mrg 	    else
    139      1.1.1.2       mrg 	      return NULL;
    140          1.1       mrg 	  }
    141          1.1       mrg 
    142          1.1       mrg 	/* No default device specified, so start scanning for any non-host
    143          1.1       mrg 	   device that is available.  */
    144          1.1       mrg 	d = acc_device_not_host;
    145          1.1       mrg       }
    146          1.1       mrg       /* FALLTHROUGH */
    147          1.1       mrg 
    148          1.1       mrg     case acc_device_not_host:
    149          1.1       mrg       /* Find the first available device after acc_device_not_host.  */
    150          1.1       mrg       while (++d != _ACC_device_hwm)
    151          1.1       mrg 	if (dispatchers[d] && dispatchers[d]->get_num_devices_func () > 0)
    152          1.1       mrg 	  goto found;
    153          1.1       mrg       if (d_arg == acc_device_default)
    154          1.1       mrg 	{
    155          1.1       mrg 	  d = acc_device_host;
    156          1.1       mrg 	  goto found;
    157          1.1       mrg 	}
    158      1.1.1.2       mrg       if (fail_is_error)
    159      1.1.1.2       mrg         {
    160      1.1.1.2       mrg 	  gomp_mutex_unlock (&acc_device_lock);
    161      1.1.1.2       mrg 	  gomp_fatal ("no device found");
    162      1.1.1.2       mrg 	}
    163      1.1.1.2       mrg       else
    164      1.1.1.2       mrg         return NULL;
    165          1.1       mrg       break;
    166          1.1       mrg 
    167          1.1       mrg     case acc_device_host:
    168          1.1       mrg       break;
    169          1.1       mrg 
    170          1.1       mrg     default:
    171          1.1       mrg       if (d > _ACC_device_hwm)
    172      1.1.1.2       mrg 	{
    173      1.1.1.2       mrg 	  if (fail_is_error)
    174      1.1.1.2       mrg 	    goto unsupported_device;
    175      1.1.1.2       mrg 	  else
    176      1.1.1.2       mrg 	    return NULL;
    177      1.1.1.2       mrg 	}
    178          1.1       mrg       break;
    179          1.1       mrg     }
    180          1.1       mrg  found:
    181          1.1       mrg 
    182          1.1       mrg   assert (d != acc_device_none
    183          1.1       mrg 	  && d != acc_device_default
    184          1.1       mrg 	  && d != acc_device_not_host);
    185          1.1       mrg 
    186      1.1.1.2       mrg   if (dispatchers[d] == NULL && fail_is_error)
    187      1.1.1.2       mrg     {
    188      1.1.1.2       mrg     unsupported_device:
    189      1.1.1.2       mrg       gomp_mutex_unlock (&acc_device_lock);
    190      1.1.1.2       mrg       gomp_fatal ("device type %s not supported", name_of_acc_device_t (d));
    191      1.1.1.2       mrg     }
    192      1.1.1.2       mrg 
    193          1.1       mrg   return dispatchers[d];
    194          1.1       mrg }
    195          1.1       mrg 
    196      1.1.1.2       mrg /* Emit a suitable error if no device of a particular type is available, or
    197      1.1.1.2       mrg    the given device number is out-of-range.  */
    198      1.1.1.2       mrg static void
    199      1.1.1.2       mrg acc_dev_num_out_of_range (acc_device_t d, int ord, int ndevs)
    200      1.1.1.2       mrg {
    201      1.1.1.2       mrg   if (ndevs == 0)
    202      1.1.1.2       mrg     gomp_fatal ("no devices of type %s available", name_of_acc_device_t (d));
    203      1.1.1.2       mrg   else
    204      1.1.1.2       mrg     gomp_fatal ("device %u out of range", ord);
    205      1.1.1.2       mrg }
    206      1.1.1.2       mrg 
    207          1.1       mrg /* This is called when plugins have been initialized, and serves to call
    208          1.1       mrg    (indirectly) the target's device_init hook.  Calling multiple times without
    209      1.1.1.2       mrg    an intervening acc_shutdown_1 call is an error.  ACC_DEVICE_LOCK must be
    210      1.1.1.2       mrg    held before calling this function.  */
    211          1.1       mrg 
    212          1.1       mrg static struct gomp_device_descr *
    213          1.1       mrg acc_init_1 (acc_device_t d)
    214          1.1       mrg {
    215          1.1       mrg   struct gomp_device_descr *base_dev, *acc_dev;
    216          1.1       mrg   int ndevs;
    217          1.1       mrg 
    218      1.1.1.2       mrg   base_dev = resolve_device (d, true);
    219          1.1       mrg 
    220          1.1       mrg   ndevs = base_dev->get_num_devices_func ();
    221          1.1       mrg 
    222      1.1.1.2       mrg   if (ndevs <= 0 || goacc_device_num >= ndevs)
    223      1.1.1.2       mrg     acc_dev_num_out_of_range (d, goacc_device_num, ndevs);
    224          1.1       mrg 
    225          1.1       mrg   acc_dev = &base_dev[goacc_device_num];
    226          1.1       mrg 
    227      1.1.1.2       mrg   gomp_mutex_lock (&acc_dev->lock);
    228      1.1.1.2       mrg   if (acc_dev->state == GOMP_DEVICE_INITIALIZED)
    229      1.1.1.2       mrg     {
    230      1.1.1.2       mrg       gomp_mutex_unlock (&acc_dev->lock);
    231      1.1.1.2       mrg       gomp_fatal ("device already active");
    232      1.1.1.2       mrg     }
    233          1.1       mrg 
    234          1.1       mrg   gomp_init_device (acc_dev);
    235      1.1.1.2       mrg   gomp_mutex_unlock (&acc_dev->lock);
    236          1.1       mrg 
    237          1.1       mrg   return base_dev;
    238          1.1       mrg }
    239          1.1       mrg 
    240      1.1.1.2       mrg /* ACC_DEVICE_LOCK must be held before calling this function.  */
    241      1.1.1.2       mrg 
    242          1.1       mrg static void
    243          1.1       mrg acc_shutdown_1 (acc_device_t d)
    244          1.1       mrg {
    245          1.1       mrg   struct gomp_device_descr *base_dev;
    246          1.1       mrg   struct goacc_thread *walk;
    247          1.1       mrg   int ndevs, i;
    248          1.1       mrg   bool devices_active = false;
    249          1.1       mrg 
    250          1.1       mrg   /* Get the base device for this device type.  */
    251      1.1.1.2       mrg   base_dev = resolve_device (d, true);
    252      1.1.1.2       mrg 
    253      1.1.1.2       mrg   ndevs = base_dev->get_num_devices_func ();
    254          1.1       mrg 
    255      1.1.1.2       mrg   /* Unload all the devices of this type that have been opened.  */
    256      1.1.1.2       mrg   for (i = 0; i < ndevs; i++)
    257      1.1.1.2       mrg     {
    258      1.1.1.2       mrg       struct gomp_device_descr *acc_dev = &base_dev[i];
    259          1.1       mrg 
    260      1.1.1.2       mrg       gomp_mutex_lock (&acc_dev->lock);
    261      1.1.1.2       mrg       gomp_unload_device (acc_dev);
    262      1.1.1.2       mrg       gomp_mutex_unlock (&acc_dev->lock);
    263      1.1.1.2       mrg     }
    264      1.1.1.2       mrg 
    265          1.1       mrg   gomp_mutex_lock (&goacc_thread_lock);
    266          1.1       mrg 
    267          1.1       mrg   /* Free target-specific TLS data and close all devices.  */
    268          1.1       mrg   for (walk = goacc_threads; walk != NULL; walk = walk->next)
    269          1.1       mrg     {
    270          1.1       mrg       if (walk->target_tls)
    271          1.1       mrg 	base_dev->openacc.destroy_thread_data_func (walk->target_tls);
    272          1.1       mrg 
    273          1.1       mrg       walk->target_tls = NULL;
    274          1.1       mrg 
    275          1.1       mrg       /* This would mean the user is shutting down OpenACC in the middle of an
    276          1.1       mrg          "acc data" pragma.  Likely not intentional.  */
    277          1.1       mrg       if (walk->mapped_data)
    278      1.1.1.2       mrg 	{
    279      1.1.1.2       mrg 	  gomp_mutex_unlock (&goacc_thread_lock);
    280      1.1.1.2       mrg 	  gomp_fatal ("shutdown in 'acc data' region");
    281      1.1.1.2       mrg 	}
    282          1.1       mrg 
    283          1.1       mrg       /* Similarly, if this happens then user code has done something weird.  */
    284          1.1       mrg       if (walk->saved_bound_dev)
    285      1.1.1.2       mrg 	{
    286      1.1.1.2       mrg 	  gomp_mutex_unlock (&goacc_thread_lock);
    287      1.1.1.2       mrg 	  gomp_fatal ("shutdown during host fallback");
    288      1.1.1.2       mrg 	}
    289          1.1       mrg 
    290          1.1       mrg       if (walk->dev)
    291          1.1       mrg 	{
    292          1.1       mrg 	  gomp_mutex_lock (&walk->dev->lock);
    293          1.1       mrg 	  gomp_free_memmap (&walk->dev->mem_map);
    294          1.1       mrg 	  gomp_mutex_unlock (&walk->dev->lock);
    295          1.1       mrg 
    296          1.1       mrg 	  walk->dev = NULL;
    297          1.1       mrg 	  walk->base_dev = NULL;
    298          1.1       mrg 	}
    299          1.1       mrg     }
    300          1.1       mrg 
    301          1.1       mrg   gomp_mutex_unlock (&goacc_thread_lock);
    302          1.1       mrg 
    303          1.1       mrg   /* Close all the devices of this type that have been opened.  */
    304  1.1.1.2.4.1  christos   bool ret = true;
    305          1.1       mrg   for (i = 0; i < ndevs; i++)
    306          1.1       mrg     {
    307          1.1       mrg       struct gomp_device_descr *acc_dev = &base_dev[i];
    308      1.1.1.2       mrg       gomp_mutex_lock (&acc_dev->lock);
    309      1.1.1.2       mrg       if (acc_dev->state == GOMP_DEVICE_INITIALIZED)
    310          1.1       mrg         {
    311          1.1       mrg 	  devices_active = true;
    312  1.1.1.2.4.1  christos 	  ret &= acc_dev->fini_device_func (acc_dev->target_id);
    313      1.1.1.2       mrg 	  acc_dev->state = GOMP_DEVICE_UNINITIALIZED;
    314          1.1       mrg 	}
    315      1.1.1.2       mrg       gomp_mutex_unlock (&acc_dev->lock);
    316          1.1       mrg     }
    317          1.1       mrg 
    318  1.1.1.2.4.1  christos   if (!ret)
    319  1.1.1.2.4.1  christos     gomp_fatal ("device finalization failed");
    320  1.1.1.2.4.1  christos 
    321          1.1       mrg   if (!devices_active)
    322          1.1       mrg     gomp_fatal ("no device initialized");
    323          1.1       mrg }
    324          1.1       mrg 
    325          1.1       mrg static struct goacc_thread *
    326          1.1       mrg goacc_new_thread (void)
    327          1.1       mrg {
    328  1.1.1.2.4.1  christos   struct goacc_thread *thr = gomp_malloc (sizeof (struct goacc_thread));
    329          1.1       mrg 
    330          1.1       mrg #if defined HAVE_TLS || defined USE_EMUTLS
    331          1.1       mrg   goacc_tls_data = thr;
    332          1.1       mrg #else
    333          1.1       mrg   pthread_setspecific (goacc_tls_key, thr);
    334          1.1       mrg #endif
    335          1.1       mrg 
    336          1.1       mrg   pthread_setspecific (goacc_cleanup_key, thr);
    337          1.1       mrg 
    338          1.1       mrg   gomp_mutex_lock (&goacc_thread_lock);
    339          1.1       mrg   thr->next = goacc_threads;
    340          1.1       mrg   goacc_threads = thr;
    341          1.1       mrg   gomp_mutex_unlock (&goacc_thread_lock);
    342          1.1       mrg 
    343          1.1       mrg   return thr;
    344          1.1       mrg }
    345          1.1       mrg 
    346          1.1       mrg static void
    347          1.1       mrg goacc_destroy_thread (void *data)
    348          1.1       mrg {
    349          1.1       mrg   struct goacc_thread *thr = data, *walk, *prev;
    350          1.1       mrg 
    351          1.1       mrg   gomp_mutex_lock (&goacc_thread_lock);
    352          1.1       mrg 
    353          1.1       mrg   if (thr)
    354          1.1       mrg     {
    355          1.1       mrg       struct gomp_device_descr *acc_dev = thr->dev;
    356          1.1       mrg 
    357          1.1       mrg       if (acc_dev && thr->target_tls)
    358          1.1       mrg 	{
    359          1.1       mrg 	  acc_dev->openacc.destroy_thread_data_func (thr->target_tls);
    360          1.1       mrg 	  thr->target_tls = NULL;
    361          1.1       mrg 	}
    362          1.1       mrg 
    363          1.1       mrg       assert (!thr->mapped_data);
    364          1.1       mrg 
    365          1.1       mrg       /* Remove from thread list.  */
    366          1.1       mrg       for (prev = NULL, walk = goacc_threads; walk;
    367          1.1       mrg 	   prev = walk, walk = walk->next)
    368          1.1       mrg 	if (walk == thr)
    369          1.1       mrg 	  {
    370          1.1       mrg 	    if (prev == NULL)
    371          1.1       mrg 	      goacc_threads = walk->next;
    372          1.1       mrg 	    else
    373          1.1       mrg 	      prev->next = walk->next;
    374          1.1       mrg 
    375          1.1       mrg 	    free (thr);
    376          1.1       mrg 
    377          1.1       mrg 	    break;
    378          1.1       mrg 	  }
    379          1.1       mrg 
    380          1.1       mrg       assert (walk);
    381          1.1       mrg     }
    382          1.1       mrg 
    383          1.1       mrg   gomp_mutex_unlock (&goacc_thread_lock);
    384          1.1       mrg }
    385          1.1       mrg 
    386          1.1       mrg /* Use the ORD'th device instance for the current host thread (or -1 for the
    387          1.1       mrg    current global default).  The device (and the runtime) must be initialised
    388          1.1       mrg    before calling this function.  */
    389          1.1       mrg 
    390          1.1       mrg void
    391          1.1       mrg goacc_attach_host_thread_to_device (int ord)
    392          1.1       mrg {
    393          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    394          1.1       mrg   struct gomp_device_descr *acc_dev = NULL, *base_dev = NULL;
    395          1.1       mrg   int num_devices;
    396          1.1       mrg 
    397          1.1       mrg   if (thr && thr->dev && (thr->dev->target_id == ord || ord < 0))
    398          1.1       mrg     return;
    399          1.1       mrg 
    400          1.1       mrg   if (ord < 0)
    401          1.1       mrg     ord = goacc_device_num;
    402          1.1       mrg 
    403          1.1       mrg   /* Decide which type of device to use.  If the current thread has a device
    404          1.1       mrg      type already (e.g. set by acc_set_device_type), use that, else use the
    405          1.1       mrg      global default.  */
    406          1.1       mrg   if (thr && thr->base_dev)
    407          1.1       mrg     base_dev = thr->base_dev;
    408          1.1       mrg   else
    409          1.1       mrg     {
    410          1.1       mrg       assert (cached_base_dev);
    411          1.1       mrg       base_dev = cached_base_dev;
    412          1.1       mrg     }
    413          1.1       mrg 
    414          1.1       mrg   num_devices = base_dev->get_num_devices_func ();
    415          1.1       mrg   if (num_devices <= 0 || ord >= num_devices)
    416      1.1.1.2       mrg     acc_dev_num_out_of_range (acc_device_type (base_dev->type), ord,
    417      1.1.1.2       mrg 			      num_devices);
    418          1.1       mrg 
    419          1.1       mrg   if (!thr)
    420          1.1       mrg     thr = goacc_new_thread ();
    421          1.1       mrg 
    422          1.1       mrg   thr->base_dev = base_dev;
    423          1.1       mrg   thr->dev = acc_dev = &base_dev[ord];
    424          1.1       mrg   thr->saved_bound_dev = NULL;
    425          1.1       mrg   thr->mapped_data = NULL;
    426          1.1       mrg 
    427          1.1       mrg   thr->target_tls
    428          1.1       mrg     = acc_dev->openacc.create_thread_data_func (ord);
    429          1.1       mrg 
    430          1.1       mrg   acc_dev->openacc.async_set_async_func (acc_async_sync);
    431          1.1       mrg }
    432          1.1       mrg 
    433          1.1       mrg /* OpenACC 2.0a (3.2.12, 3.2.13) doesn't specify whether the serialization of
    434          1.1       mrg    init/shutdown is per-process or per-thread.  We choose per-process.  */
    435          1.1       mrg 
    436          1.1       mrg void
    437          1.1       mrg acc_init (acc_device_t d)
    438          1.1       mrg {
    439  1.1.1.2.4.1  christos   gomp_init_targets_once ();
    440          1.1       mrg 
    441          1.1       mrg   gomp_mutex_lock (&acc_device_lock);
    442          1.1       mrg 
    443          1.1       mrg   cached_base_dev = acc_init_1 (d);
    444          1.1       mrg 
    445          1.1       mrg   gomp_mutex_unlock (&acc_device_lock);
    446          1.1       mrg 
    447          1.1       mrg   goacc_attach_host_thread_to_device (-1);
    448          1.1       mrg }
    449          1.1       mrg 
    450          1.1       mrg ialias (acc_init)
    451          1.1       mrg 
    452          1.1       mrg void
    453          1.1       mrg acc_shutdown (acc_device_t d)
    454          1.1       mrg {
    455      1.1.1.2       mrg   gomp_init_targets_once ();
    456      1.1.1.2       mrg 
    457          1.1       mrg   gomp_mutex_lock (&acc_device_lock);
    458          1.1       mrg 
    459          1.1       mrg   acc_shutdown_1 (d);
    460          1.1       mrg 
    461          1.1       mrg   gomp_mutex_unlock (&acc_device_lock);
    462          1.1       mrg }
    463          1.1       mrg 
    464          1.1       mrg ialias (acc_shutdown)
    465          1.1       mrg 
    466          1.1       mrg int
    467          1.1       mrg acc_get_num_devices (acc_device_t d)
    468          1.1       mrg {
    469          1.1       mrg   int n = 0;
    470          1.1       mrg   struct gomp_device_descr *acc_dev;
    471          1.1       mrg 
    472          1.1       mrg   if (d == acc_device_none)
    473          1.1       mrg     return 0;
    474          1.1       mrg 
    475          1.1       mrg   gomp_init_targets_once ();
    476          1.1       mrg 
    477      1.1.1.2       mrg   gomp_mutex_lock (&acc_device_lock);
    478      1.1.1.2       mrg   acc_dev = resolve_device (d, false);
    479      1.1.1.2       mrg   gomp_mutex_unlock (&acc_device_lock);
    480      1.1.1.2       mrg 
    481          1.1       mrg   if (!acc_dev)
    482          1.1       mrg     return 0;
    483          1.1       mrg 
    484          1.1       mrg   n = acc_dev->get_num_devices_func ();
    485          1.1       mrg   if (n < 0)
    486          1.1       mrg     n = 0;
    487          1.1       mrg 
    488          1.1       mrg   return n;
    489          1.1       mrg }
    490          1.1       mrg 
    491          1.1       mrg ialias (acc_get_num_devices)
    492          1.1       mrg 
    493          1.1       mrg /* Set the device type for the current thread only (using the current global
    494          1.1       mrg    default device number), initialising that device if necessary.  Also set the
    495          1.1       mrg    default device type for new threads to D.  */
    496          1.1       mrg 
    497          1.1       mrg void
    498          1.1       mrg acc_set_device_type (acc_device_t d)
    499          1.1       mrg {
    500          1.1       mrg   struct gomp_device_descr *base_dev, *acc_dev;
    501          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    502          1.1       mrg 
    503  1.1.1.2.4.1  christos   gomp_init_targets_once ();
    504          1.1       mrg 
    505  1.1.1.2.4.1  christos   gomp_mutex_lock (&acc_device_lock);
    506          1.1       mrg 
    507      1.1.1.2       mrg   cached_base_dev = base_dev = resolve_device (d, true);
    508          1.1       mrg   acc_dev = &base_dev[goacc_device_num];
    509          1.1       mrg 
    510      1.1.1.2       mrg   gomp_mutex_lock (&acc_dev->lock);
    511      1.1.1.2       mrg   if (acc_dev->state == GOMP_DEVICE_UNINITIALIZED)
    512          1.1       mrg     gomp_init_device (acc_dev);
    513      1.1.1.2       mrg   gomp_mutex_unlock (&acc_dev->lock);
    514          1.1       mrg 
    515          1.1       mrg   gomp_mutex_unlock (&acc_device_lock);
    516          1.1       mrg 
    517          1.1       mrg   /* We're changing device type: invalidate the current thread's dev and
    518          1.1       mrg      base_dev pointers.  */
    519          1.1       mrg   if (thr && thr->base_dev != base_dev)
    520          1.1       mrg     {
    521          1.1       mrg       thr->base_dev = thr->dev = NULL;
    522          1.1       mrg       if (thr->mapped_data)
    523          1.1       mrg         gomp_fatal ("acc_set_device_type in 'acc data' region");
    524          1.1       mrg     }
    525          1.1       mrg 
    526          1.1       mrg   goacc_attach_host_thread_to_device (-1);
    527          1.1       mrg }
    528          1.1       mrg 
    529          1.1       mrg ialias (acc_set_device_type)
    530          1.1       mrg 
    531          1.1       mrg acc_device_t
    532          1.1       mrg acc_get_device_type (void)
    533          1.1       mrg {
    534          1.1       mrg   acc_device_t res = acc_device_none;
    535          1.1       mrg   struct gomp_device_descr *dev;
    536          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    537          1.1       mrg 
    538          1.1       mrg   if (thr && thr->base_dev)
    539          1.1       mrg     res = acc_device_type (thr->base_dev->type);
    540          1.1       mrg   else
    541          1.1       mrg     {
    542          1.1       mrg       gomp_init_targets_once ();
    543          1.1       mrg 
    544      1.1.1.2       mrg       gomp_mutex_lock (&acc_device_lock);
    545      1.1.1.2       mrg       dev = resolve_device (acc_device_default, true);
    546      1.1.1.2       mrg       gomp_mutex_unlock (&acc_device_lock);
    547          1.1       mrg       res = acc_device_type (dev->type);
    548          1.1       mrg     }
    549          1.1       mrg 
    550          1.1       mrg   assert (res != acc_device_default
    551          1.1       mrg 	  && res != acc_device_not_host);
    552          1.1       mrg 
    553          1.1       mrg   return res;
    554          1.1       mrg }
    555          1.1       mrg 
    556          1.1       mrg ialias (acc_get_device_type)
    557          1.1       mrg 
    558          1.1       mrg int
    559          1.1       mrg acc_get_device_num (acc_device_t d)
    560          1.1       mrg {
    561          1.1       mrg   const struct gomp_device_descr *dev;
    562          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    563          1.1       mrg 
    564          1.1       mrg   if (d >= _ACC_device_hwm)
    565      1.1.1.2       mrg     gomp_fatal ("unknown device type %u", (unsigned) d);
    566          1.1       mrg 
    567  1.1.1.2.4.1  christos   gomp_init_targets_once ();
    568          1.1       mrg 
    569      1.1.1.2       mrg   gomp_mutex_lock (&acc_device_lock);
    570      1.1.1.2       mrg   dev = resolve_device (d, true);
    571      1.1.1.2       mrg   gomp_mutex_unlock (&acc_device_lock);
    572          1.1       mrg 
    573          1.1       mrg   if (thr && thr->base_dev == dev && thr->dev)
    574          1.1       mrg     return thr->dev->target_id;
    575          1.1       mrg 
    576          1.1       mrg   return goacc_device_num;
    577          1.1       mrg }
    578          1.1       mrg 
    579          1.1       mrg ialias (acc_get_device_num)
    580          1.1       mrg 
    581          1.1       mrg void
    582          1.1       mrg acc_set_device_num (int ord, acc_device_t d)
    583          1.1       mrg {
    584          1.1       mrg   struct gomp_device_descr *base_dev, *acc_dev;
    585          1.1       mrg   int num_devices;
    586          1.1       mrg 
    587  1.1.1.2.4.1  christos   gomp_init_targets_once ();
    588          1.1       mrg 
    589          1.1       mrg   if (ord < 0)
    590          1.1       mrg     ord = goacc_device_num;
    591          1.1       mrg 
    592          1.1       mrg   if ((int) d == 0)
    593          1.1       mrg     /* Set whatever device is being used by the current host thread to use
    594          1.1       mrg        device instance ORD.  It's unclear if this is supposed to affect other
    595          1.1       mrg        host threads too (OpenACC 2.0 (3.2.4) acc_set_device_num).  */
    596          1.1       mrg     goacc_attach_host_thread_to_device (ord);
    597          1.1       mrg   else
    598          1.1       mrg     {
    599          1.1       mrg       gomp_mutex_lock (&acc_device_lock);
    600          1.1       mrg 
    601      1.1.1.2       mrg       cached_base_dev = base_dev = resolve_device (d, true);
    602          1.1       mrg 
    603          1.1       mrg       num_devices = base_dev->get_num_devices_func ();
    604          1.1       mrg 
    605      1.1.1.2       mrg       if (num_devices <= 0 || ord >= num_devices)
    606      1.1.1.2       mrg         acc_dev_num_out_of_range (d, ord, num_devices);
    607          1.1       mrg 
    608          1.1       mrg       acc_dev = &base_dev[ord];
    609          1.1       mrg 
    610      1.1.1.2       mrg       gomp_mutex_lock (&acc_dev->lock);
    611      1.1.1.2       mrg       if (acc_dev->state == GOMP_DEVICE_UNINITIALIZED)
    612          1.1       mrg         gomp_init_device (acc_dev);
    613      1.1.1.2       mrg       gomp_mutex_unlock (&acc_dev->lock);
    614          1.1       mrg 
    615          1.1       mrg       gomp_mutex_unlock (&acc_device_lock);
    616          1.1       mrg 
    617          1.1       mrg       goacc_attach_host_thread_to_device (ord);
    618          1.1       mrg     }
    619          1.1       mrg 
    620          1.1       mrg   goacc_device_num = ord;
    621          1.1       mrg }
    622          1.1       mrg 
    623          1.1       mrg ialias (acc_set_device_num)
    624          1.1       mrg 
    625      1.1.1.2       mrg /* For -O and higher, the compiler always attempts to expand acc_on_device, but
    626      1.1.1.2       mrg    if the user disables the builtin, or calls it via a pointer, we'll need this
    627      1.1.1.2       mrg    version.
    628          1.1       mrg 
    629      1.1.1.2       mrg    Compile this with optimization, so that the compiler expands
    630      1.1.1.2       mrg    this, rather than generating infinitely recursive code.  */
    631          1.1       mrg 
    632      1.1.1.2       mrg int __attribute__ ((__optimize__ ("O2")))
    633      1.1.1.2       mrg acc_on_device (acc_device_t dev)
    634      1.1.1.2       mrg {
    635      1.1.1.2       mrg   return __builtin_acc_on_device (dev);
    636          1.1       mrg }
    637          1.1       mrg 
    638          1.1       mrg ialias (acc_on_device)
    639          1.1       mrg 
    640          1.1       mrg attribute_hidden void
    641          1.1       mrg goacc_runtime_initialize (void)
    642          1.1       mrg {
    643          1.1       mrg   gomp_mutex_init (&acc_device_lock);
    644          1.1       mrg 
    645          1.1       mrg #if !(defined HAVE_TLS || defined USE_EMUTLS)
    646          1.1       mrg   pthread_key_create (&goacc_tls_key, NULL);
    647          1.1       mrg #endif
    648          1.1       mrg 
    649          1.1       mrg   pthread_key_create (&goacc_cleanup_key, goacc_destroy_thread);
    650          1.1       mrg 
    651          1.1       mrg   cached_base_dev = NULL;
    652          1.1       mrg 
    653          1.1       mrg   goacc_threads = NULL;
    654          1.1       mrg   gomp_mutex_init (&goacc_thread_lock);
    655          1.1       mrg 
    656          1.1       mrg   /* Initialize and register the 'host' device type.  */
    657          1.1       mrg   goacc_host_init ();
    658          1.1       mrg }
    659          1.1       mrg 
    660  1.1.1.2.4.2    martin static void __attribute__((destructor))
    661  1.1.1.2.4.2    martin goacc_runtime_deinitialize (void)
    662  1.1.1.2.4.2    martin {
    663  1.1.1.2.4.2    martin #if !(defined HAVE_TLS || defined USE_EMUTLS)
    664  1.1.1.2.4.2    martin   pthread_key_delete (goacc_tls_key);
    665  1.1.1.2.4.2    martin #endif
    666  1.1.1.2.4.2    martin   pthread_key_delete (goacc_cleanup_key);
    667  1.1.1.2.4.2    martin }
    668  1.1.1.2.4.2    martin 
    669          1.1       mrg /* Compiler helper functions */
    670          1.1       mrg 
    671          1.1       mrg attribute_hidden void
    672          1.1       mrg goacc_save_and_set_bind (acc_device_t d)
    673          1.1       mrg {
    674          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    675          1.1       mrg 
    676          1.1       mrg   assert (!thr->saved_bound_dev);
    677          1.1       mrg 
    678          1.1       mrg   thr->saved_bound_dev = thr->dev;
    679          1.1       mrg   thr->dev = dispatchers[d];
    680          1.1       mrg }
    681          1.1       mrg 
    682          1.1       mrg attribute_hidden void
    683          1.1       mrg goacc_restore_bind (void)
    684          1.1       mrg {
    685          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    686          1.1       mrg 
    687          1.1       mrg   thr->dev = thr->saved_bound_dev;
    688          1.1       mrg   thr->saved_bound_dev = NULL;
    689          1.1       mrg }
    690          1.1       mrg 
    691          1.1       mrg /* This is called from any OpenACC support function that may need to implicitly
    692          1.1       mrg    initialize the libgomp runtime, either globally or from a new host thread.
    693          1.1       mrg    On exit "goacc_thread" will return a valid & populated thread block.  */
    694          1.1       mrg 
    695          1.1       mrg attribute_hidden void
    696          1.1       mrg goacc_lazy_initialize (void)
    697          1.1       mrg {
    698          1.1       mrg   struct goacc_thread *thr = goacc_thread ();
    699          1.1       mrg 
    700          1.1       mrg   if (thr && thr->dev)
    701          1.1       mrg     return;
    702          1.1       mrg 
    703          1.1       mrg   if (!cached_base_dev)
    704          1.1       mrg     acc_init (acc_device_default);
    705          1.1       mrg   else
    706          1.1       mrg     goacc_attach_host_thread_to_device (-1);
    707          1.1       mrg }
    708