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