Hi Jakub, there's a path for deadlock on acc_device_lock when going through the acc_set_device_type() OpenACC library function. Basically, the gomp_init_targets_once() function should not be called with that held. The attached patch moves it appropriately.
Also in this patch, there are several cases in acc_* functions where gomp_init_targets_once() is guarded by a test of !cached_base_dev. Since that function already uses pthread_once() to call gomp_target_init(), and technically cached_base_dev is protected by acc_device_lock, the cleanest way should be to simply drop those "if(!cached_base_dev)" tests. Tested libgomp without regressions on an nvptx offloaded system, is this okay for trunk? Thanks, Chung-Lin 2016-03-28 Chung-Lin Tang <clt...@codesourcery.com> * oacc-init.c (acc_init): Remove !cached_base_dev condition on call to gomp_init_targets_once(). (acc_set_device_type): Remove !cached_base_dev condition on call to gomp_init_targets_once(), move call to before acc_device_lock acquire, to avoid deadlock. (acc_get_device_num): Remove !cached_base_dev condition on call to gomp_init_targets_once(). (acc_set_device_num): Likewise.
Index: oacc-init.c =================================================================== --- oacc-init.c (revision 234502) +++ oacc-init.c (working copy) @@ -433,8 +433,7 @@ goacc_attach_host_thread_to_device (int ord) void acc_init (acc_device_t d) { - if (!cached_base_dev) - gomp_init_targets_once (); + gomp_init_targets_once (); gomp_mutex_lock (&acc_device_lock); @@ -498,11 +497,10 @@ acc_set_device_type (acc_device_t d) struct gomp_device_descr *base_dev, *acc_dev; struct goacc_thread *thr = goacc_thread (); + gomp_init_targets_once (); + gomp_mutex_lock (&acc_device_lock); - if (!cached_base_dev) - gomp_init_targets_once (); - cached_base_dev = base_dev = resolve_device (d, true); acc_dev = &base_dev[goacc_device_num]; @@ -563,8 +561,7 @@ acc_get_device_num (acc_device_t d) if (d >= _ACC_device_hwm) gomp_fatal ("unknown device type %u", (unsigned) d); - if (!cached_base_dev) - gomp_init_targets_once (); + gomp_init_targets_once (); gomp_mutex_lock (&acc_device_lock); dev = resolve_device (d, true); @@ -584,8 +581,7 @@ acc_set_device_num (int ord, acc_device_t d) struct gomp_device_descr *base_dev, *acc_dev; int num_devices; - if (!cached_base_dev) - gomp_init_targets_once (); + gomp_init_targets_once (); if (ord < 0) ord = goacc_device_num;