static struct gomp_device_descr * acc_init_1 (acc_device_t d) { struct gomp_device_descr *base_dev, *acc_dev; int ndevs; base_dev = resolve_device (d); ndevs = base_dev->get_num_devices_func (); if (!base_dev || ndevs <= 0 || goacc_device_num >= ndevs) gomp_fatal ("device %s not supported", name_of_acc_device_t (d)); acc_dev = &base_dev[goacc_device_num]; gomp_mutex_lock (&acc_dev->lock); if (acc_dev->is_initialized) { gomp_mutex_unlock (&acc_dev->lock); gomp_fatal ("device already active"); } gomp_init_device (acc_dev); gomp_mutex_unlock (&acc_dev->lock); return base_dev; }
/* Emit a suitable error if no device of a particular type is available, or the given device number is out-of-range. */ static void acc_dev_num_out_of_range (acc_device_t d, int ord, int ndevs) { if (ndevs == 0) gomp_fatal ("no devices of type %s available", name_of_acc_device_t (d)); else gomp_fatal ("device %u out of range", ord); }
int acc_get_device_num (acc_device_t d) { const struct gomp_device_descr *dev; struct goacc_thread *thr = goacc_thread (); if (d >= _ACC_device_hwm) gomp_fatal ("device %u out of range", (unsigned)d); if (!cached_base_dev) gomp_init_targets_once (); gomp_mutex_lock (&acc_device_lock); dev = resolve_device (d); gomp_mutex_unlock (&acc_device_lock); if (!dev) gomp_fatal ("device %s not supported", name_of_acc_device_t (d)); if (thr && thr->base_dev == dev && thr->dev) return thr->dev->target_id; return goacc_device_num; }
static void acc_shutdown_1 (acc_device_t d) { struct gomp_device_descr *base_dev; struct goacc_thread *walk; int ndevs, i; bool devices_active = false; /* Get the base device for this device type. */ base_dev = resolve_device (d); if (!base_dev) gomp_fatal ("device %s not supported", name_of_acc_device_t (d)); gomp_mutex_lock (&goacc_thread_lock); /* Free target-specific TLS data and close all devices. */ for (walk = goacc_threads; walk != NULL; walk = walk->next) { if (walk->target_tls) base_dev->openacc.destroy_thread_data_func (walk->target_tls); walk->target_tls = NULL; /* This would mean the user is shutting down OpenACC in the middle of an "acc data" pragma. Likely not intentional. */ if (walk->mapped_data) { gomp_mutex_unlock (&goacc_thread_lock); gomp_fatal ("shutdown in 'acc data' region"); } /* Similarly, if this happens then user code has done something weird. */ if (walk->saved_bound_dev) { gomp_mutex_unlock (&goacc_thread_lock); gomp_fatal ("shutdown during host fallback"); } if (walk->dev) { gomp_mutex_lock (&walk->dev->lock); gomp_free_memmap (&walk->dev->mem_map); gomp_mutex_unlock (&walk->dev->lock); walk->dev = NULL; walk->base_dev = NULL; } } gomp_mutex_unlock (&goacc_thread_lock); ndevs = base_dev->get_num_devices_func (); /* Close all the devices of this type that have been opened. */ for (i = 0; i < ndevs; i++) { struct gomp_device_descr *acc_dev = &base_dev[i]; gomp_mutex_lock (&acc_dev->lock); if (acc_dev->is_initialized) { devices_active = true; gomp_fini_device (acc_dev); } gomp_mutex_unlock (&acc_dev->lock); } if (!devices_active) gomp_fatal ("no device initialized"); }
static struct gomp_device_descr * resolve_device (acc_device_t d, bool fail_is_error) { acc_device_t d_arg = d; switch (d) { case acc_device_default: { if (goacc_device_type) { /* Lookup the named device. */ while (++d != _ACC_device_hwm) if (dispatchers[d] && !strcasecmp (goacc_device_type, get_openacc_name (dispatchers[d]->name)) && dispatchers[d]->get_num_devices_func () > 0) goto found; if (fail_is_error) { gomp_mutex_unlock (&acc_device_lock); gomp_fatal ("device type %s not supported", goacc_device_type); } else return NULL; } /* No default device specified, so start scanning for any non-host device that is available. */ d = acc_device_not_host; } /* FALLTHROUGH */ case acc_device_not_host: /* Find the first available device after acc_device_not_host. */ while (++d != _ACC_device_hwm) if (dispatchers[d] && dispatchers[d]->get_num_devices_func () > 0) goto found; if (d_arg == acc_device_default) { d = acc_device_host; goto found; } if (fail_is_error) { gomp_mutex_unlock (&acc_device_lock); gomp_fatal ("no device found"); } else return NULL; break; case acc_device_host: break; default: if (d > _ACC_device_hwm) { if (fail_is_error) goto unsupported_device; else return NULL; } break; } found: assert (d != acc_device_none && d != acc_device_default && d != acc_device_not_host); if (dispatchers[d] == NULL && fail_is_error) { unsupported_device: gomp_mutex_unlock (&acc_device_lock); gomp_fatal ("device type %s not supported", name_of_acc_device_t (d)); } return dispatchers[d]; }