[OMPT] Windows Support for OMPT

The problem is that the ompt_tool() function (which must be implemented by a
performance tool) should be defined in the RTL as well to cover the case when
the tool is not present in the address space of the process. This functionality
is accomplished with weak symbols in Unices. Unfortunately, Windows does not
support weak symbols.

The solution in these changes is to grab the list of all modules loaded by the
process and then search for symbol "ompt_tool()" within them. The function
ompt_tool_windows() performs the search of the ompt_tool symbol. If ompt_tool is
found, then its return value is used to initialize the tool. If ompt_tool is not
found, then ompt_tool_windows() returns NULL and OMPT is thus, disabled.

While doing these changes, the OMPT_SUPPORT detection in CMake was changed to
test for the required featuers for OMPT_SUPPORT, namely: builtin_frame_address()
existence, weak attribute existence and psapi.dll existence. For
LIBOMP_HAVE_OMPT_SUPPORT to be true, it must be that the builtin_frame_address()
intrinsic exists AND one of: either weak attributes exist or psapi.dll exists.

Also, since Process Status API is used I had to add new dependency -- psapi.dll
to the library dependency micro test.

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

llvm-svn: 251654
This commit is contained in:
Jonathan Peyton 2015-10-29 20:56:24 +00:00
parent e8df6750f4
commit 69e596a5e7
7 changed files with 126 additions and 12 deletions

View File

@ -273,7 +273,6 @@ if(LIBOMP_STATS)
endif()
# OMPT-support
# TODO: Make this a real feature check
set(LIBOMP_OMPT_SUPPORT FALSE CACHE BOOL
"OMPT-support?")
set(LIBOMP_OMPT_BLAME TRUE CACHE BOOL

View File

@ -175,6 +175,7 @@ elseif(APPLE)
set(libomp_expected_library_deps /usr/lib/libSystem.B.dylib)
elseif(WIN32)
set(libomp_expected_library_deps kernel32.dll)
libomp_append(libomp_expected_library_deps psapi.dll LIBOMP_OMPT_SUPPORT)
else()
if(${MIC})
set(libomp_expected_library_deps libc.so.6 libpthread.so.0 libdl.so.2)

View File

@ -13,6 +13,7 @@ include(CheckCCompilerFlag)
include(CheckCSourceCompiles)
include(CheckCXXCompilerFlag)
include(CheckLibraryExists)
include(CheckIncludeFiles)
include(LibompCheckLinkerFlag)
include(LibompCheckFortranFlag)
@ -187,8 +188,26 @@ else()
endif()
# Check if OMPT support is available
if(NOT WIN32)
set(LIBOMP_HAVE_OMPT_SUPPORT TRUE)
else()
set(LIBOMP_HAVE_OMPT_SUPPORT FALSE)
# Currently, __builtin_frame_address() is required for OMPT
# Weak attribute is required for Unices, LIBPSAPI is used for Windows
check_c_source_compiles("int main(int argc, char** argv) {
void* p = __builtin_frame_address(0);
return 0;}" LIBOMP_HAVE___BUILTIN_FRAME_ADDRESS)
check_c_source_compiles("__attribute__ ((weak)) int foo(int a) { return a*a; }
int main(int argc, char** argv) {
return foo(argc);}" LIBOMP_HAVE_WEAK_ATTRIBUTE)
check_include_files("windows.h;psapi.h" LIBOMP_HAVE_PSAPI_H)
check_library_exists(psapi EnumProcessModules "" LIBOMP_HAVE_LIBPSAPI)
if(LIBOMP_HAVE_PSAPI_H AND LIBOMP_HAVE_LIBPSAPI)
set(LIBOMP_HAVE_PSAPI TRUE)
endif()
if(NOT LIBOMP_HAVE___BUILTIN_FRAME_ADDRESS)
set(LIBOMP_HAVE_OMPT_SUPPORT FALSE)
else()
if(LIBOMP_HAVE_WEAK_ATTRIBUTE OR LIBOMP_HAVE_PSAPI)
set(LIBOMP_HAVE_OMPT_SUPPORT TRUE)
else()
set(LIBOMP_HAVE_OMPT_SUPPORT FALSE)
endif()
endif()

View File

@ -27,6 +27,10 @@
#if LIBOMP_USE_VERSION_SYMBOLS
# define KMP_USE_VERSION_SYMBOLS
#endif
#cmakedefine01 LIBOMP_HAVE_WEAK_ATTRIBUTE
#define KMP_HAVE_WEAK_ATTRIBUTE LIBOMP_HAVE_WEAK_ATTRIBUTE
#cmakedefine01 LIBOMP_HAVE_PSAPI
#define KMP_HAVE_PSAPI LIBOMP_HAVE_PSAPI
#cmakedefine01 LIBOMP_STATS
#define KMP_STATS_ENABLED LIBOMP_STATS
#cmakedefine01 LIBOMP_USE_DEBUGGER

View File

@ -15,7 +15,6 @@
* ompt include files
****************************************************************************/
#include "kmp_config.h"
#include "ompt-internal.h"
#include "ompt-specific.c"
@ -32,6 +31,9 @@
#define OMPT_API_ROUTINE static
#ifndef OMPT_STR_MATCH
#define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle))
#endif
/*****************************************************************************
@ -87,17 +89,93 @@ 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 ))
/* On Unix-like systems that support weak symbols the following implementation
* of ompt_tool() will be used in case no tool-supplied implementation of
* this function is present in the address space of a process.
*
* On Windows, the ompt_tool_windows function is used to find the
* ompt_tool symbol across all modules loaded by a process. If ompt_tool is
* found, ompt_tool's return value is used to initialize the tool. Otherwise,
* NULL is returned and OMPT won't be enabled */
#if OMPT_HAVE_WEAK_ATTRIBUTE
_OMP_EXTERN
__attribute__ (( weak ))
ompt_initialize_t ompt_tool()
{
#if OMPT_DEBUG
printf("ompt_tool() is called from the RTL\n");
#endif
return NULL;
}
#elif OMPT_HAVE_PSAPI
#include <psapi.h>
#pragma comment(lib, "psapi.lib")
#define ompt_tool ompt_tool_windows
// The number of loaded modules to start enumeration with EnumProcessModules()
#define NUM_MODULES 128
static
ompt_initialize_t ompt_tool_windows()
{
int i;
DWORD needed, new_size;
HMODULE *modules;
HANDLE process = GetCurrentProcess();
modules = (HMODULE*)malloc( NUM_MODULES * sizeof(HMODULE) );
ompt_initialize_t (*ompt_tool_p)() = NULL;
#if OMPT_DEBUG
printf("ompt_tool_windows(): looking for ompt_tool\n");
#endif
if( !EnumProcessModules( process, modules, NUM_MODULES * sizeof(HMODULE),
&needed ) ) {
// Regardless of the error reason use the stub initialization function
return NULL;
}
// Check if NUM_MODULES is enough to list all modules
new_size = needed / sizeof(HMODULE);
if( new_size > NUM_MODULES ) {
#if OMPT_DEBUG
printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed);
#endif
modules = (HMODULE*)realloc( modules, needed );
// If resizing failed use the stub function.
if( !EnumProcessModules( process, modules, needed, &needed ) ) {
return NULL;
}
}
for( i = 0; i < new_size; ++i ) {
(FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_tool");
if( ompt_tool_p ) {
#if OMPT_DEBUG
TCHAR modName[MAX_PATH];
if( GetModuleFileName(modules[i], modName, MAX_PATH))
printf("ompt_tool_windows(): ompt_tool found in module %s\n",
modName);
#endif
return ompt_tool_p();
}
#if OMPT_DEBUG
else {
TCHAR modName[MAX_PATH];
if( GetModuleFileName(modules[i], modName, MAX_PATH) )
printf("ompt_tool_windows(): ompt_tool not found in module %s\n",
modName);
}
#endif
}
return NULL;
}
#else
# error Either __attribute__((weak)) or psapi.dll are required for OMPT support
#endif // OMPT_HAVE_WEAK_ATTRIBUTE
void ompt_pre_init()
{
@ -118,11 +196,14 @@ void ompt_pre_init()
if (!ompt_env_var || !strcmp(ompt_env_var, ""))
tool_setting = omp_tool_unset;
else if (!strcasecmp(ompt_env_var, "disabled"))
else if (OMPT_STR_MATCH(ompt_env_var, "disabled"))
tool_setting = omp_tool_disabled;
else if (!strcasecmp(ompt_env_var, "enabled"))
else if (OMPT_STR_MATCH(ompt_env_var, "enabled"))
tool_setting = omp_tool_enabled;
#if OMPT_DEBUG
printf("ompt_pre_init(): tool_setting = %d\n", tool_setting);
#endif
switch(tool_setting) {
case omp_tool_disabled:
break;
@ -142,7 +223,9 @@ void ompt_pre_init()
"\"enabled\").\n", ompt_env_var);
break;
}
#if OMPT_DEBUG
printf("ompt_pre_init():ompt_enabled = %d\n", ompt_enabled);
#endif
}

View File

@ -29,7 +29,7 @@
#define NEXT_ID(id_ptr,tid) \
((KMP_TEST_THEN_INC64(id_ptr) << OMPT_THREAD_ID_BITS) | (tid))
#else
#define NEXT_ID(id_ptr,tid) (KMP_TEST_THEN_INC64(id_ptr))
#define NEXT_ID(id_ptr,tid) (KMP_TEST_THEN_INC64((volatile kmp_int64 *)id_ptr))
#endif
//******************************************************************************

View File

@ -34,6 +34,14 @@ ompt_task_id_t __ompt_get_task_id_internal(int depth);
ompt_frame_t *__ompt_get_task_frame_internal(int depth);
/*****************************************************************************
* macros
****************************************************************************/
#define OMPT_DEBUG KMP_DEBUG
#define OMPT_HAVE_WEAK_ATTRIBUTE KMP_HAVE_WEAK_ATTRIBUTE
#define OMPT_HAVE_PSAPI KMP_HAVE_PSAPI
#define OMPT_STR_MATCH(haystack, needle) __kmp_str_match(haystack, 0, needle)
//******************************************************************************
// inline functions