svn merge -r 217500:218679 svn+ssh://gcc.gnu.org/svn/gcc/trunk
[official-gcc.git] / libgomp / oacc-init.c
blob3d29eb39f6fd6f0be39473fe1a28a4c8c8da99a6
1 /* OpenACC Runtime initialization routines
3 Copyright (C) 2013-2014 Free Software Foundation, Inc.
5 Contributed by Mentor Embedded.
7 This file is part of the GNU OpenMP Library (libgomp).
9 Libgomp is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 more details.
19 Under Section 7 of GPL version 3, you are granted additional
20 permissions described in the GCC Runtime Library Exception, version
21 3.1, as published by the Free Software Foundation.
23 You should have received a copy of the GNU General Public License and
24 a copy of the GCC Runtime Library Exception along with this program;
25 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26 <http://www.gnu.org/licenses/>. */
28 #include "libgomp.h"
29 #include "libgomp_target.h"
30 #include "oacc-int.h"
31 #include "openacc.h"
32 #include <assert.h>
33 #include <stdlib.h>
34 #include <strings.h>
35 #include <stdbool.h>
36 #include <stdio.h>
38 static gomp_mutex_t acc_device_lock;
40 /* The dispatch table for the current accelerator device. This is global, so
41 you can only have one type of device open at any given time in a program.
42 This is the "base" device in that several devices that use the same
43 dispatch table may be active concurrently: this one (the "zeroth") is used
44 for overall initialisation/shutdown, and other instances -- not necessarily
45 including this one -- may be opened and closed once the base device has
46 been initialized. */
47 struct gomp_device_descr const *base_dev;
49 #if defined HAVE_TLS || defined USE_EMUTLS
50 __thread struct goacc_thread *goacc_tls_data;
51 #else
52 pthread_key_t goacc_tls_key;
53 #endif
54 static pthread_key_t goacc_cleanup_key;
56 /* Current dispatcher, and how it was initialized */
57 static acc_device_t init_key = _ACC_device_hwm;
59 static struct goacc_thread *goacc_threads;
60 static gomp_mutex_t goacc_thread_lock;
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 const *dispatchers[_ACC_device_hwm] = { 0 };
68 attribute_hidden void
69 ACC_register (struct gomp_device_descr const *disp)
71 /* Only register the 0th device here. */
72 if (disp->target_id != 0)
73 return;
75 gomp_mutex_lock (&acc_device_lock);
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;
83 gomp_mutex_unlock (&acc_device_lock);
86 static struct gomp_device_descr const *
87 resolve_device (acc_device_t d)
89 acc_device_t d_arg = d;
91 switch (d)
93 case acc_device_default:
95 if (goacc_device_type)
97 /* Lookup the named device. */
98 while (++d != _ACC_device_hwm)
99 if (dispatchers[d]
100 && !strcasecmp (goacc_device_type, dispatchers[d]->name)
101 && dispatchers[d]->get_num_devices_func () > 0)
102 goto found;
104 gomp_fatal ("device type %s not supported", goacc_device_type);
107 /* No default device specified, so start scanning for any non-host
108 device that is available. */
109 d = acc_device_not_host;
111 /* FALLTHROUGH */
113 case acc_device_not_host:
114 /* Find the first available device after acc_device_not_host. */
115 while (++d != _ACC_device_hwm)
116 if (dispatchers[d] && dispatchers[d]->get_num_devices_func () > 0)
117 goto found;
118 if (d_arg == acc_device_default)
120 d = acc_device_host;
121 goto found;
123 gomp_fatal ("no device found");
124 break;
126 case acc_device_host:
127 break;
129 default:
130 if (d > _ACC_device_hwm)
131 gomp_fatal ("device %u out of range", (unsigned)d);
132 break;
134 found:
136 assert (d != acc_device_none
137 && d != acc_device_default
138 && d != acc_device_not_host);
140 return dispatchers[d];
143 /* This is called when plugins have been initialized, and serves to call
144 (indirectly) the target's device_init hook. Calling multiple times without
145 an intervening _acc_shutdown call is an error. */
147 static struct gomp_device_descr const *
148 _acc_init (acc_device_t d)
150 struct gomp_device_descr const *acc_dev;
152 acc_dev = resolve_device (d);
154 if (!acc_dev || acc_dev->get_num_devices_func () <= 0)
155 gomp_fatal ("device %u not supported", (unsigned)d);
157 if (acc_dev->is_initialized)
158 gomp_fatal ("device already active");
160 /* We need to remember what we were intialized as, to check shutdown etc. */
161 init_key = d;
163 gomp_init_device ((struct gomp_device_descr *) acc_dev);
165 return acc_dev;
168 static struct goacc_thread *
169 goacc_new_thread (void)
171 struct goacc_thread *thr = gomp_malloc (sizeof (struct gomp_thread));
173 #if defined HAVE_TLS || defined USE_EMUTLS
174 goacc_tls_data = thr;
175 #else
176 pthread_setspecific (goacc_tls_key, thr);
177 #endif
179 pthread_setspecific (goacc_cleanup_key, thr);
181 gomp_mutex_lock (&goacc_thread_lock);
182 thr->next = goacc_threads;
183 goacc_threads = thr;
184 gomp_mutex_unlock (&goacc_thread_lock);
186 return thr;
189 static void
190 goacc_destroy_thread (void *data)
192 struct goacc_thread *thr = data, *walk, *prev;
194 gomp_mutex_lock (&goacc_thread_lock);
196 if (thr)
198 if (base_dev && thr->target_tls)
200 base_dev->openacc.destroy_thread_data_func (thr->target_tls);
201 thr->target_tls = NULL;
204 assert (!thr->mapped_data);
206 /* Remove from thread list. */
207 for (prev = NULL, walk = goacc_threads; walk;
208 prev = walk, walk = walk->next)
209 if (walk == thr)
211 if (prev == NULL)
212 goacc_threads = walk->next;
213 else
214 prev->next = walk->next;
216 free (thr);
218 break;
221 assert (walk);
224 gomp_mutex_unlock (&goacc_thread_lock);
227 /* Open the ORD'th device of the currently-active type (base_dev must be
228 initialised before calling). If ORD is < 0, open the default-numbered
229 device (set by the ACC_DEVICE_NUM environment variable or a call to
230 acc_set_device_num), or leave any currently-opened device as is. "Opening"
231 consists of calling the device's open_device_func hook, and setting up
232 thread-local data (maybe allocating, then initializing with information
233 pertaining to the newly-opened or previously-opened device). */
235 static void
236 lazy_open (int ord)
238 struct goacc_thread *thr = goacc_thread ();
239 struct gomp_device_descr *acc_dev;
241 if (thr && thr->dev)
243 assert (ord < 0 || ord == thr->dev->target_id);
244 return;
247 assert (base_dev);
249 if (ord < 0)
250 ord = goacc_device_num;
252 /* The OpenACC 2.0 spec leaves the runtime's behaviour when an out-of-range
253 device is requested as implementation-defined (4.2 ACC_DEVICE_NUM).
254 We choose to raise an error in such a case. */
255 if (ord >= base_dev->get_num_devices_func ())
256 gomp_fatal ("device %u does not exist", ord);
258 if (!thr)
259 thr = goacc_new_thread ();
261 acc_dev = thr->dev = (struct gomp_device_descr *) &base_dev[ord];
263 assert (acc_dev->target_id == ord);
265 thr->saved_bound_dev = NULL;
266 thr->mapped_data = NULL;
268 if (!acc_dev->target_data)
269 acc_dev->target_data = acc_dev->openacc.open_device_func (ord);
271 thr->target_tls
272 = acc_dev->openacc.create_thread_data_func (acc_dev->target_data);
274 acc_dev->openacc.async_set_async_func (acc_async_sync);
276 if (!acc_dev->mem_map.is_initialized)
277 gomp_init_tables (acc_dev, &acc_dev->mem_map);
280 /* OpenACC 2.0a (3.2.12, 3.2.13) doesn't specify whether the serialization of
281 init/shutdown is per-process or per-thread. We choose per-process. */
283 void
284 acc_init (acc_device_t d)
286 if (!base_dev)
287 gomp_init_targets_once ();
289 gomp_mutex_lock (&acc_device_lock);
291 base_dev = _acc_init (d);
293 lazy_open (-1);
295 gomp_mutex_unlock (&acc_device_lock);
298 ialias (acc_init)
300 void
301 _acc_shutdown (acc_device_t d)
303 struct goacc_thread *walk;
305 /* We don't check whether d matches the actual device found, because
306 OpenACC 2.0 (3.2.12) says the parameters to the init and this
307 call must match (for the shutdown call anyway, it's silent on
308 others). */
310 if (!base_dev)
311 gomp_fatal ("no device initialized");
312 if (d != init_key)
313 gomp_fatal ("device %u(%u) is initialized",
314 (unsigned) init_key, (unsigned) base_dev->type);
316 gomp_mutex_lock (&goacc_thread_lock);
318 /* Free target-specific TLS data and close all devices. */
319 for (walk = goacc_threads; walk != NULL; walk = walk->next)
321 if (walk->target_tls)
322 base_dev->openacc.destroy_thread_data_func (walk->target_tls);
324 walk->target_tls = NULL;
326 /* This would mean the user is shutting down OpenACC in the middle of an
327 "acc data" pragma. Likely not intentional. */
328 if (walk->mapped_data)
329 gomp_fatal ("shutdown in 'acc data' region");
331 if (walk->dev)
333 if (walk->dev->openacc.close_device_func (walk->dev->target_data) < 0)
334 gomp_fatal ("failed to close device");
336 walk->dev->target_data = NULL;
338 gomp_free_memmap (walk->dev);
340 walk->dev = NULL;
344 gomp_mutex_unlock (&goacc_thread_lock);
346 gomp_fini_device ((struct gomp_device_descr *) base_dev);
348 base_dev = NULL;
351 void
352 acc_shutdown (acc_device_t d)
354 gomp_mutex_lock (&acc_device_lock);
356 _acc_shutdown (d);
358 gomp_mutex_unlock (&acc_device_lock);
361 ialias (acc_shutdown)
363 /* This function is called after plugins have been initialized. It deals with
364 the "base" device, and is used to prepare the runtime for dealing with a
365 number of such devices (as implemented by some particular plugin). If the
366 argument device type D matches a previous call to the function, return the
367 current base device, else shut the old device down and re-initialize with
368 the new device type. */
370 static struct gomp_device_descr const *
371 lazy_init (acc_device_t d)
373 if (base_dev)
375 /* Re-initializing the same device, do nothing. */
376 if (d == init_key)
377 return base_dev;
379 _acc_shutdown (init_key);
382 assert (!base_dev);
384 return _acc_init (d);
387 /* Ensure that plugins are loaded, initialize and open the (default-numbered)
388 device. */
390 static void
391 lazy_init_and_open (acc_device_t d)
393 if (!base_dev)
394 gomp_init_targets_once ();
396 gomp_mutex_lock (&acc_device_lock);
398 base_dev = lazy_init (d);
400 lazy_open (-1);
402 gomp_mutex_unlock (&acc_device_lock);
406 acc_get_num_devices (acc_device_t d)
408 int n = 0;
409 struct gomp_device_descr const *acc_dev;
411 if (d == acc_device_none)
412 return 0;
414 if (!base_dev)
415 gomp_init_targets_once ();
417 acc_dev = resolve_device (d);
418 if (!acc_dev)
419 return 0;
421 n = acc_dev->get_num_devices_func ();
422 if (n < 0)
423 n = 0;
425 return n;
428 ialias (acc_get_num_devices)
430 void
431 acc_set_device_type (acc_device_t d)
433 lazy_init_and_open (d);
436 ialias (acc_set_device_type)
438 acc_device_t
439 acc_get_device_type (void)
441 acc_device_t res = acc_device_none;
442 const struct gomp_device_descr *dev;
444 if (base_dev)
445 res = acc_device_type (base_dev->type);
446 else
448 gomp_init_targets_once ();
450 dev = resolve_device (acc_device_default);
451 res = acc_device_type (dev->type);
454 assert (res != acc_device_default
455 && res != acc_device_not_host);
457 return res;
460 ialias (acc_get_device_type)
463 acc_get_device_num (acc_device_t d)
465 const struct gomp_device_descr *dev;
466 int num;
468 if (d >= _ACC_device_hwm)
469 gomp_fatal ("device %u out of range", (unsigned)d);
471 if (!base_dev)
472 gomp_init_targets_once ();
474 dev = resolve_device (d);
475 if (!dev)
476 gomp_fatal ("no devices of type %u", d);
478 /* We might not have called lazy_open for this host thread yet, in which case
479 the get_device_num_func hook will return -1. */
480 num = dev->openacc.get_device_num_func ();
481 if (num < 0)
482 num = goacc_device_num;
484 return num;
487 ialias (acc_get_device_num)
489 void
490 acc_set_device_num (int n, acc_device_t d)
492 const struct gomp_device_descr *dev;
493 int num_devices;
495 if (!base_dev)
496 gomp_init_targets_once ();
498 if ((int) d == 0)
500 int i;
502 /* A device setting of zero sets all device types on the system to use
503 the Nth instance of that device type. Only attempt it for initialized
504 devices though. */
505 for (i = acc_device_not_host + 1; i < _ACC_device_hwm; i++)
507 dev = resolve_device (d);
508 if (dev && dev->is_initialized)
509 dev->openacc.set_device_num_func (n);
512 /* ...and for future calls to acc_init/acc_set_device_type, etc. */
513 goacc_device_num = n;
515 else
517 struct goacc_thread *thr = goacc_thread ();
519 gomp_mutex_lock (&acc_device_lock);
521 base_dev = lazy_init (d);
523 num_devices = base_dev->get_num_devices_func ();
525 if (n >= num_devices)
526 gomp_fatal ("device %u out of range", n);
528 /* If we're changing the device number, de-associate this thread with
529 the device (but don't close the device, since it may be in use by
530 other threads). */
531 if (thr && thr->dev && n != thr->dev->target_id)
532 thr->dev = NULL;
534 lazy_open (n);
536 gomp_mutex_unlock (&acc_device_lock);
540 ialias (acc_set_device_num)
543 acc_on_device (acc_device_t dev)
545 struct goacc_thread *thr = goacc_thread ();
547 if (thr && thr->dev
548 && acc_device_type (thr->dev->type) == acc_device_host_nonshm)
549 return dev == acc_device_host_nonshm || dev == acc_device_not_host;
551 /* Just rely on the compiler builtin. */
552 return __builtin_acc_on_device (dev);
554 ialias (acc_on_device)
556 attribute_hidden void
557 ACC_runtime_initialize (void)
559 gomp_mutex_init (&acc_device_lock);
561 #if !(defined HAVE_TLS || defined USE_EMUTLS)
562 pthread_key_create (&goacc_tls_key, NULL);
563 #endif
565 pthread_key_create (&goacc_cleanup_key, goacc_destroy_thread);
567 base_dev = NULL;
569 goacc_threads = NULL;
570 gomp_mutex_init (&goacc_thread_lock);
573 /* Compiler helper functions */
575 attribute_hidden void
576 ACC_save_and_set_bind (acc_device_t d)
578 struct goacc_thread *thr = goacc_thread ();
580 assert (!thr->saved_bound_dev);
582 thr->saved_bound_dev = thr->dev;
583 thr->dev = (struct gomp_device_descr *) dispatchers[d];
586 attribute_hidden void
587 ACC_restore_bind (void)
589 struct goacc_thread *thr = goacc_thread ();
591 thr->dev = thr->saved_bound_dev;
592 thr->saved_bound_dev = NULL;
595 /* This is called from any OpenACC support function that may need to implicitly
596 initialize the libgomp runtime. On exit all such initialization will have
597 been done, and both the global ACC_dev and the per-host-thread ACC_memmap
598 pointers will be valid. */
600 attribute_hidden void
601 ACC_lazy_initialize (void)
603 struct goacc_thread *thr = goacc_thread ();
605 if (thr && thr->dev)
606 return;
608 if (!base_dev)
609 lazy_init_and_open (acc_device_default);
610 else
612 gomp_mutex_lock (&acc_device_lock);
613 lazy_open (-1);
614 gomp_mutex_unlock (&acc_device_lock);