[OMPT] Overhaul OMPT initialization interface

The OMPT specification has changed. This revision brings the LLVM OpenMP
implementation up to date.

Technical overview of changes:
Previously, a public weak symbol ompt_initialize was called after the OpenMP
runtime is initialized. The new interface calls a global weak symbol ompt_tool
prior to initialization. If a tool is present, ompt_tool returns a pointer to
a function that matches the signature for ompt_initialize. After OpenMP is 
initialized the function pointer is called to initialize a tool.
Knowing that OMPT will be enabled before initialization allows OMPT support to
be initialized as part of initialization instead of back patching
initialization of OMPT support after the fact.
Post OpenMP initialization support has been generalized moves from
ompt-specific.c into ompt-general.c, since the OMPT initialization logic is no
longer implementation specific.

Patch by John Mellor-Crummey

Differential Revision: http://reviews.llvm.org/D12998

llvm-svn: 248187
This commit is contained in:
Jonathan Peyton 2015-09-21 18:01:02 +00:00
parent ab58c74d98
commit 82a13bf36c
9 changed files with 200 additions and 163 deletions

View File

@ -21,7 +21,11 @@ VERSION {
# "Normal" symbols.
#
omp_*; # Standard OpenMP functions.
ompt_initialize; # OMPT initialization interface
#
# OMPT API
#
ompt_tool; # OMPT initialization interface
ompt_control; # OMPT control interface
#

View File

@ -418,12 +418,15 @@ OMPT_API_FUNCTION(void, ompt_mutex_wait, (
* INITIALIZATION FUNCTIONS
***************************************************************************/
/* initialization interface to be defined by tool */
int ompt_initialize(
OMPT_API_FUNCTION(void, ompt_initialize, (
ompt_function_lookup_t ompt_fn_lookup,
const char *runtime_version,
unsigned int ompt_version
);
));
/* initialization interface to be defined by tool */
ompt_initialize_t ompt_tool(void);
typedef enum opt_init_mode_e {
ompt_init_mode_never = 0,

View File

@ -418,12 +418,15 @@ OMPT_API_FUNCTION(void, ompt_mutex_wait, (
* INITIALIZATION FUNCTIONS
***************************************************************************/
/* initialization interface to be defined by tool */
int ompt_initialize(
OMPT_API_FUNCTION(void, ompt_initialize, (
ompt_function_lookup_t ompt_fn_lookup,
const char *runtime_version,
unsigned int ompt_version
);
));
/* initialization interface to be defined by tool */
ompt_initialize_t ompt_tool(void);
typedef enum opt_init_mode_e {
ompt_init_mode_never = 0,

View File

@ -418,12 +418,15 @@ OMPT_API_FUNCTION(void, ompt_mutex_wait, (
* INITIALIZATION FUNCTIONS
***************************************************************************/
/* initialization interface to be defined by tool */
int ompt_initialize(
OMPT_API_FUNCTION(void, ompt_initialize, (
ompt_function_lookup_t ompt_fn_lookup,
const char *runtime_version,
unsigned int ompt_version
);
));
/* initialization interface to be defined by tool */
ompt_initialize_t ompt_tool(void);
typedef enum opt_init_mode_e {
ompt_init_mode_never = 0,

View File

@ -6386,6 +6386,10 @@ __kmp_do_serial_initialize( void )
KMP_DEBUG_ASSERT( sizeof( kmp_uint64 ) == 8 );
KMP_DEBUG_ASSERT( sizeof( kmp_intptr_t ) == sizeof( void * ) );
#if OMPT_SUPPORT
ompt_pre_init();
#endif
__kmp_validate_locks();
/* Initialize internal memory allocator */
@ -6623,12 +6627,13 @@ __kmp_do_serial_initialize( void )
}
#endif // OMP_40_ENABLED
#if OMPT_SUPPORT
ompt_post_init();
#endif
KMP_MB();
KA_TRACE( 10, ("__kmp_do_serial_initialize: exit\n" ) );
#if OMPT_SUPPORT
ompt_init();
#endif
}
void
@ -6773,9 +6778,6 @@ __kmp_middle_initialize( void )
}
__kmp_do_middle_initialize();
__kmp_release_bootstrap_lock( &__kmp_initz_lock );
#if OMPT_SUPPORT
ompt_init();
#endif
}
void
@ -6783,7 +6785,7 @@ __kmp_parallel_initialize( void )
{
int gtid = __kmp_entry_gtid(); // this might be a new root
/* syncronize parallel initialization (for sibling) */
/* synchronize parallel initialization (for sibling) */
if( TCR_4(__kmp_init_parallel) ) return;
__kmp_acquire_bootstrap_lock( &__kmp_initz_lock );
if( TCR_4(__kmp_init_parallel) ) { __kmp_release_bootstrap_lock( &__kmp_initz_lock ); return; }
@ -6845,9 +6847,6 @@ __kmp_parallel_initialize( void )
KA_TRACE( 10, ("__kmp_parallel_initialize: exit\n" ) );
__kmp_release_bootstrap_lock( &__kmp_initz_lock );
#if OMPT_SUPPORT
ompt_init();
#endif
}

View File

@ -44,6 +44,21 @@ typedef struct {
} ompt_state_info_t;
enum tool_setting_e {
omp_tool_error,
omp_tool_unset,
omp_tool_disabled,
omp_tool_enabled
};
typedef void (*ompt_initialize_t) (
ompt_function_lookup_t ompt_fn_lookup,
const char *version,
unsigned int ompt_version
);
/*****************************************************************************
* global variables
@ -58,9 +73,10 @@ ompt_state_info_t ompt_state_info[] = {
#undef ompt_state_macro
};
ompt_callbacks_t ompt_callbacks;
static ompt_initialize_t ompt_initialize_fn = NULL;
/*****************************************************************************
@ -69,6 +85,116 @@ ompt_callbacks_t ompt_callbacks;
static ompt_interface_fn_t ompt_fn_lookup(const char *s);
OMPT_API_ROUTINE ompt_thread_id_t ompt_get_thread_id(void);
/*****************************************************************************
* initialization and finalization (private operations)
****************************************************************************/
_OMP_EXTERN __attribute__ (( weak ))
ompt_initialize_t ompt_tool()
{
return NULL;
}
void ompt_pre_init()
{
//--------------------------------------------------
// Execute the pre-initialization logic only once.
//--------------------------------------------------
static int ompt_pre_initialized = 0;
if (ompt_pre_initialized) return;
ompt_pre_initialized = 1;
//--------------------------------------------------
// Use a tool iff a tool is enabled and available.
//--------------------------------------------------
const char *ompt_env_var = getenv("OMP_TOOL");
tool_setting_e tool_setting = omp_tool_error;
if (!ompt_env_var || !strcmp(ompt_env_var, ""))
tool_setting = omp_tool_unset;
else if (!strcasecmp(ompt_env_var, "disabled"))
tool_setting = omp_tool_disabled;
else if (!strcasecmp(ompt_env_var, "enabled"))
tool_setting = omp_tool_enabled;
switch(tool_setting) {
case omp_tool_disabled:
ompt_status = ompt_status_disabled;
break;
case omp_tool_unset:
case omp_tool_enabled:
ompt_initialize_fn = ompt_tool();
if (ompt_initialize_fn) {
ompt_status = ompt_status_track_callback;
}
break;
case omp_tool_error:
fprintf(stderr,
"Warning: OMP_TOOL has invalid value \"%s\".\n"
" legal values are (NULL,\"\",\"disabled\","
"\"enabled\").\n", ompt_env_var);
break;
}
}
void ompt_post_init()
{
//--------------------------------------------------
// Execute the post-initialization logic only once.
//--------------------------------------------------
static int ompt_post_initialized = 0;
if (ompt_post_initialized) return;
ompt_post_initialized = 1;
//--------------------------------------------------
// Initialize the tool if so indicated.
//--------------------------------------------------
if (ompt_status == ompt_status_track_callback) {
ompt_initialize_fn(ompt_fn_lookup, ompt_get_runtime_version(),
OMPT_VERSION);
ompt_thread_t *root_thread = ompt_get_thread();
ompt_set_thread_state(root_thread, ompt_state_overhead);
if (ompt_callbacks.ompt_callback(ompt_event_thread_begin)) {
ompt_callbacks.ompt_callback(ompt_event_thread_begin)
(ompt_thread_initial, ompt_get_thread_id());
}
ompt_set_thread_state(root_thread, ompt_state_work_serial);
}
}
void ompt_fini()
{
if (ompt_status == ompt_status_track_callback) {
if (ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)) {
ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)();
}
}
ompt_status = ompt_status_disabled;
}
/*****************************************************************************
* interface operations
****************************************************************************/
/*****************************************************************************
* state
@ -142,85 +268,6 @@ OMPT_API_ROUTINE int ompt_get_callback(ompt_event_t evid, ompt_callback_t *cb)
}
/*****************************************************************************
* intialization/finalization
****************************************************************************/
_OMP_EXTERN __attribute__ (( weak ))
int ompt_initialize(ompt_function_lookup_t ompt_fn_lookup, const char *version,
unsigned int ompt_version)
{
return no_tool_present;
}
enum tool_setting_e {
omp_tool_error,
omp_tool_unset,
omp_tool_disabled,
omp_tool_enabled
};
void ompt_init()
{
static int ompt_initialized = 0;
if (ompt_initialized) return;
const char *ompt_env_var = getenv("OMP_TOOL");
tool_setting_e tool_setting = omp_tool_error;
if (!ompt_env_var || !strcmp(ompt_env_var, ""))
tool_setting = omp_tool_unset;
else if (!strcmp(ompt_env_var, "disabled"))
tool_setting = omp_tool_disabled;
else if (!strcmp(ompt_env_var, "enabled"))
tool_setting = omp_tool_enabled;
switch(tool_setting) {
case omp_tool_disabled:
ompt_status = ompt_status_disabled;
break;
case omp_tool_unset:
case omp_tool_enabled:
{
const char *runtime_version = __ompt_get_runtime_version_internal();
int ompt_init_val =
ompt_initialize(ompt_fn_lookup, runtime_version, OMPT_VERSION);
if (ompt_init_val) {
ompt_status = ompt_status_track_callback;
__ompt_init_internal();
}
break;
}
case omp_tool_error:
fprintf(stderr,
"Warning: OMP_TOOL has invalid value \"%s\".\n"
" legal values are (NULL,\"\",\"disabled\","
"\"enabled\").\n", ompt_env_var);
break;
}
ompt_initialized = 1;
}
void ompt_fini()
{
if (ompt_status == ompt_status_track_callback) {
if (ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)) {
ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)();
}
}
ompt_status = ompt_status_disabled;
}
/*****************************************************************************
* parallel regions
****************************************************************************/

View File

@ -77,7 +77,8 @@ extern ompt_callbacks_t ompt_callbacks;
extern "C" {
#endif
void ompt_init(void);
void ompt_pre_init(void);
void ompt_post_init(void);
void ompt_fini(void);
#ifdef __cplusplus

View File

@ -123,39 +123,6 @@ __ompt_get_taskinfo(int depth)
// interface operations
//******************************************************************************
//----------------------------------------------------------
// initialization support
//----------------------------------------------------------
void
__ompt_init_internal()
{
if (ompt_status & ompt_status_track) {
// initialize initial thread for OMPT
kmp_info_t *root_thread = ompt_get_thread();
__kmp_task_init_ompt(
root_thread->th.th_team->t.t_implicit_task_taskdata, 0);
__kmp_task_init_ompt(
root_thread->th.th_serial_team->t.t_implicit_task_taskdata, 0);
// make mandatory callback for creation of initial thread
// this needs to occur here rather than in __kmp_register_root because
// __kmp_register_root is called before ompt_initialize
int gtid = __kmp_get_gtid();
if (KMP_UBER_GTID(gtid)) {
// initialize the initial thread's idle frame and state
root_thread->th.ompt_thread_info.idle_frame = 0;
root_thread->th.ompt_thread_info.state = ompt_state_overhead;
if ((ompt_status == ompt_status_track_callback) &&
ompt_callbacks.ompt_callback(ompt_event_thread_begin)) {
__ompt_thread_begin(ompt_thread_initial, gtid);
}
root_thread->th.ompt_thread_info.state = ompt_state_work_serial;
}
}
}
//----------------------------------------------------------
// thread support
//----------------------------------------------------------
@ -361,14 +328,3 @@ __ompt_team_assign_id(kmp_team_t *team, ompt_parallel_id_t ompt_pid)
{
team->t.ompt_team_info.parallel_id = ompt_pid;
}
//----------------------------------------------------------
// runtime version support
//----------------------------------------------------------
const char *
__ompt_get_runtime_version_internal()
{
return &__kmp_version_lib_ver[KMP_VERSION_MAGIC_LEN];
}

View File

@ -3,16 +3,18 @@
#include "kmp.h"
typedef kmp_info_t ompt_thread_t;
void __ompt_team_assign_id(kmp_team_t *team, ompt_parallel_id_t ompt_pid);
void __ompt_thread_assign_wait_id(void *variable);
void __ompt_lw_taskteam_init(ompt_lw_taskteam_t *lwt, kmp_info_t *thr,
void __ompt_lw_taskteam_init(ompt_lw_taskteam_t *lwt, ompt_thread_t *thr,
int gtid, void *microtask,
ompt_parallel_id_t ompt_pid);
void __ompt_lw_taskteam_link(ompt_lw_taskteam_t *lwt, kmp_info_t *thr);
void __ompt_lw_taskteam_link(ompt_lw_taskteam_t *lwt, ompt_thread_t *thr);
ompt_lw_taskteam_t * __ompt_lw_taskteam_unlink(kmp_info_t *thr);
ompt_lw_taskteam_t * __ompt_lw_taskteam_unlink(ompt_thread_t *thr);
ompt_parallel_id_t __ompt_parallel_id_new(int gtid);
ompt_task_id_t __ompt_task_id_new(int gtid);
@ -21,29 +23,48 @@ ompt_team_info_t *__ompt_get_teaminfo(int depth, int *size);
ompt_task_info_t *__ompt_get_taskinfo(int depth);
inline kmp_info_t *
ompt_get_thread_gtid(int gtid)
{
return (gtid >= 0) ? __kmp_thread_from_gtid(gtid) : NULL;
}
inline kmp_info_t *
ompt_get_thread()
{
int gtid = __kmp_gtid_get_specific();
return ompt_get_thread_gtid(gtid);
}
void __ompt_thread_begin(ompt_thread_type_t thread_type, int gtid);
void __ompt_thread_end(ompt_thread_type_t thread_type, int gtid);
int __ompt_get_parallel_team_size_internal(int ancestor_level);
ompt_task_id_t __ompt_get_task_id_internal(int depth);
ompt_frame_t *__ompt_get_task_frame_internal(int depth);
//******************************************************************************
// inline functions
//******************************************************************************
inline ompt_thread_t *
ompt_get_thread_gtid(int gtid)
{
return (gtid >= 0) ? __kmp_thread_from_gtid(gtid) : NULL;
}
inline ompt_thread_t *
ompt_get_thread()
{
int gtid = __kmp_gtid_get_specific();
return ompt_get_thread_gtid(gtid);
}
inline void
ompt_set_thread_state(ompt_thread_t *thread, ompt_state_t state)
{
thread->th.ompt_thread_info.state = state;
}
inline const char *
ompt_get_runtime_version()
{
return &__kmp_version_lib_ver[KMP_VERSION_MAGIC_LEN];
}
#endif