b52643ab90
The version of nvprof in CUDA 9.0 causes a hang when used to profile an OpenACC program. This is because it calls acc_get_device_type from a callback called during device initialization, which then attempts to acquire acc_device_lock while it is already taken, resulting in deadlock. This works around the issue by returning acc_device_none from acc_get_device_type without attempting to acquire the lock when initialization has not completed yet. 2020-07-14 Tom de Vries <tom@codesourcery.com> Cesar Philippidis <cesar@codesourcery.com> Thomas Schwinge <thomas@codesourcery.com> Kwok Cheung Yeung <kcy@codesourcery.com> libgomp/ * oacc-init.c (acc_init_state_lock, acc_init_state, acc_init_thread): New variable. (acc_init_1): Set acc_init_thread to pthread_self (). Set acc_init_state to initializing at the start, and to initialized at the end. (self_initializing_p): New function. (acc_get_device_type): Return acc_device_none if called by thread that is currently executing acc_init_1. * libgomp.texi (acc_get_device_type): Update documentation. (Implementation Status and Implementation-Defined Behavior): Likewise. * testsuite/libgomp.oacc-c-c++-common/acc_prof-init-2.c: New.
81 lines
2.2 KiB
C
81 lines
2.2 KiB
C
/* { dg-do run } */
|
|
/* { dg-timeout 10 } */
|
|
|
|
/* Test the calling of 'acc_get_device_type' from within
|
|
'cb_device_init_start' and 'cb_device_init_end' callbacks. This occurs
|
|
when the CUDA 9.0 'nvprof' tool is used, and previously deadlocked. */
|
|
|
|
#include <assert.h>
|
|
#include <stdbool.h>
|
|
#include <acc_prof.h>
|
|
|
|
static acc_prof_reg reg;
|
|
static acc_prof_reg unreg;
|
|
static acc_prof_lookup_func lookup;
|
|
|
|
void acc_register_library (acc_prof_reg reg_, acc_prof_reg unreg_, acc_prof_lookup_func lookup_)
|
|
{
|
|
reg = reg_;
|
|
unreg = unreg_;
|
|
lookup = lookup_;
|
|
}
|
|
|
|
static bool expect_cb_device_init_start;
|
|
static bool expect_cb_device_init_end;
|
|
|
|
static void cb_device_init_start (acc_prof_info *prof_info, acc_event_info *event_info, acc_api_info *api_info)
|
|
{
|
|
assert (expect_cb_device_init_start);
|
|
expect_cb_device_init_start = false;
|
|
|
|
acc_device_t acc_device_type;
|
|
acc_device_type = acc_get_device_type ();
|
|
assert (acc_device_type == acc_device_none);
|
|
|
|
expect_cb_device_init_end = true;
|
|
}
|
|
|
|
static void cb_device_init_end (acc_prof_info *prof_info, acc_event_info *event_info, acc_api_info *api_info)
|
|
{
|
|
assert (expect_cb_device_init_end);
|
|
expect_cb_device_init_end = false;
|
|
|
|
acc_device_t acc_device_type;
|
|
acc_device_type = acc_get_device_type ();
|
|
assert (acc_device_type == acc_device_none);
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
acc_register_library (acc_prof_register, acc_prof_unregister, acc_prof_lookup);
|
|
|
|
reg (acc_ev_device_init_start, cb_device_init_start, acc_reg);
|
|
reg (acc_ev_device_init_end, cb_device_init_end, acc_reg);
|
|
|
|
expect_cb_device_init_start = true;
|
|
expect_cb_device_init_end = false;
|
|
acc_init (acc_device_host);
|
|
assert (!expect_cb_device_init_start);
|
|
assert (!expect_cb_device_init_end);
|
|
{
|
|
acc_device_t acc_device_type;
|
|
acc_device_type = acc_get_device_type ();
|
|
assert (acc_device_type == acc_device_host);
|
|
}
|
|
acc_shutdown (acc_device_host);
|
|
|
|
expect_cb_device_init_start = true;
|
|
expect_cb_device_init_end = false;
|
|
acc_init (acc_device_default);
|
|
assert (!expect_cb_device_init_start);
|
|
assert (!expect_cb_device_init_end);
|
|
{
|
|
acc_device_t acc_device_type;
|
|
acc_device_type = acc_get_device_type ();
|
|
assert (acc_device_type != acc_device_none);
|
|
}
|
|
acc_shutdown (acc_device_default);
|
|
|
|
return 0;
|
|
}
|