Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,30 @@ jobs:
# doesn't work in case of CMake + VS (https://github.com/fortran-lang/setup-fortran/issues/45)
run: python buildall.py --force_bits 64 -ft ${{ matrix.optional_args }}

refcol_smoke:
name: Reference collector smoke test
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
lib: build_linux/64/bin/libittnotify_refcol.so
exe: build_linux/64/bin/refcol_smoke_test
- os: windows-latest
lib: build_win/64/bin/libittnotify_refcol.dll
exe: build_win/64/bin/refcol_smoke_test.exe
defaults:
run:
shell: bash
steps:
- name: Checkout sources
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Build reference collector library and smoke test
run: python buildall.py --force_bits 64 --refcol -DITT_API_REFCOL_SMOKE_TESTS=ON ${{ runner.os == 'Windows' && '--cmake_gen ninja' || '' }}
- name: Run smoke test
run: python src/ittnotify_refcol/tests/run_smoke_test.py --lib ${{ matrix.lib }} --exe ${{ matrix.exe }}

cpp_wrapper:
name: Check C++ wrapper
runs-on: ${{ matrix.os }}
Expand Down
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ option(FORCE_32 "Force a 32-bit compile on 64-bit" OFF)
option(ITT_API_IPT_SUPPORT "ptmarks support" OFF)
option(ITT_API_FORTRAN_SUPPORT "fortran support" OFF)
option(ITT_API_CPP_SUPPORT "C++ wrapper support" OFF)
option(ITT_API_REFERENCE_COLLECTOR "Build reference collector shared library" OFF)
option(ITT_API_INSTALL "Enable ITT API installation rules" ON)

if(FORCE_32 AND UNIX)
Expand Down Expand Up @@ -141,6 +142,10 @@ add_library(ittapi::ittnotify ALIAS ittnotify)
set(JITPROFILING_SRC "src/ittnotify/jitprofiling.c")
add_library(jitprofiling STATIC ${JITPROFILING_SRC})

if(ITT_API_REFERENCE_COLLECTOR)
Comment thread
alexey-kireev marked this conversation as resolved.
add_subdirectory(src/ittnotify_refcol)
endif()

if(WIN32)
set_target_properties(ittnotify PROPERTIES OUTPUT_NAME libittnotify)
set_target_properties(jitprofiling PROPERTIES OUTPUT_NAME libjitprofiling)
Expand Down
10 changes: 8 additions & 2 deletions buildall.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ def main():
"-ft", "--fortran", help="enable fortran support", action="store_true")
parser.add_argument(
"-cpp", "--cpp", help="enable C++ wrapper support", action="store_true")
parser.add_argument(
"--refcol", help="enable reference collector build", action="store_true")
parser.add_argument(
"-D", dest="cmake_defines", metavar="VAR=VALUE", action="append", default=[],
help="pass extra -D defines to cmake (may be specified multiple times)")
parser.add_argument(
"--force_bits", choices=["32", "64"], help="specify bit version for the target")
if sys.platform == 'win32' and vs_versions:
Expand Down Expand Up @@ -180,8 +185,9 @@ def main():
('-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON' if args.verbose else ''),
("-DITT_API_IPT_SUPPORT=1" if args.ptmark else ""),
("-DITT_API_FORTRAN_SUPPORT=1" if args.fortran else ""),
("-DITT_API_CPP_SUPPORT=ON" if args.cpp else "")
])))
("-DITT_API_CPP_SUPPORT=ON" if args.cpp else ""),
("-DITT_API_REFERENCE_COLLECTOR=ON" if args.refcol else ""),
] + ["-D" + d for d in args.cmake_defines])))

if sys.platform == 'win32':
target_project = 'ALL_BUILD' if not use_ninja else 'all'
Expand Down
33 changes: 33 additions & 0 deletions src/ittnotify_refcol/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
add_library(ittnotify_refcol SHARED itt_refcol_impl.c)

target_include_directories(ittnotify_refcol
PUBLIC $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
PRIVATE ${CMAKE_SOURCE_DIR}/src/ittnotify
)

target_link_libraries(ittnotify_refcol PRIVATE ${CMAKE_DL_LIBS})
set_target_properties(ittnotify_refcol PROPERTIES
LINKER_LANGUAGE C
RUNTIME_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH})

if(WIN32)
set_target_properties(ittnotify_refcol PROPERTIES
OUTPUT_NAME libittnotify_refcol
PREFIX ""
WINDOWS_EXPORT_ALL_SYMBOLS ON)
else()
set_target_properties(ittnotify_refcol PROPERTIES OUTPUT_NAME ittnotify_refcol)
endif()

option(ITT_API_REFCOL_SMOKE_TESTS "Build reference collector smoke tests" OFF)
if(ITT_API_REFCOL_SMOKE_TESTS)
add_executable(refcol_smoke_test tests/smoke_test.c)
target_include_directories(refcol_smoke_test
PRIVATE ${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src/ittnotify
)
target_link_libraries(refcol_smoke_test PRIVATE ittnotify ${CMAKE_DL_LIBS})
set_target_properties(refcol_smoke_test PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH})
endif()
47 changes: 40 additions & 7 deletions src/ittnotify_refcol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,52 @@ performs tracing data from ITT API function calls to log files.

To use this solution, build the collector as a shared library and point the
full library path to the `INTEL_LIBITTNOTIFY64` or `INTEL_LIBITTNOTIFY32`
environment variable:
environment variable.

**On Linux**
## Building

### CMake (all platforms, recommended)

```
cmake <repo_root> -DITT_API_REFERENCE_COLLECTOR=ON
cmake --build .
```

The shared library is placed in the `bin/` subdirectory of the CMake build
directory. Alternatively, use the provided `buildall.py` script:

```
python buildall.py --refcol
```

### Make (Linux / FreeBSD)

```
make
export INTEL_LIBITTNOTIFY64=<build_dir>/libittnotify_refcol.so
```

## Usage

**On Linux**

```
export INTEL_LIBITTNOTIFY64=<build_dir>/bin/libittnotify_refcol.so
```

**On FreeBSD**

```
make
setenv INTEL_LIBITTNOTIFY64 <build_dir>/libittnotify_refcol.so
setenv INTEL_LIBITTNOTIFY64 <build_dir>/bin/libittnotify_refcol.so
```

**On Windows**

```
set INTEL_LIBITTNOTIFY64=<build_dir>\bin\libittnotify_refcol.dll
```

By default, log files save in the `tmp` directory. To change the location,
use the `INTEL_LIBITTNOTIFY_LOG_DIR` environment variable:
By default, log files are saved in the system temporary directory. To change
the location, use the `INTEL_LIBITTNOTIFY_LOG_DIR` environment variable:

**On Linux**

Expand All @@ -35,6 +63,11 @@ export INTEL_LIBITTNOTIFY_LOG_DIR=<log_dir>
setenv INTEL_LIBITTNOTIFY_LOG_DIR <log_dir>
```

**On Windows**
```
set INTEL_LIBITTNOTIFY_LOG_DIR=<log_dir>
```

This implementation adds logging of some of the ITT API function calls. Adding
logging of other ITT API function calls is welcome. The solution provides 4
functions with different log levels that take `printf` format for logging:
Expand Down
137 changes: 134 additions & 3 deletions src/ittnotify_refcol/itt_refcol_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
*/

#include <inttypes.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
Expand Down Expand Up @@ -45,15 +47,34 @@ static struct ref_collector_global {
__itt_histogram* histogram_list;
} g_ref_collector_global = {MUTEX_INITIALIZER, 0, NULL, NULL, NULL, NULL};

#ifdef _WIN32
#define REFCOL_LOCALTIME(out_tm, in_time) (localtime_s((out_tm), (in_time)) == 0)
#else
#define REFCOL_LOCALTIME(out_tm, in_time) (localtime_r((in_time), (out_tm)) != NULL)
#endif

static char* log_file_name_generate()
{
time_t time_now = time(NULL);
struct tm* time_info = localtime(&time_now);
struct tm time_info;
char* log_file_name = malloc(sizeof(char) * (LOG_BUFFER_MAX_SIZE/2));

if (log_file_name == NULL)
{
printf("ERROR: Failed to allocate memory for log file name\n");
return NULL;
}

if (!REFCOL_LOCALTIME(&time_info, &time_now))
{
printf("ERROR: Failed to get local time for log file name\n");
free(log_file_name);
return NULL;
}

sprintf(log_file_name,"libittnotify_refcol_%d%d%d%d%d%d.log",
time_info->tm_year+1900, time_info->tm_mon+1, time_info->tm_mday,
time_info->tm_hour, time_info->tm_min, time_info->tm_sec);
time_info.tm_year+1900, time_info.tm_mon+1, time_info.tm_mday,
time_info.tm_hour, time_info.tm_min, time_info.tm_sec);

return log_file_name;
}
Expand Down Expand Up @@ -85,6 +106,10 @@ static void ref_collector_init()
{
sprintf(file_name_buffer,"%s\\%s", temp_dir, log_file);
}
else
{
sprintf(file_name_buffer,"%s", log_file);
}
#else
sprintf(file_name_buffer,"/tmp/%s", log_file);
Comment on lines +111 to 114
#endif
Expand Down Expand Up @@ -364,7 +389,48 @@ static char* get_context_metadata_element(__itt_context_type type, void* metadat
return metadata_str;
}

#ifdef _WIN32
static char* wchar2char(const wchar_t* wide_str)
{
if (wide_str == NULL)
{
return NULL;
}

int narrow_size = WideCharToMultiByte(CP_UTF8, 0, wide_str, -1, NULL, 0, NULL, NULL);
if (narrow_size <= 0)
{
return NULL;
}

char* narrow_str = (char*)malloc((size_t)narrow_size);
if (narrow_str == NULL)
{
return NULL;
}

if (!WideCharToMultiByte(CP_UTF8, 0, wide_str, -1, narrow_str, narrow_size, NULL, NULL))
{
free(narrow_str);
return NULL;
}

return narrow_str;
}
#endif

#ifdef _WIN32
ITT_EXTERN_C __itt_domain* ITTAPI __itt_domain_createW(const wchar_t *name)
{
char* name_a = wchar2char(name);
__itt_domain* result = __itt_domain_createA(name_a);
free(name_a);
return result;
}
ITT_EXTERN_C __itt_domain* ITTAPI __itt_domain_createA(const char *name)
#else
ITT_EXTERN_C __itt_domain* ITTAPI __itt_domain_create(const char *name)
#endif
{
if (!g_ref_collector_global.mutex_initialized || name == NULL)
{
Expand Down Expand Up @@ -396,7 +462,18 @@ ITT_EXTERN_C __itt_domain* ITTAPI __itt_domain_create(const char *name)
return h;
}

#ifdef _WIN32
ITT_EXTERN_C __itt_string_handle* ITTAPI __itt_string_handle_createW(const wchar_t* name)
{
char* name_a = wchar2char(name);
__itt_string_handle* result = __itt_string_handle_createA(name_a);
free(name_a);
return result;
}
Comment thread
alexey-kireev marked this conversation as resolved.
ITT_EXTERN_C __itt_string_handle* ITTAPI __itt_string_handle_createA(const char* name)
#else
ITT_EXTERN_C __itt_string_handle* ITTAPI __itt_string_handle_create(const char* name)
#endif
{
if (!g_ref_collector_global.mutex_initialized || name == NULL)
{
Expand Down Expand Up @@ -428,21 +505,62 @@ ITT_EXTERN_C __itt_string_handle* ITTAPI __itt_string_handle_create(const char*
return h;
}

#ifdef _WIN32
ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_createW(const wchar_t *name, const wchar_t *domain)
{
char* name_a = wchar2char(name);
char* domain_a = wchar2char(domain);
__itt_counter result = __itt_counter_createA(name_a, domain_a);
free(name_a);
free(domain_a);
return result;
}
Comment thread
alexey-kireev marked this conversation as resolved.
ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_createA(const char *name, const char *domain)
#else
ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_create(const char *name, const char *domain)
#endif
{
LOG_FUNC_CALL_INFO("function call");
return __itt_counter_create_typed(name, domain, __itt_metadata_u64);
}

#ifdef _WIN32
ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_createW_v3(
const __itt_domain* domain, const wchar_t* name, __itt_metadata_type type)
{
char* name_a = wchar2char(name);
__itt_counter result = __itt_counter_create_typed(name_a, domain->nameA, type);
free(name_a);
return result;
}
Comment thread
alexey-kireev marked this conversation as resolved.
Comment on lines +528 to +535
ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_createA_v3(
const __itt_domain* domain, const char* name, __itt_metadata_type type)
#else
ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_create_v3(
const __itt_domain* domain, const char* name, __itt_metadata_type type)
#endif
{
LOG_FUNC_CALL_INFO("function call");
return __itt_counter_create_typed(name, domain->nameA, type);
}

#ifdef _WIN32
ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_create_typedW(
const wchar_t *name, const wchar_t *domain, __itt_metadata_type type)
{
char* name_a = wchar2char(name);
char* domain_a = wchar2char(domain);
__itt_counter result = __itt_counter_create_typedA(name_a, domain_a, type);
free(name_a);
free(domain_a);
return result;
}
Comment thread
alexey-kireev marked this conversation as resolved.
ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_create_typedA(
const char *name, const char *domain, __itt_metadata_type type)
#else
ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_create_typed(
const char *name, const char *domain, __itt_metadata_type type)
#endif
{
if (!g_ref_collector_global.mutex_initialized || name == NULL || domain == NULL)
{
Expand Down Expand Up @@ -478,8 +596,21 @@ ITT_EXTERN_C __itt_counter ITTAPI __itt_counter_create_typed(
return (__itt_counter)h;
}

#ifdef _WIN32
ITT_EXTERN_C __itt_histogram* ITTAPI __itt_histogram_createW(
const __itt_domain* domain, const wchar_t* name, __itt_metadata_type x_type, __itt_metadata_type y_type)
{
char* name_a = wchar2char(name);
__itt_histogram* result = __itt_histogram_createA(domain, name_a, x_type, y_type);
free(name_a);
return result;
}
Comment thread
alexey-kireev marked this conversation as resolved.
ITT_EXTERN_C __itt_histogram* ITTAPI __itt_histogram_createA(
const __itt_domain* domain, const char* name, __itt_metadata_type x_type, __itt_metadata_type y_type)
#else
ITT_EXTERN_C __itt_histogram* ITTAPI __itt_histogram_create(
const __itt_domain* domain, const char* name, __itt_metadata_type x_type, __itt_metadata_type y_type)
#endif
{
if (!g_ref_collector_global.mutex_initialized || name == NULL || domain == NULL)
{
Expand Down
Loading
Loading