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)
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
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/>. */
29 #include "libgomp_target.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
47 struct gomp_device_descr
const *base_dev
;
49 #if defined HAVE_TLS || defined USE_EMUTLS
50 __thread
struct goacc_thread
*goacc_tls_data
;
52 pthread_key_t goacc_tls_key
;
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 };
69 ACC_register (struct gomp_device_descr
const *disp
)
71 /* Only register the 0th device here. */
72 if (disp
->target_id
!= 0)
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
;
93 case acc_device_default
:
95 if (goacc_device_type
)
97 /* Lookup the named device. */
98 while (++d
!= _ACC_device_hwm
)
100 && !strcasecmp (goacc_device_type
, dispatchers
[d
]->name
)
101 && dispatchers
[d
]->get_num_devices_func () > 0)
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
;
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)
118 if (d_arg
== acc_device_default
)
123 gomp_fatal ("no device found");
126 case acc_device_host
:
130 if (d
> _ACC_device_hwm
)
131 gomp_fatal ("device %u out of range", (unsigned)d
);
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. */
163 gomp_init_device ((struct gomp_device_descr
*) 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
;
176 pthread_setspecific (goacc_tls_key
, thr
);
179 pthread_setspecific (goacc_cleanup_key
, thr
);
181 gomp_mutex_lock (&goacc_thread_lock
);
182 thr
->next
= goacc_threads
;
184 gomp_mutex_unlock (&goacc_thread_lock
);
190 goacc_destroy_thread (void *data
)
192 struct goacc_thread
*thr
= data
, *walk
, *prev
;
194 gomp_mutex_lock (&goacc_thread_lock
);
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
)
212 goacc_threads
= walk
->next
;
214 prev
->next
= walk
->next
;
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). */
238 struct goacc_thread
*thr
= goacc_thread ();
239 struct gomp_device_descr
*acc_dev
;
243 assert (ord
< 0 || ord
== thr
->dev
->target_id
);
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
);
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
);
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. */
284 acc_init (acc_device_t d
)
287 gomp_init_targets_once ();
289 gomp_mutex_lock (&acc_device_lock
);
291 base_dev
= _acc_init (d
);
295 gomp_mutex_unlock (&acc_device_lock
);
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
311 gomp_fatal ("no device initialized");
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");
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
);
344 gomp_mutex_unlock (&goacc_thread_lock
);
346 gomp_fini_device ((struct gomp_device_descr
*) base_dev
);
352 acc_shutdown (acc_device_t d
)
354 gomp_mutex_lock (&acc_device_lock
);
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
)
375 /* Re-initializing the same device, do nothing. */
379 _acc_shutdown (init_key
);
384 return _acc_init (d
);
387 /* Ensure that plugins are loaded, initialize and open the (default-numbered)
391 lazy_init_and_open (acc_device_t d
)
394 gomp_init_targets_once ();
396 gomp_mutex_lock (&acc_device_lock
);
398 base_dev
= lazy_init (d
);
402 gomp_mutex_unlock (&acc_device_lock
);
406 acc_get_num_devices (acc_device_t d
)
409 struct gomp_device_descr
const *acc_dev
;
411 if (d
== acc_device_none
)
415 gomp_init_targets_once ();
417 acc_dev
= resolve_device (d
);
421 n
= acc_dev
->get_num_devices_func ();
428 ialias (acc_get_num_devices
)
431 acc_set_device_type (acc_device_t d
)
433 lazy_init_and_open (d
);
436 ialias (acc_set_device_type
)
439 acc_get_device_type (void)
441 acc_device_t res
= acc_device_none
;
442 const struct gomp_device_descr
*dev
;
445 res
= acc_device_type (base_dev
->type
);
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
);
460 ialias (acc_get_device_type
)
463 acc_get_device_num (acc_device_t d
)
465 const struct gomp_device_descr
*dev
;
468 if (d
>= _ACC_device_hwm
)
469 gomp_fatal ("device %u out of range", (unsigned)d
);
472 gomp_init_targets_once ();
474 dev
= resolve_device (d
);
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 ();
482 num
= goacc_device_num
;
487 ialias (acc_get_device_num
)
490 acc_set_device_num (int n
, acc_device_t d
)
492 const struct gomp_device_descr
*dev
;
496 gomp_init_targets_once ();
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
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
;
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
531 if (thr
&& thr
->dev
&& n
!= thr
->dev
->target_id
)
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 ();
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
);
565 pthread_key_create (&goacc_cleanup_key
, goacc_destroy_thread
);
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 ();
609 lazy_init_and_open (acc_device_default
);
612 gomp_mutex_lock (&acc_device_lock
);
614 gomp_mutex_unlock (&acc_device_lock
);