Clang-format check for itt collector (#4893)
* Enable clang_format for ITT collector
* Fixed code style
* Bad code style
* Enable clang-format for ITT collector
* Revert "Bad code style"
This reverts commit 82cbd40539
.
* Fixed build
This commit is contained in:
parent
3672fb9817
commit
3ee41375a3
3
.github/workflows/code_style.yml
vendored
3
.github/workflows/code_style.yml
vendored
@ -17,11 +17,12 @@ jobs:
|
||||
sudo apt --assume-yes install libusb-1.0-0-dev
|
||||
python3 -m pip install -r ./inference-engine/ie_bridges/python/requirements.txt
|
||||
|
||||
# Run cmake with -DENABLE_PROFILING_ITT=ON -DSELECTIVE_BUILD=COLLECT in order to enable codestyle check for ITT collector
|
||||
- name: CMake
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake -DENABLE_PROFILING_ITT=ON -DSELECTIVE_BUILD=COLLECT ..
|
||||
|
||||
- name: Check code style
|
||||
run: cmake --build build --target clang_format_check_all
|
||||
|
26
thirdparty/itt_collector/.clang-format
vendored
Normal file
26
thirdparty/itt_collector/.clang-format
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 4
|
||||
UseTab: Never
|
||||
---
|
||||
Language: Cpp
|
||||
Standard: Cpp11
|
||||
|
||||
AccessModifierOffset: -4
|
||||
AlignConsecutiveMacros: true
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: Empty
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
ColumnLimit: 160
|
||||
# Specialize this comment pragma in order to avoid changes in SEA copyrights
|
||||
CommentPragmas: '^#'
|
||||
DerivePointerAlignment: false
|
||||
FixNamespaceComments: true
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: BeforeHash
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: false
|
||||
---
|
@ -35,4 +35,4 @@ elseif(WIN32)
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE Dbghelp)
|
||||
endif()
|
||||
|
||||
add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME})
|
||||
add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME})
|
||||
|
1016
thirdparty/itt_collector/sea_itt_lib/IttNotifyStdSrc.cpp
vendored
1016
thirdparty/itt_collector/sea_itt_lib/IttNotifyStdSrc.cpp
vendored
File diff suppressed because it is too large
Load Diff
@ -25,55 +25,53 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SEA_EXPORT __declspec(dllexport)
|
||||
#define _sprintf sprintf_s
|
||||
#define _sprintf sprintf_s
|
||||
#else
|
||||
#define SEA_EXPORT __attribute__ ((visibility ("default")))
|
||||
#define _sprintf sprintf
|
||||
#define SEA_EXPORT __attribute__((visibility("default")))
|
||||
#define _sprintf sprintf
|
||||
#endif
|
||||
|
||||
namespace sea {
|
||||
bool IsVerboseMode();
|
||||
bool IsVerboseMode();
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define VerbosePrint(...) { \
|
||||
if (sea::IsVerboseMode()) { \
|
||||
std::vector<char> buff(1024); \
|
||||
sprintf_s(buff.data(), 1024, __VA_ARGS__); \
|
||||
OutputDebugStringA(buff.data()); \
|
||||
printf("%s", buff.data()); \
|
||||
} \
|
||||
}
|
||||
#define VerbosePrint(...) \
|
||||
{ \
|
||||
if (sea::IsVerboseMode()) { \
|
||||
std::vector<char> buff(1024); \
|
||||
sprintf_s(buff.data(), 1024, __VA_ARGS__); \
|
||||
OutputDebugStringA(buff.data()); \
|
||||
printf("%s", buff.data()); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define VerbosePrint(...) { \
|
||||
if (sea::IsVerboseMode()) \
|
||||
printf(__VA_ARGS__); \
|
||||
}
|
||||
#define VerbosePrint(...) \
|
||||
{ \
|
||||
if (sea::IsVerboseMode()) \
|
||||
printf(__VA_ARGS__); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "Utils.h"
|
||||
#include "TraceEventFormat.h"
|
||||
#include <Recorder.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "TraceEventFormat.h"
|
||||
#include "Utils.h"
|
||||
|
||||
__itt_global* GetITTGlobal();
|
||||
extern __itt_domain* g_pIntelSEAPIDomain;
|
||||
|
||||
|
||||
namespace sea {
|
||||
extern std::string g_savepath;
|
||||
extern uint64_t g_nAutoCut;
|
||||
#ifdef __linux
|
||||
bool WriteFTraceTimeSyncMarkers(); //For Driver instrumentation see: http://lwn.net/Articles/379903/
|
||||
bool WriteFTraceTimeSyncMarkers(); // For Driver instrumentation see: http://lwn.net/Articles/379903/
|
||||
#endif
|
||||
void InitSEA();
|
||||
void FillApiList(__itt_api_info* pApiInfo);
|
||||
void FinitaLaComedia();
|
||||
void Counter(const __itt_domain *pDomain,
|
||||
__itt_string_handle *pName,
|
||||
double value,
|
||||
__itt_clock_domain* clock_domain = nullptr,
|
||||
void Counter(const __itt_domain* pDomain, __itt_string_handle* pName, double value, __itt_clock_domain* clock_domain = nullptr,
|
||||
unsigned long long timestamp = 0);
|
||||
__itt_clock_domain* clock_domain_create(__itt_get_clock_info_fn fn, void* fn_data);
|
||||
void SetCutName(const std::string& path);
|
||||
@ -91,11 +89,11 @@ std::string GetDir(std::string path, const std::string& append = "");
|
||||
} // namespace sea
|
||||
|
||||
struct SDomainName {
|
||||
__itt_domain *pDomain;
|
||||
__itt_string_handle *pName;
|
||||
__itt_domain* pDomain;
|
||||
__itt_string_handle* pName;
|
||||
};
|
||||
|
||||
struct ___itt_counter : public __itt_counter_info_t{};
|
||||
struct ___itt_counter : public __itt_counter_info_t {};
|
||||
|
||||
#include <string>
|
||||
#define USE_PROBES
|
||||
@ -104,34 +102,34 @@ struct ___itt_counter : public __itt_counter_info_t{};
|
||||
#include "windows.h"
|
||||
#elif defined(__linux__)
|
||||
#ifndef USE_PROBES
|
||||
__thread FILE* stdsrc_trace_info_t::pFile = nullptr;
|
||||
__thread FILE* stdsrc_trace_info_t::pFile = nullptr;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define UNICODE_AGNOSTIC(name) name##A
|
||||
inline std::string W2L(const wchar_t* wstr) {
|
||||
size_t len = lstrlenW(wstr);
|
||||
char* dest = (char*)alloca(len + 2); // NOLINT
|
||||
errno_t err = wcstombs_s(&len, dest, len + 1, wstr, len + 1);
|
||||
return std::string(dest, dest + len);
|
||||
}
|
||||
inline std::string W2L(const wchar_t* wstr) {
|
||||
size_t len = lstrlenW(wstr);
|
||||
char* dest = (char*)alloca(len + 2);
|
||||
errno_t err = wcstombs_s(&len, dest, len + 1, wstr, len + 1);
|
||||
return std::string(dest, dest + len);
|
||||
}
|
||||
|
||||
static_assert(sizeof(__itt_id) == 24, "sizeof(__itt_id) == 24");
|
||||
static_assert(sizeof(GUID) == 16, "sizeof(GUID) == 16");
|
||||
static_assert(sizeof(__itt_id) == 24, "sizeof(__itt_id) == 24");
|
||||
static_assert(sizeof(GUID) == 16, "sizeof(GUID) == 16");
|
||||
|
||||
union IdCaster {
|
||||
__itt_id from; //d3 is not used, so we fit d1 and d2 into 16 bytes
|
||||
GUID to;
|
||||
};
|
||||
union IdCaster {
|
||||
__itt_id from; // d3 is not used, so we fit d1 and d2 into 16 bytes
|
||||
GUID to;
|
||||
};
|
||||
#else
|
||||
#include <cstdio>
|
||||
#define _strdup strdup
|
||||
#define _strdup strdup
|
||||
#define UNICODE_AGNOSTIC(name) name
|
||||
#endif
|
||||
|
||||
namespace sea {
|
||||
__itt_counter UNICODE_AGNOSTIC(counter_create)(const char *name, const char *domain);
|
||||
__itt_counter UNICODE_AGNOSTIC(counter_create)(const char* name, const char* domain);
|
||||
__itt_domain* UNICODE_AGNOSTIC(domain_create)(const char* name);
|
||||
__itt_string_handle* ITTAPI UNICODE_AGNOSTIC(string_handle_create)(const char* name);
|
||||
|
||||
@ -159,8 +157,8 @@ static const size_t MAX_HANDLERS = 10;
|
||||
struct STaskDescriptor {
|
||||
STaskDescriptor* prev;
|
||||
CTraceEventFormat::SRegularFields rf;
|
||||
const __itt_domain *pDomain;
|
||||
const __itt_string_handle *pName;
|
||||
const __itt_domain* pDomain;
|
||||
const __itt_string_handle* pName;
|
||||
__itt_id id;
|
||||
__itt_id parent;
|
||||
void* fn;
|
||||
@ -172,7 +170,7 @@ struct STaskDescriptor {
|
||||
|
||||
#ifdef TURBO_MODE
|
||||
uint64_t nMemCounter;
|
||||
double *pDur;
|
||||
double* pDur;
|
||||
#endif
|
||||
|
||||
~STaskDescriptor() {
|
||||
@ -185,7 +183,6 @@ struct STaskDescriptor {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct IHandler {
|
||||
protected:
|
||||
static bool RegisterHandler(IHandler* pHandler);
|
||||
@ -194,7 +191,7 @@ protected:
|
||||
m_cookie = cookie;
|
||||
}
|
||||
|
||||
template<class T, class ...TArgs>
|
||||
template <class T, class... TArgs>
|
||||
T& Cookie(STaskDescriptor& oTask, TArgs&... args) {
|
||||
if (!oTask.cookies[m_cookie].pCookie) {
|
||||
struct SDeleter {
|
||||
@ -202,20 +199,13 @@ protected:
|
||||
placement_free(reinterpret_cast<T*>(ptr));
|
||||
}
|
||||
};
|
||||
oTask.cookies[m_cookie] = STaskDescriptor::SCookie{placement_new(T)(args...), SDeleter::Deleter}; //consider placement new here!
|
||||
oTask.cookies[m_cookie] = STaskDescriptor::SCookie {placement_new(T)(args...), SDeleter::Deleter}; // consider placement new here!
|
||||
}
|
||||
return *reinterpret_cast<T*>(oTask.cookies[m_cookie].pCookie);
|
||||
}
|
||||
|
||||
const char* GetScope(__itt_scope theScope) {
|
||||
static const char * scopes[] = {
|
||||
"unknown",
|
||||
"global",
|
||||
"track_group",
|
||||
"track",
|
||||
"task",
|
||||
"marker"
|
||||
};
|
||||
static const char* scopes[] = {"unknown", "global", "track_group", "track", "task", "marker"};
|
||||
|
||||
return scopes[theScope];
|
||||
}
|
||||
@ -224,17 +214,17 @@ public:
|
||||
struct SData {
|
||||
CTraceEventFormat::SRegularFields rf;
|
||||
SThreadRecord* pThreadRecord;
|
||||
const __itt_domain *pDomain;
|
||||
const __itt_domain* pDomain;
|
||||
const __itt_id& taskid;
|
||||
const __itt_id& parentid;
|
||||
const __itt_string_handle *pName;
|
||||
const __itt_string_handle* pName;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
template <class T>
|
||||
static T* Register(bool bRegister) {
|
||||
T* pObject = nullptr;
|
||||
#ifndef _DEBUG //register all in debug to discover all problems sooner
|
||||
if (bRegister) //NOLINT
|
||||
#ifndef _DEBUG // register all in debug to discover all problems sooner
|
||||
if (bRegister) // NOLINT
|
||||
#endif
|
||||
{
|
||||
pObject = new T();
|
||||
@ -249,28 +239,25 @@ public:
|
||||
|
||||
virtual void Init(const CTraceEventFormat::SRegularFields& main) {}
|
||||
virtual void TaskBegin(STaskDescriptor& oTask, bool bOverlapped) {}
|
||||
virtual void AddArg(STaskDescriptor& oTask, const __itt_string_handle *pKey, const char *data, size_t length) {}
|
||||
virtual void AddArg(STaskDescriptor& oTask, const __itt_string_handle *pKey, double value) {}
|
||||
virtual void AddRelation(const CTraceEventFormat::SRegularFields& rf,
|
||||
const __itt_domain *pDomain,
|
||||
__itt_id head,
|
||||
__itt_string_handle* relation,
|
||||
virtual void AddArg(STaskDescriptor& oTask, const __itt_string_handle* pKey, const char* data, size_t length) {}
|
||||
virtual void AddArg(STaskDescriptor& oTask, const __itt_string_handle* pKey, double value) {}
|
||||
virtual void AddRelation(const CTraceEventFormat::SRegularFields& rf, const __itt_domain* pDomain, __itt_id head, __itt_string_handle* relation,
|
||||
__itt_id tail) {}
|
||||
virtual void TaskEnd(STaskDescriptor& oTask, const CTraceEventFormat::SRegularFields& rf, bool bOverlapped) {}
|
||||
virtual void Marker(const CTraceEventFormat::SRegularFields& rf, const __itt_domain *pDomain, __itt_id id, __itt_string_handle *pName, __itt_scope scope) {}
|
||||
virtual void Marker(const CTraceEventFormat::SRegularFields& rf, const __itt_domain* pDomain, __itt_id id, __itt_string_handle* pName, __itt_scope scope) {}
|
||||
virtual void CreateCounter(const __itt_counter& id) {}
|
||||
virtual void Counter(const CTraceEventFormat::SRegularFields& rf, const __itt_domain *pDomain, const __itt_string_handle *pName, double value) {}
|
||||
virtual void Counter(const CTraceEventFormat::SRegularFields& rf, const __itt_domain* pDomain, const __itt_string_handle* pName, double value) {}
|
||||
virtual void SetThreadName(const CTraceEventFormat::SRegularFields& rf, const char* name) {}
|
||||
virtual void Alloc(const CTraceEventFormat::SRegularFields& rf, const void* addr, size_t size, const char* domain, const char* name) {}
|
||||
virtual void Free(const CTraceEventFormat::SRegularFields& rf, const void* addr, size_t size, const char* domain, const char* name) {}
|
||||
|
||||
virtual ~IHandler(){}
|
||||
virtual ~IHandler() {}
|
||||
};
|
||||
|
||||
class COverlapped;
|
||||
|
||||
struct SThreadRecord {
|
||||
std::map<std::string/*domain*/, CRecorder> files;
|
||||
std::map<std::string /*domain*/, CRecorder> files;
|
||||
bool bRemoveFiles = false;
|
||||
__itt_track* pTrack = nullptr;
|
||||
SThreadRecord* pNext = nullptr;
|
||||
@ -281,40 +268,45 @@ struct SThreadRecord {
|
||||
const void* pLastDomain = nullptr;
|
||||
int nSpeedupCounter = 0;
|
||||
#ifdef TURBO_MODE
|
||||
uint64_t nMemMoveCounter = 0; //updated every time memory window moves
|
||||
#endif // TURBO_MODE
|
||||
uint64_t nMemMoveCounter = 0; // updated every time memory window moves
|
||||
#endif // TURBO_MODE
|
||||
};
|
||||
|
||||
void TraverseDomains(const std::function<void(___itt_domain&)>& callback);
|
||||
void TraverseThreadRecords(const std::function<void(SThreadRecord&)>& callback);
|
||||
|
||||
|
||||
void InitDomain(__itt_domain* pDomain);
|
||||
|
||||
struct DomainExtra {
|
||||
std::string strDomainPath; //always changed and accessed under lock
|
||||
bool bHasDomainPath = false; //for light check of strDomainPath.empty() without lock
|
||||
SThreadRecord* pThreadRecords = nullptr; //keeping track of thread records for later freeing
|
||||
std::string strDomainPath; // always changed and accessed under lock
|
||||
bool bHasDomainPath = false; // for light check of strDomainPath.empty() without lock
|
||||
SThreadRecord* pThreadRecords = nullptr; // keeping track of thread records for later freeing
|
||||
__itt_clock_domain* pClockDomain = nullptr;
|
||||
__itt_track_group* pTrackGroup = nullptr;
|
||||
};
|
||||
|
||||
SThreadRecord* GetThreadRecord();
|
||||
|
||||
#define CHECKRET(cond, res) {if (!(cond)) {VerbosePrint("Error: !(%s) at %s, %s:(%d)\n", #cond, __FUNCTION__, __FILE__, __LINE__); return res;}}
|
||||
|
||||
#define CHECKRET(cond, res) \
|
||||
{ \
|
||||
if (!(cond)) { \
|
||||
VerbosePrint("Error: !(%s) at %s, %s:(%d)\n", #cond, __FUNCTION__, __FILE__, __LINE__); \
|
||||
return res; \
|
||||
} \
|
||||
}
|
||||
|
||||
class CIttLocker {
|
||||
__itt_global* m_pGlobal = nullptr;
|
||||
|
||||
public:
|
||||
CIttLocker();
|
||||
~CIttLocker();
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
const uint32_t FilePermissions = _S_IWRITE|_S_IWRITE; //read by user, write by user
|
||||
const uint32_t FilePermissions = _S_IWRITE | _S_IWRITE; // read by user, write by user
|
||||
#else
|
||||
const uint32_t FilePermissions = S_IRWXU | S_IRWXG | S_IRWXO; //read by all, write by all
|
||||
const uint32_t FilePermissions = S_IRWXU | S_IRWXG | S_IRWXO; // read by all, write by all
|
||||
#endif
|
||||
|
||||
} //namespace sea
|
||||
} // namespace sea
|
||||
|
407
thirdparty/itt_collector/sea_itt_lib/Recorder.cpp
vendored
407
thirdparty/itt_collector/sea_itt_lib/Recorder.cpp
vendored
@ -16,33 +16,33 @@
|
||||
#
|
||||
**********************************************************************************************************************************************************************************************************************************************************************************************/
|
||||
|
||||
#include "IttNotifyStdSrc.h"
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "IttNotifyStdSrc.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
#define open crossopen
|
||||
#define write _write
|
||||
#define close _close
|
||||
int crossopen(_In_z_ const char * _Filename, _In_ int _Openflag, int perm) {
|
||||
#define open crossopen
|
||||
#define write _write
|
||||
#define close _close
|
||||
int crossopen(_In_z_ const char* _Filename, _In_ int _Openflag, int perm) {
|
||||
int fd = 0;
|
||||
_sopen_s(&fd, _Filename, _Openflag|_O_BINARY, _SH_DENYWR, perm);
|
||||
_sopen_s(&fd, _Filename, _Openflag | _O_BINARY, _SH_DENYWR, perm);
|
||||
return fd;
|
||||
}
|
||||
//FIXME: support wide char mode
|
||||
// FIXME: support wide char mode
|
||||
#endif
|
||||
|
||||
CRecorder::CRecorder()
|
||||
: m_pCurPos(nullptr) {}
|
||||
CRecorder::CRecorder(): m_pCurPos(nullptr) {}
|
||||
|
||||
size_t ChunkSize = 1*1020*1024;
|
||||
size_t ChunkSize = 1 * 1020 * 1024;
|
||||
|
||||
bool CRecorder::Init(const std::string& path, uint64_t time, void* pCut) {
|
||||
Close(true);
|
||||
@ -62,12 +62,12 @@ bool CRecorder::Init(const std::string& path, uint64_t time, void* pCut) {
|
||||
|
||||
size_t CRecorder::CheckCapacity(size_t size) {
|
||||
#ifdef IN_MEMORY_RING
|
||||
size_t nWroteBytes = (char*)m_pCurPos - (char*)m_pAlloc; // NOLINT
|
||||
size_t nWroteBytes = (char*)m_pCurPos - (char*)m_pAlloc;
|
||||
if (nWroteBytes + size > m_nBufferSize) {
|
||||
if (m_pBackBuffer)
|
||||
VirtualFree(m_pBackBuffer, 0, MEM_RELEASE);
|
||||
m_nBufferSize *= 2; //We grow the buffer each time to accommodate needs
|
||||
m_pBackBuffer = m_pAlloc; //back buffer will always be half of m_nBufferSize
|
||||
m_nBufferSize *= 2; // We grow the buffer each time to accommodate needs
|
||||
m_pBackBuffer = m_pAlloc; // back buffer will always be half of m_nBufferSize
|
||||
m_nBackSize = nWroteBytes;
|
||||
m_pCurPos = m_pAlloc = VirtualAlloc(nullptr, m_nBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
sea::GetThreadRecord()->nMemMoveCounter += 1;
|
||||
@ -77,12 +77,12 @@ size_t CRecorder::CheckCapacity(size_t size) {
|
||||
#else
|
||||
if (!m_memmap)
|
||||
return 0;
|
||||
size_t nWroteBytes = (char*)m_pCurPos - (char*)m_memmap->GetPtr(); // NOLINT
|
||||
size_t nWroteBytes = (char*)m_pCurPos - (char*)m_memmap->GetPtr();
|
||||
if (nWroteBytes + size > m_memmap->GetSize()) {
|
||||
m_pCurPos = m_memmap->Remap((std::max)(ChunkSize, size), m_nWroteTotal);
|
||||
#ifdef TURBO_MODE
|
||||
#ifdef TURBO_MODE
|
||||
sea::GetThreadRecord()->nMemMoveCounter += 1;
|
||||
#endif
|
||||
#endif
|
||||
if (!m_pCurPos)
|
||||
return 0;
|
||||
}
|
||||
@ -91,10 +91,10 @@ size_t CRecorder::CheckCapacity(size_t size) {
|
||||
}
|
||||
|
||||
void* CRecorder::Allocate(size_t size) {
|
||||
//must be called only from one thread
|
||||
void * pCurPos = m_pCurPos;
|
||||
// must be called only from one thread
|
||||
void* pCurPos = m_pCurPos;
|
||||
m_nWroteTotal += size;
|
||||
m_pCurPos = (char*)m_pCurPos + size; // NOLINT
|
||||
m_pCurPos = (char*)m_pCurPos + size;
|
||||
return pCurPos;
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ void CRecorder::Close(bool bSave) {
|
||||
if (m_pBackBuffer)
|
||||
res = write(fd, m_pBackBuffer, uint32_t(m_nBackSize));
|
||||
if (m_pAlloc)
|
||||
res = write(fd, m_pAlloc, uint32_t((char*)m_pCurPos - (char*)m_pAlloc)); // NOLINT
|
||||
res = write(fd, m_pAlloc, uint32_t((char*)m_pCurPos - (char*)m_pAlloc));
|
||||
close(fd);
|
||||
}
|
||||
if (m_pBackBuffer)
|
||||
@ -117,11 +117,11 @@ void CRecorder::Close(bool bSave) {
|
||||
if (m_pAlloc)
|
||||
VirtualFree(m_pAlloc, 0, MEM_RELEASE);
|
||||
m_pBackBuffer = m_pAlloc = nullptr;
|
||||
#else // IN_MEMORY_RING
|
||||
#else // IN_MEMORY_RING
|
||||
if (m_memmap)
|
||||
m_memmap->Resize(m_nWroteTotal);
|
||||
m_memmap.reset();
|
||||
#endif // IN_MEMORY_RING
|
||||
#endif // IN_MEMORY_RING
|
||||
m_pCurPos = nullptr;
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ CRecorder::~CRecorder() {
|
||||
Close(true);
|
||||
}
|
||||
|
||||
static_assert(sizeof(__itt_id) == 3*8, "sizeof(__itt_id) must be 3*8");
|
||||
static_assert(sizeof(__itt_id) == 3 * 8, "sizeof(__itt_id) must be 3*8");
|
||||
static_assert(sizeof(CTraceEventFormat::SRegularFields().tid) == 8, "sizeof(tid) must be 8");
|
||||
|
||||
enum EFlags {
|
||||
@ -144,19 +144,19 @@ enum EFlags {
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
//File tree is pid/domain/tid (pid is one per dll instance)
|
||||
// File tree is pid/domain/tid (pid is one per dll instance)
|
||||
struct STinyRecord {
|
||||
uint64_t timestamp;
|
||||
ERecordType ert;
|
||||
uint8_t flags; //EFlags
|
||||
uint8_t flags; // EFlags
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static_assert(sizeof(STinyRecord) == 10, "SRecord must fit in 10 bytes");
|
||||
|
||||
template<class T>
|
||||
template <class T>
|
||||
inline T* WriteToBuff(CRecorder& recorder, const T& value) {
|
||||
T* ptr = (T*)recorder.Allocate(sizeof(T)); // NOLINT
|
||||
T* ptr = (T*)recorder.Allocate(sizeof(T));
|
||||
if (ptr)
|
||||
*ptr = value;
|
||||
return ptr;
|
||||
@ -164,104 +164,105 @@ inline T* WriteToBuff(CRecorder& recorder, const T& value) {
|
||||
|
||||
namespace sea {
|
||||
|
||||
extern int64_t g_nRingBuffer;
|
||||
extern int64_t g_nRingBuffer;
|
||||
|
||||
extern std::shared_ptr<std::string> g_spCutName;
|
||||
extern std::shared_ptr<std::string> g_spCutName;
|
||||
|
||||
inline CRecorder* GetFile(const SRecord& record) {
|
||||
DomainExtra* pDomainExtra = reinterpret_cast<DomainExtra*>(record.domain.extra2);
|
||||
if (!pDomainExtra || !pDomainExtra->bHasDomainPath)
|
||||
return nullptr;
|
||||
inline CRecorder* GetFile(const SRecord& record) {
|
||||
DomainExtra* pDomainExtra = reinterpret_cast<DomainExtra*>(record.domain.extra2);
|
||||
if (!pDomainExtra || !pDomainExtra->bHasDomainPath)
|
||||
return nullptr;
|
||||
|
||||
static thread_local SThreadRecord* pThreadRecord = nullptr;
|
||||
if (!pThreadRecord)
|
||||
pThreadRecord = GetThreadRecord();
|
||||
static thread_local SThreadRecord* pThreadRecord = nullptr;
|
||||
if (!pThreadRecord)
|
||||
pThreadRecord = GetThreadRecord();
|
||||
|
||||
if (pThreadRecord->bRemoveFiles) {
|
||||
pThreadRecord->pLastRecorder = nullptr;
|
||||
pThreadRecord->pLastDomain = nullptr;
|
||||
pThreadRecord->bRemoveFiles = false;
|
||||
pThreadRecord->files.clear();
|
||||
if (pThreadRecord->bRemoveFiles) {
|
||||
pThreadRecord->pLastRecorder = nullptr;
|
||||
pThreadRecord->pLastDomain = nullptr;
|
||||
pThreadRecord->bRemoveFiles = false;
|
||||
pThreadRecord->files.clear();
|
||||
}
|
||||
// with very high probability the same thread will write into the same domain
|
||||
if (pThreadRecord->pLastRecorder && (pThreadRecord->pLastDomain == record.domain.nameA) && (100 > pThreadRecord->nSpeedupCounter++))
|
||||
return reinterpret_cast<CRecorder*>(pThreadRecord->pLastRecorder);
|
||||
pThreadRecord->nSpeedupCounter = 0; // we can't avoid checking ring size
|
||||
pThreadRecord->pLastDomain = record.domain.nameA;
|
||||
|
||||
auto it = pThreadRecord->files.find(record.domain.nameA);
|
||||
CRecorder* pRecorder = nullptr;
|
||||
if (it != pThreadRecord->files.end()) {
|
||||
pRecorder = &it->second;
|
||||
int64_t diff = record.rf.nanoseconds - pRecorder->GetCreationTime(); // timestamp can be in the past, it's ok
|
||||
// just checking pointer of g_spCutName.get() is thread safe without any locks: we don't access internals.
|
||||
// And if it's the same we work with the old path.
|
||||
// but if it's changed we will lock and access the value below
|
||||
bool bSameCut = pRecorder->SameCut(g_spCutName.get());
|
||||
if (bSameCut && (!g_nRingBuffer || (diff < g_nRingBuffer))) {
|
||||
pThreadRecord->pLastRecorder = pRecorder;
|
||||
return pRecorder; // normal flow
|
||||
}
|
||||
//with very high probability the same thread will write into the same domain
|
||||
if (pThreadRecord->pLastRecorder && (pThreadRecord->pLastDomain == record.domain.nameA) && (100 > pThreadRecord->nSpeedupCounter++))
|
||||
return reinterpret_cast<CRecorder*>(pThreadRecord->pLastRecorder);
|
||||
pThreadRecord->nSpeedupCounter = 0; //we can't avoid checking ring size
|
||||
pThreadRecord->pLastDomain = record.domain.nameA;
|
||||
pRecorder->Close(!bSameCut); // time to create new file
|
||||
}
|
||||
|
||||
auto it = pThreadRecord->files.find(record.domain.nameA);
|
||||
CRecorder* pRecorder = nullptr;
|
||||
if (it != pThreadRecord->files.end()) {
|
||||
pRecorder = &it->second;
|
||||
int64_t diff = record.rf.nanoseconds - pRecorder->GetCreationTime(); //timestamp can be in the past, it's ok
|
||||
// just checking pointer of g_spCutName.get() is thread safe without any locks: we don't access internals.
|
||||
// And if it's the same we work with the old path.
|
||||
// but if it's changed we will lock and access the value below
|
||||
bool bSameCut = pRecorder->SameCut(g_spCutName.get());
|
||||
if (bSameCut && (!g_nRingBuffer || (diff < g_nRingBuffer))) {
|
||||
pThreadRecord->pLastRecorder = pRecorder;
|
||||
return pRecorder; //normal flow
|
||||
}
|
||||
pRecorder->Close(!bSameCut); //time to create new file
|
||||
}
|
||||
if (!pRecorder) {
|
||||
pRecorder = &pThreadRecord->files[record.domain.nameA];
|
||||
}
|
||||
CIttLocker lock; // locking only on file creation
|
||||
// this is theoretically possible because we check pDomainExtra->bHasDomainPath without lock above
|
||||
if (pDomainExtra->strDomainPath.empty()) {
|
||||
pThreadRecord->pLastRecorder = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
std::shared_ptr<std::string> spCutName = g_spCutName;
|
||||
|
||||
if (!pRecorder) {
|
||||
pRecorder = &pThreadRecord->files[record.domain.nameA];
|
||||
}
|
||||
CIttLocker lock; //locking only on file creation
|
||||
//this is theoretically possible because we check pDomainExtra->bHasDomainPath without lock above
|
||||
if (pDomainExtra->strDomainPath.empty()) {
|
||||
pThreadRecord->pLastRecorder = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
std::shared_ptr<std::string> spCutName = g_spCutName;
|
||||
|
||||
CTraceEventFormat::SRegularFields rf = CTraceEventFormat::GetRegularFields();
|
||||
char path[1024] = {};
|
||||
_sprintf(path, "%s%llu%s%s.sea",
|
||||
pDomainExtra->strDomainPath.c_str(),
|
||||
(unsigned long long)rf.tid,
|
||||
spCutName ? (std::string("!") + *spCutName).c_str() : "",
|
||||
(g_nRingBuffer ? ((pRecorder->GetCount() % 2) ? "-1" : "-0") : ""));
|
||||
try {
|
||||
VerbosePrint("Opening: %s\n", path);
|
||||
if (!pRecorder->Init(path, rf.nanoseconds, spCutName.get())) {
|
||||
VerbosePrint("Failed to init recorder\n");
|
||||
pThreadRecord->files.erase(record.domain.nameA);
|
||||
pRecorder = nullptr;
|
||||
}
|
||||
} catch (const std::exception& exc) {
|
||||
VerbosePrint("Exception: %s\n", exc.what());
|
||||
CTraceEventFormat::SRegularFields rf = CTraceEventFormat::GetRegularFields();
|
||||
char path[1024] = {};
|
||||
_sprintf(path, "%s%llu%s%s.sea", pDomainExtra->strDomainPath.c_str(), (unsigned long long)rf.tid, spCutName ? (std::string("!") + *spCutName).c_str() : "",
|
||||
(g_nRingBuffer ? ((pRecorder->GetCount() % 2) ? "-1" : "-0") : ""));
|
||||
try {
|
||||
VerbosePrint("Opening: %s\n", path);
|
||||
if (!pRecorder->Init(path, rf.nanoseconds, spCutName.get())) {
|
||||
VerbosePrint("Failed to init recorder\n");
|
||||
pThreadRecord->files.erase(record.domain.nameA);
|
||||
pRecorder = nullptr;
|
||||
}
|
||||
pThreadRecord->pLastRecorder = pRecorder;
|
||||
return pRecorder;
|
||||
} catch (const std::exception& exc) {
|
||||
VerbosePrint("Exception: %s\n", exc.what());
|
||||
pThreadRecord->files.erase(record.domain.nameA);
|
||||
pRecorder = nullptr;
|
||||
}
|
||||
pThreadRecord->pLastRecorder = pRecorder;
|
||||
return pRecorder;
|
||||
}
|
||||
} // namespace sea
|
||||
|
||||
double* WriteRecord(ERecordType type, const SRecord& record) {
|
||||
CRecorder* pFile = sea::GetFile(record);
|
||||
if (!pFile) return nullptr;
|
||||
if (!pFile)
|
||||
return nullptr;
|
||||
|
||||
CRecorder& stream = *pFile;
|
||||
|
||||
const size_t MaxSize = sizeof(STinyRecord) + 2*sizeof(__itt_id) + 3*sizeof(uint64_t) + sizeof(double) + sizeof(void*);
|
||||
const size_t MaxSize = sizeof(STinyRecord) + 2 * sizeof(__itt_id) + 3 * sizeof(uint64_t) + sizeof(double) + sizeof(void*);
|
||||
size_t size = stream.CheckCapacity(MaxSize + record.length);
|
||||
if (!size)
|
||||
return nullptr;
|
||||
|
||||
STinyRecord* pRecord = WriteToBuff(stream, STinyRecord{record.rf.nanoseconds, type});
|
||||
if (!pRecord) return nullptr;
|
||||
STinyRecord* pRecord = WriteToBuff(stream, STinyRecord {record.rf.nanoseconds, type});
|
||||
if (!pRecord)
|
||||
return nullptr;
|
||||
|
||||
struct ShortId { unsigned long long a, b; };
|
||||
struct ShortId {
|
||||
unsigned long long a, b;
|
||||
};
|
||||
if (record.taskid.d1) {
|
||||
WriteToBuff(stream, *(ShortId*)&record.taskid); // NOLINT
|
||||
WriteToBuff(stream, *(ShortId*)&record.taskid);
|
||||
pRecord->flags |= efHasId;
|
||||
}
|
||||
|
||||
if (record.parentid.d1) {
|
||||
WriteToBuff(stream, *(ShortId*)&record.parentid); // NOLINT
|
||||
WriteToBuff(stream, *(ShortId*)&record.parentid);
|
||||
pRecord->flags |= efHasParent;
|
||||
}
|
||||
|
||||
@ -308,16 +309,16 @@ double* WriteRecord(ERecordType type, const SRecord& record) {
|
||||
return pDelta;
|
||||
}
|
||||
|
||||
CMemMap::CMemMap(const std::string &path, size_t size, size_t offset) {
|
||||
CMemMap::CMemMap(const std::string& path, size_t size, size_t offset) {
|
||||
#ifdef _WIN32
|
||||
m_hFile = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||
m_hFile = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_SEQUENTIAL_SCAN,
|
||||
NULL);
|
||||
if (INVALID_HANDLE_VALUE == m_hFile) {
|
||||
m_hFile = NULL;
|
||||
throw std::runtime_error("Failed to open file: " + path + " err=" + std::to_string(GetLastError()));
|
||||
}
|
||||
#else
|
||||
m_fdin = open(path.c_str(), O_CREAT|O_TRUNC|O_RDWR, sea::FilePermissions);
|
||||
m_fdin = open(path.c_str(), O_CREAT | O_TRUNC | O_RDWR, sea::FilePermissions);
|
||||
if (-1 == m_fdin) {
|
||||
m_fdin = 0;
|
||||
throw std::runtime_error("Failed to open file: " + path + " err=" + std::to_string(errno));
|
||||
@ -329,7 +330,7 @@ CMemMap::CMemMap(const std::string &path, size_t size, size_t offset) {
|
||||
void* CMemMap::Remap(size_t size, size_t offset) {
|
||||
Resize(size + offset);
|
||||
static const size_t PageSize = GetMemPageSize();
|
||||
size_t nRoundOffset = offset / PageSize * PageSize; //align by memory page size
|
||||
size_t nRoundOffset = offset / PageSize * PageSize; // align by memory page size
|
||||
m_size = size + offset % PageSize;
|
||||
#ifdef _WIN32
|
||||
m_hMapping = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
|
||||
@ -337,12 +338,12 @@ void* CMemMap::Remap(size_t size, size_t offset) {
|
||||
uliOffset.QuadPart = nRoundOffset;
|
||||
m_pView = ::MapViewOfFile(m_hMapping, FILE_MAP_WRITE, uliOffset.HighPart, uliOffset.LowPart, m_size);
|
||||
#else
|
||||
m_pView = mmap(0, m_size, PROT_READ|PROT_WRITE, MAP_SHARED, m_fdin, nRoundOffset);
|
||||
m_pView = mmap(0, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fdin, nRoundOffset);
|
||||
if (m_pView == MAP_FAILED)
|
||||
throw std::runtime_error("Failed to map file: err=" + std::to_string(errno));
|
||||
|
||||
#endif
|
||||
return (char*)m_pView + offset % PageSize; // NOLINT
|
||||
return (char*)m_pView + offset % PageSize;
|
||||
}
|
||||
|
||||
void CMemMap::Unmap() {
|
||||
@ -366,7 +367,7 @@ void CMemMap::Unmap() {
|
||||
bool CMemMap::Resize(size_t size) {
|
||||
Unmap();
|
||||
#ifdef _WIN32
|
||||
//resize
|
||||
// resize
|
||||
LARGE_INTEGER liSize = {};
|
||||
liSize.QuadPart = size;
|
||||
return SetFilePointerEx(m_hFile, liSize, nullptr, FILE_BEGIN) && ::SetEndOfFile(m_hFile);
|
||||
@ -394,115 +395,106 @@ CMemMap::~CMemMap() {
|
||||
using namespace sea;
|
||||
const bool g_bWithStacks = !!(GetFeatureSet() & sfStack);
|
||||
|
||||
|
||||
void WriteMeta(const CTraceEventFormat::SRegularFields& main, __itt_string_handle* pKey, const char* name, double* pDelta) {
|
||||
WriteRecord(ERecordType::Metadata, SRecord{ main, *g_pIntelSEAPIDomain, __itt_null, __itt_null, pKey, pDelta, name, strlen(name) });
|
||||
WriteRecord(ERecordType::Metadata, SRecord {main, *g_pIntelSEAPIDomain, __itt_null, __itt_null, pKey, pDelta, name, strlen(name)});
|
||||
}
|
||||
|
||||
class CSEARecorder : public IHandler {void Init(const CTraceEventFormat::SRegularFields& main)
|
||||
override {// write process name into trace
|
||||
__itt_string_handle* pKey = UNICODE_AGNOSTIC(string_handle_create)("__process__");
|
||||
const char* name = GetProcessName(true);
|
||||
|
||||
class CSEARecorder: public IHandler {
|
||||
void Init(const CTraceEventFormat::SRegularFields& main) override {
|
||||
//write process name into trace
|
||||
__itt_string_handle* pKey = UNICODE_AGNOSTIC(string_handle_create)("__process__");
|
||||
const char * name = GetProcessName(true);
|
||||
double delta = -1; // sort order - highest for processes written thru SEA
|
||||
WriteMeta(main, pKey, name, &delta);
|
||||
|
||||
double delta = -1;//sort order - highest for processes written thru SEA
|
||||
WriteMeta(main, pKey, name, &delta);
|
||||
|
||||
if (!g_savepath.empty()) {
|
||||
std::ofstream ss(GetDir(g_savepath) + "process.dct");
|
||||
ss << "{";
|
||||
ss << "'time_freq':" << GetTimeFreq();
|
||||
if (!g_savepath.empty()) {
|
||||
std::ofstream ss(GetDir(g_savepath) + "process.dct");
|
||||
ss << "{";
|
||||
ss << "'time_freq':" << GetTimeFreq();
|
||||
#if INTPTR_MAX == INT64_MAX
|
||||
ss << ", 'bits':64";
|
||||
ss << ", 'bits':64";
|
||||
#else
|
||||
ss << ", 'bits':32";
|
||||
ss << ", 'bits':32";
|
||||
#endif
|
||||
ss << "}";
|
||||
}
|
||||
}
|
||||
ss << "}";
|
||||
}
|
||||
}
|
||||
|
||||
void TaskBegin(STaskDescriptor& oTask, bool bOverlapped) override {
|
||||
const char *pData = nullptr;
|
||||
size_t length = 0;
|
||||
if (g_bWithStacks) {
|
||||
static thread_local TStack* pStack = nullptr;
|
||||
if (!pStack)
|
||||
pStack = (TStack*)malloc(sizeof(TStack)); // NOLINT
|
||||
length = (GetStack(*pStack) - 2) * sizeof(void*);
|
||||
pData = reinterpret_cast<const char *>(&(*pStack)[2]);
|
||||
}
|
||||
void TaskBegin(STaskDescriptor& oTask, bool bOverlapped) override {
|
||||
const char* pData = nullptr;
|
||||
size_t length = 0;
|
||||
if (g_bWithStacks) {
|
||||
static thread_local TStack* pStack = nullptr;
|
||||
if (!pStack)
|
||||
pStack = (TStack*)malloc(sizeof(TStack));
|
||||
length = (GetStack(*pStack) - 2) * sizeof(void*);
|
||||
pData = reinterpret_cast<const char*>(&(*pStack)[2]);
|
||||
}
|
||||
#ifdef TURBO_MODE
|
||||
double duration = 0;
|
||||
oTask.pDur = WriteRecord(bOverlapped ? ERecordType::BeginOverlappedTask : ERecordType::BeginTask, SRecord {
|
||||
oTask.rf, *oTask.pDomain, oTask.id, oTask.parent, oTask.pName, &duration, pData, length, oTask.fn });
|
||||
oTask.nMemCounter = GetThreadRecord()->nMemMoveCounter;
|
||||
double duration = 0;
|
||||
oTask.pDur = WriteRecord(bOverlapped ? ERecordType::BeginOverlappedTask : ERecordType::BeginTask,
|
||||
SRecord {oTask.rf, *oTask.pDomain, oTask.id, oTask.parent, oTask.pName, &duration, pData, length, oTask.fn});
|
||||
oTask.nMemCounter = GetThreadRecord()->nMemMoveCounter;
|
||||
#else
|
||||
WriteRecord(bOverlapped ? ERecordType::BeginOverlappedTask : ERecordType::BeginTask, SRecord {
|
||||
oTask.rf, *oTask.pDomain, oTask.id, oTask.parent, oTask.pName, nullptr, pData, length, oTask.fn });
|
||||
WriteRecord(bOverlapped ? ERecordType::BeginOverlappedTask : ERecordType::BeginTask,
|
||||
SRecord {oTask.rf, *oTask.pDomain, oTask.id, oTask.parent, oTask.pName, nullptr, pData, length, oTask.fn});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AddArg(STaskDescriptor& oTask, const __itt_string_handle *pKey, const char *data, size_t length) override {
|
||||
WriteRecord(ERecordType::Metadata, SRecord{oTask.rf, *oTask.pDomain, oTask.id, __itt_null, pKey, nullptr, data, length});
|
||||
void AddArg(STaskDescriptor& oTask, const __itt_string_handle* pKey, const char* data, size_t length) override {
|
||||
WriteRecord(ERecordType::Metadata, SRecord {oTask.rf, *oTask.pDomain, oTask.id, __itt_null, pKey, nullptr, data, length});
|
||||
#ifdef TURBO_MODE
|
||||
oTask.pDur = nullptr; //for now we don't support turbo tasks with arguments. But if count of arguments was saved it could work.
|
||||
oTask.pDur = nullptr; // for now we don't support turbo tasks with arguments. But if count of arguments was saved it could work.
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AddArg(STaskDescriptor& oTask, const __itt_string_handle *pKey, double value) override {
|
||||
WriteRecord(ERecordType::Metadata, SRecord{ oTask.rf, *oTask.pDomain, oTask.id, __itt_null, pKey, &value});
|
||||
void AddArg(STaskDescriptor& oTask, const __itt_string_handle* pKey, double value) override {
|
||||
WriteRecord(ERecordType::Metadata, SRecord {oTask.rf, *oTask.pDomain, oTask.id, __itt_null, pKey, &value});
|
||||
#ifdef TURBO_MODE
|
||||
oTask.pDur = nullptr; //for now we don't support turbo tasks with arguments. But if count of arguments was saved it could work.
|
||||
oTask.pDur = nullptr; // for now we don't support turbo tasks with arguments. But if count of arguments was saved it could work.
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AddRelation(const CTraceEventFormat::SRegularFields& rf,
|
||||
const __itt_domain *pDomain,
|
||||
__itt_id head,
|
||||
__itt_string_handle* relation,
|
||||
__itt_id tail) override {
|
||||
WriteRecord(ERecordType::Relation, SRecord{ rf, *pDomain, head, tail, relation});
|
||||
}
|
||||
void AddRelation(const CTraceEventFormat::SRegularFields& rf, const __itt_domain* pDomain, __itt_id head, __itt_string_handle* relation,
|
||||
__itt_id tail) override {
|
||||
WriteRecord(ERecordType::Relation, SRecord {rf, *pDomain, head, tail, relation});
|
||||
}
|
||||
|
||||
void TaskEnd(STaskDescriptor& oTask, const CTraceEventFormat::SRegularFields& rf, bool bOverlapped) override {
|
||||
void TaskEnd(STaskDescriptor& oTask, const CTraceEventFormat::SRegularFields& rf, bool bOverlapped) override {
|
||||
#ifdef TURBO_MODE
|
||||
if (oTask.pDur && (oTask.nMemCounter == GetThreadRecord()->nMemMoveCounter))
|
||||
*oTask.pDur = double(rf.nanoseconds - oTask.rf.nanoseconds); // NOLINT
|
||||
else
|
||||
WriteRecord(bOverlapped ? ERecordType::EndOverlappedTask : ERecordType::EndTask, SRecord {
|
||||
rf, *oTask.pDomain, oTask.id, oTask.parent, oTask.pName, nullptr, nullptr, 0, oTask.fn });
|
||||
if (oTask.pDur && (oTask.nMemCounter == GetThreadRecord()->nMemMoveCounter))
|
||||
*oTask.pDur = double(rf.nanoseconds - oTask.rf.nanoseconds);
|
||||
else
|
||||
WriteRecord(bOverlapped ? ERecordType::EndOverlappedTask : ERecordType::EndTask,
|
||||
SRecord {rf, *oTask.pDomain, oTask.id, oTask.parent, oTask.pName, nullptr, nullptr, 0, oTask.fn});
|
||||
#else
|
||||
WriteRecord(bOverlapped ? ERecordType::EndOverlappedTask : ERecordType::EndTask, SRecord{rf, *oTask.pDomain, oTask.id, __itt_null});
|
||||
WriteRecord(bOverlapped ? ERecordType::EndOverlappedTask : ERecordType::EndTask, SRecord {rf, *oTask.pDomain, oTask.id, __itt_null});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Marker(const CTraceEventFormat::SRegularFields& rf,
|
||||
const __itt_domain *pDomain,
|
||||
__itt_id id,
|
||||
__itt_string_handle *pName,
|
||||
__itt_scope theScope) override {
|
||||
const char* scope = GetScope(theScope);
|
||||
WriteRecord(ERecordType::Marker, SRecord{rf, *pDomain, id, __itt_null, pName, nullptr, scope, strlen(scope)});
|
||||
}
|
||||
void Marker(const CTraceEventFormat::SRegularFields& rf, const __itt_domain* pDomain, __itt_id id, __itt_string_handle* pName, __itt_scope theScope) override {
|
||||
const char* scope = GetScope(theScope);
|
||||
WriteRecord(ERecordType::Marker, SRecord {rf, *pDomain, id, __itt_null, pName, nullptr, scope, strlen(scope)});
|
||||
}
|
||||
|
||||
void Counter(const CTraceEventFormat::SRegularFields& rf, const __itt_domain *pDomain, const __itt_string_handle *pName, double value) override {
|
||||
const char *pData = nullptr;
|
||||
size_t length = 0;
|
||||
if (g_bWithStacks) {
|
||||
static thread_local TStack* pStack = nullptr;
|
||||
if (!pStack)
|
||||
pStack = (TStack*)malloc(sizeof(TStack)); // NOLINT
|
||||
length = (GetStack(*pStack) - 3) * sizeof(void*);
|
||||
pData = reinterpret_cast<const char *>(&(*pStack)[3]);
|
||||
}
|
||||
WriteRecord(ERecordType::Counter, SRecord{rf, *pDomain, __itt_null, __itt_null, pName, &value, pData, length});
|
||||
void Counter(const CTraceEventFormat::SRegularFields& rf, const __itt_domain* pDomain, const __itt_string_handle* pName, double value) override {
|
||||
const char* pData = nullptr;
|
||||
size_t length = 0;
|
||||
if (g_bWithStacks) {
|
||||
static thread_local TStack* pStack = nullptr;
|
||||
if (!pStack)
|
||||
pStack = (TStack*)malloc(sizeof(TStack));
|
||||
length = (GetStack(*pStack) - 3) * sizeof(void*);
|
||||
pData = reinterpret_cast<const char*>(&(*pStack)[3]);
|
||||
}
|
||||
WriteRecord(ERecordType::Counter, SRecord {rf, *pDomain, __itt_null, __itt_null, pName, &value, pData, length});
|
||||
}
|
||||
|
||||
void SetThreadName(const CTraceEventFormat::SRegularFields& rf, const char* name) override {
|
||||
WriteThreadName(rf, name);
|
||||
}
|
||||
}* g_pSEARecorder = IHandler::Register<CSEARecorder>(true);
|
||||
void SetThreadName(const CTraceEventFormat::SRegularFields& rf, const char* name) override {
|
||||
WriteThreadName(rf, name);
|
||||
}
|
||||
}
|
||||
*g_pSEARecorder = IHandler::Register<CSEARecorder>(true);
|
||||
|
||||
IHandler& GetSEARecorder() {
|
||||
return *g_pSEARecorder;
|
||||
@ -512,33 +504,39 @@ namespace sea {
|
||||
|
||||
bool WriteThreadName(const CTraceEventFormat::SRegularFields& rf, const char* name) {
|
||||
CIttLocker lock;
|
||||
if (g_savepath.empty()) return true;
|
||||
if (g_savepath.empty())
|
||||
return true;
|
||||
std::string path = g_savepath + "/";
|
||||
path += std::to_string(rf.pid) + "," + std::to_string(rf.tid) + ".tid";
|
||||
int fd = open(path.c_str(), O_WRONLY|O_CREAT|O_EXCL, FilePermissions);
|
||||
if (-1 == fd) return true; //file already exists, other thread was faster
|
||||
int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_EXCL, FilePermissions);
|
||||
if (-1 == fd)
|
||||
return true; // file already exists, other thread was faster
|
||||
int res = write(fd, name, (unsigned int)strlen(name));
|
||||
close(fd);
|
||||
return res != -1;
|
||||
}
|
||||
|
||||
bool WriteGroupName(int64_t pid, const char* name) {
|
||||
if (g_savepath.empty()) return true;
|
||||
if (g_savepath.empty())
|
||||
return true;
|
||||
std::string path = g_savepath + "/";
|
||||
path += std::to_string(pid) + ".pid";
|
||||
int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_EXCL, FilePermissions);
|
||||
if (-1 == fd) return true; //file already exists, other thread was faster
|
||||
if (-1 == fd)
|
||||
return true; // file already exists, other thread was faster
|
||||
int res = write(fd, name, (unsigned int)strlen(name));
|
||||
close(fd);
|
||||
return res != -1;
|
||||
}
|
||||
|
||||
bool ReportString(__itt_string_handle* pStr) {
|
||||
if (g_savepath.empty()) return true;
|
||||
if (g_savepath.empty())
|
||||
return true;
|
||||
std::string path = g_savepath + "/";
|
||||
path += std::to_string((uint64_t)pStr) + ".str";
|
||||
int fd = open(path.c_str(), O_WRONLY|O_CREAT|O_EXCL, FilePermissions);
|
||||
if (-1 == fd) return true; //file already exists, other thread was faster
|
||||
int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_EXCL, FilePermissions);
|
||||
if (-1 == fd)
|
||||
return true; // file already exists, other thread was faster
|
||||
int res = write(fd, pStr->strA, (unsigned int)strlen(pStr->strA));
|
||||
close(fd);
|
||||
return res != -1;
|
||||
@ -551,8 +549,9 @@ bool ReportModule(void* fn) {
|
||||
SModuleInfo module_info = Fn2Mdl(fn);
|
||||
|
||||
std::string path = GetDir(g_savepath) + std::to_string((uint64_t)module_info.base) + ".mdl";
|
||||
int fd = open(path.c_str(), O_WRONLY|O_CREAT|O_EXCL, FilePermissions);
|
||||
if (-1 == fd) return true; //file already exists
|
||||
int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_EXCL, FilePermissions);
|
||||
if (-1 == fd)
|
||||
return true; // file already exists
|
||||
std::string text = module_info.path + " " + std::to_string(module_info.size);
|
||||
int res = write(fd, text.c_str(), (unsigned int)text.size());
|
||||
close(fd);
|
||||
@ -586,4 +585,4 @@ bool WriteMemStat(const void* buff, size_t size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} //namespace sea
|
||||
} // namespace sea
|
||||
|
51
thirdparty/itt_collector/sea_itt_lib/Recorder.h
vendored
51
thirdparty/itt_collector/sea_itt_lib/Recorder.h
vendored
@ -23,15 +23,17 @@
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string>
|
||||
|
||||
#include "IttNotifyStdSrc.h"
|
||||
#include "TraceEventFormat.h"
|
||||
#include "ittnotify.h"
|
||||
|
||||
inline size_t GetMemPageSize() {
|
||||
@ -46,7 +48,7 @@ inline size_t GetMemPageSize() {
|
||||
|
||||
class CMemMap {
|
||||
CMemMap(const CMemMap&) = delete;
|
||||
CMemMap& operator = (const CMemMap&) = delete;
|
||||
CMemMap& operator=(const CMemMap&) = delete;
|
||||
|
||||
public:
|
||||
CMemMap(const std::string& path, size_t size, size_t offset = 0);
|
||||
@ -79,17 +81,23 @@ protected:
|
||||
|
||||
class CRecorder {
|
||||
CRecorder(const CRecorder&) = delete;
|
||||
CRecorder& operator = (const CRecorder&) = delete;
|
||||
CRecorder& operator=(const CRecorder&) = delete;
|
||||
|
||||
public:
|
||||
CRecorder();
|
||||
bool Init(const std::string& path, uint64_t time, void* pCut);
|
||||
size_t CheckCapacity(size_t size);
|
||||
void* Allocate(size_t size);
|
||||
uint64_t GetCount() { return m_counter; }
|
||||
uint64_t GetCreationTime() { return m_time; }
|
||||
uint64_t GetCount() {
|
||||
return m_counter;
|
||||
}
|
||||
uint64_t GetCreationTime() {
|
||||
return m_time;
|
||||
}
|
||||
void Close(bool bSave);
|
||||
inline bool SameCut(void* pCut) { return pCut == m_pCut; }
|
||||
inline bool SameCut(void* pCut) {
|
||||
return pCut == m_pCut;
|
||||
}
|
||||
~CRecorder();
|
||||
|
||||
protected:
|
||||
@ -109,8 +117,7 @@ protected:
|
||||
void* m_pCut = nullptr;
|
||||
};
|
||||
|
||||
|
||||
enum class ERecordType: uint8_t {
|
||||
enum class ERecordType : uint8_t {
|
||||
BeginTask,
|
||||
EndTask,
|
||||
BeginOverlappedTask,
|
||||
@ -131,9 +138,9 @@ struct SRecord {
|
||||
const __itt_domain& domain;
|
||||
const __itt_id& taskid;
|
||||
const __itt_id& parentid;
|
||||
const __itt_string_handle *pName;
|
||||
const __itt_string_handle* pName;
|
||||
double* pDelta;
|
||||
const char *pData;
|
||||
const char* pData;
|
||||
size_t length;
|
||||
void* function;
|
||||
};
|
||||
@ -141,15 +148,15 @@ double* WriteRecord(ERecordType type, const SRecord& record);
|
||||
void WriteMeta(const CTraceEventFormat::SRegularFields& main, __itt_string_handle* pKey, const char* name, double* pDelta = nullptr);
|
||||
|
||||
namespace sea {
|
||||
struct IHandler;
|
||||
bool WriteThreadName(const CTraceEventFormat::SRegularFields& rf, const char* name);
|
||||
bool WriteGroupName(int64_t pid, const char* name);
|
||||
bool ReportString(__itt_string_handle* pStr);
|
||||
bool ReportModule(void* fn);
|
||||
bool InitJit();
|
||||
bool WriteJit(const void* buff, size_t size);
|
||||
bool InitMemStat();
|
||||
bool WriteMemStat(const void* buff, size_t size);
|
||||
struct IHandler;
|
||||
bool WriteThreadName(const CTraceEventFormat::SRegularFields& rf, const char* name);
|
||||
bool WriteGroupName(int64_t pid, const char* name);
|
||||
bool ReportString(__itt_string_handle* pStr);
|
||||
bool ReportModule(void* fn);
|
||||
bool InitJit();
|
||||
bool WriteJit(const void* buff, size_t size);
|
||||
bool InitMemStat();
|
||||
bool WriteMemStat(const void* buff, size_t size);
|
||||
} // namespace sea
|
||||
|
||||
sea::IHandler& GetSEARecorder();
|
||||
|
@ -21,20 +21,20 @@
|
||||
#include "Utils.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static const int64_t g_PID = (int64_t)GetCurrentProcessId();
|
||||
static const int64_t g_PID = (int64_t)GetCurrentProcessId();
|
||||
#else
|
||||
static const int64_t g_PID = (int64_t)getpid();
|
||||
static const int64_t g_PID = (int64_t)getpid();
|
||||
#if defined(__APPLE__)
|
||||
inline int64_t GetTidFromPThread() {
|
||||
uint64_t tid64 = 0;
|
||||
pthread_threadid_np(NULL, &tid64);
|
||||
return (int64_t)tid64;
|
||||
}
|
||||
inline int64_t GetTidFromPThread() {
|
||||
uint64_t tid64 = 0;
|
||||
pthread_threadid_np(NULL, &tid64);
|
||||
return (int64_t)tid64;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -59,29 +59,29 @@ public:
|
||||
};
|
||||
|
||||
enum EventPhase {
|
||||
Begin = 'B', //name, pid, tid, ts
|
||||
End = 'E', //name, pid, tid, ts
|
||||
Complete = 'X', //name, pid, tid, ts, dur
|
||||
Instant = 'i', //name, pid, tid, ts, s = (g, p, t) //vertical line
|
||||
Counter = 'C', //name, pid, tid, ts //"args": {"cats": 0, "dogs": 7}
|
||||
AsyncBegin = 'b', //name, pid, tid, ts, id
|
||||
AsyncInstant = 'n', //name, pid, tid, ts, id
|
||||
AsyncEnd = 'e', //name, pid, tid, ts, id
|
||||
Begin = 'B', // name, pid, tid, ts
|
||||
End = 'E', // name, pid, tid, ts
|
||||
Complete = 'X', // name, pid, tid, ts, dur
|
||||
Instant = 'i', // name, pid, tid, ts, s = (g, p, t) //vertical line
|
||||
Counter = 'C', // name, pid, tid, ts //"args": {"cats": 0, "dogs": 7}
|
||||
AsyncBegin = 'b', // name, pid, tid, ts, id
|
||||
AsyncInstant = 'n', // name, pid, tid, ts, id
|
||||
AsyncEnd = 'e', // name, pid, tid, ts, id
|
||||
//'S', 'T', 'F',
|
||||
//'s', 't', 'f', //Flow events, with arrows: cool but unclear
|
||||
FlowStart = 's',
|
||||
FlowInstant = 't',
|
||||
FlowFinish = 'f',
|
||||
Metadata = 'M',
|
||||
Sample = 'P', //pid, tid, ts
|
||||
ObjectNew = 'N', //name, pid, tid, ts, id but no args!
|
||||
ObjectDelete = 'D', //name, pid, tid, ts, id but no args!
|
||||
ObjectSnapshot = 'O', //name, pid, tid, ts, id, can have args! See snapshot.basetype for deeper.
|
||||
Sample = 'P', // pid, tid, ts
|
||||
ObjectNew = 'N', // name, pid, tid, ts, id but no args!
|
||||
ObjectDelete = 'D', // name, pid, tid, ts, id but no args!
|
||||
ObjectSnapshot = 'O', // name, pid, tid, ts, id, can have args! See snapshot.basetype for deeper.
|
||||
};
|
||||
|
||||
static uint64_t GetTimeNS() {
|
||||
#ifdef _WIN32
|
||||
return SHiResClock::now64(); //in nanoseconds
|
||||
return SHiResClock::now64(); // in nanoseconds
|
||||
#elif defined(__linux__)
|
||||
static struct timespec res = {};
|
||||
if (!res.tv_nsec && !res.tv_sec) {
|
||||
@ -94,24 +94,24 @@ public:
|
||||
struct timespec ts = {};
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
return uint64_t((1000000000. * ts.tv_sec + ts.tv_nsec) / (1000000000. * res.tv_sec + res.tv_nsec));
|
||||
#else // FIXME: use mach_absolute_time for APPLE
|
||||
#else // FIXME: use mach_absolute_time for APPLE
|
||||
using namespace std::chrono;
|
||||
return (uint64_t)duration_cast<nanoseconds>(SHiResClock::now().time_since_epoch()).count();
|
||||
#endif
|
||||
}
|
||||
|
||||
static SRegularFields GetRegularFields() {
|
||||
return SRegularFields{
|
||||
#if defined(_WIN32)
|
||||
return SRegularFields {
|
||||
#if defined(_WIN32)
|
||||
g_PID, (int64_t)GetCurrentThreadId(),
|
||||
#elif defined(__linux__)
|
||||
#elif defined(__linux__)
|
||||
g_PID, (int64_t)syscall(SYS_gettid),
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__)
|
||||
g_PID, GetTidFromPThread(),
|
||||
#else
|
||||
#else
|
||||
g_PID, (int64_t)syscall(SYS_thread_selfid),
|
||||
#endif
|
||||
GetTimeNS()
|
||||
#endif
|
||||
GetTimeNS()
|
||||
};
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ public:
|
||||
|
||||
public:
|
||||
CArgs() {}
|
||||
template<class T>
|
||||
template <class T>
|
||||
CArgs(const std::string& name, const T& value) {
|
||||
Add(name, value);
|
||||
}
|
||||
@ -130,13 +130,14 @@ public:
|
||||
m_args[name] = value ? value : "";
|
||||
return *this;
|
||||
}
|
||||
template<class T>
|
||||
template <class T>
|
||||
CArgs& Add(const std::string& name, const T& value) {
|
||||
m_args[name] = std::to_string(value);
|
||||
return *this;
|
||||
}
|
||||
operator bool() const { return !m_args.empty(); }
|
||||
|
||||
operator bool() const {
|
||||
return !m_args.empty();
|
||||
}
|
||||
|
||||
std::string Str() const {
|
||||
std::string res;
|
||||
@ -147,7 +148,8 @@ public:
|
||||
}
|
||||
return res;
|
||||
}
|
||||
const TMap& GetMap() const {return m_args;}
|
||||
const TMap& GetMap() const {
|
||||
return m_args;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
80
thirdparty/itt_collector/sea_itt_lib/Utils.cpp
vendored
80
thirdparty/itt_collector/sea_itt_lib/Utils.cpp
vendored
@ -17,9 +17,11 @@
|
||||
**********************************************************************************************************************************************************************************************************************************************************************************************/
|
||||
|
||||
#include "Utils.h"
|
||||
#include "IttNotifyStdSrc.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "IttNotifyStdSrc.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Psapi.h>
|
||||
#undef API_VERSION
|
||||
@ -27,7 +29,6 @@
|
||||
#else
|
||||
#include <cxxabi.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
@ -46,10 +47,9 @@
|
||||
#include <link.h>
|
||||
#endif
|
||||
|
||||
|
||||
size_t GetStack(TStack& stack) {
|
||||
#ifdef _WIN32
|
||||
typedef USHORT (WINAPI *FCaptureStackBackTrace)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
|
||||
typedef USHORT(WINAPI * FCaptureStackBackTrace)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
|
||||
static FCaptureStackBackTrace CaptureStackBackTrace = (FCaptureStackBackTrace)(GetProcAddress(LoadLibraryA("kernel32.dll"), "RtlCaptureStackBackTrace"));
|
||||
return CaptureStackBackTrace ? CaptureStackBackTrace(0, StackSize, stack, NULL) : 0;
|
||||
#else
|
||||
@ -64,7 +64,7 @@ std::string GetStackString() {
|
||||
TStack stack = {};
|
||||
size_t size = GetStack(stack);
|
||||
|
||||
char **bt_syms = backtrace_symbols(stack, size);
|
||||
char** bt_syms = backtrace_symbols(stack, size);
|
||||
if (!bt_syms)
|
||||
return std::string();
|
||||
std::string res;
|
||||
@ -97,32 +97,27 @@ SModuleInfo Fn2Mdl(void* fn) {
|
||||
GetModuleFileNameA(hModule, filename, sizeof(filename) - 1);
|
||||
MODULEINFO mi = {};
|
||||
GetModuleInformation(GetCurrentProcess(), hModule, &mi, sizeof(MODULEINFO));
|
||||
return SModuleInfo{hModule, mi.SizeOfImage, filename};
|
||||
return SModuleInfo {hModule, mi.SizeOfImage, filename};
|
||||
}
|
||||
|
||||
LONG WINAPI CreateMiniDump(EXCEPTION_POINTERS* pep) {
|
||||
typedef BOOL(WINAPI *PDUMPFN)(
|
||||
HANDLE hProcess,
|
||||
DWORD ProcessId,
|
||||
HANDLE hFile,
|
||||
MINIDUMP_TYPE DumpType,
|
||||
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||
PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
|
||||
typedef BOOL(WINAPI * PDUMPFN)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
|
||||
|
||||
PDUMPFN fnMiniDumpWriteDump = (PDUMPFN)GetProcAddress(::LoadLibraryA("DbgHelp.dll"), "MiniDumpWriteDump");
|
||||
if (!fnMiniDumpWriteDump) return EXCEPTION_EXECUTE_HANDLER;
|
||||
if (!fnMiniDumpWriteDump)
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
std::string path = g_savepath.empty() ? "c:/temp" : g_savepath;
|
||||
path += "/isea_minidump.dmp";
|
||||
HANDLE hFile = CreateFileA(path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (!hFile || INVALID_HANDLE_VALUE == hFile) return EXCEPTION_EXECUTE_HANDLER;
|
||||
if (!hFile || INVALID_HANDLE_VALUE == hFile)
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
|
||||
MINIDUMP_EXCEPTION_INFORMATION mdei = {};
|
||||
mdei.ThreadId = GetCurrentThreadId();
|
||||
mdei.ExceptionPointers = pep;
|
||||
mdei.ClientPointers = TRUE;
|
||||
|
||||
|
||||
fnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, (pep != 0) ? &mdei : 0, 0, 0);
|
||||
CloseHandle(hFile);
|
||||
|
||||
@ -136,12 +131,12 @@ void SetGlobalCrashHandler() {
|
||||
#else
|
||||
|
||||
void SetGlobalCrashHandler() {
|
||||
//FIXME: implement
|
||||
// FIXME: implement
|
||||
}
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
size_t GetFileSize(const char *path) {
|
||||
size_t GetFileSize(const char* path) {
|
||||
struct stat st = {};
|
||||
|
||||
if (0 == stat(path, &st))
|
||||
@ -150,17 +145,17 @@ size_t GetFileSize(const char *path) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
#ifndef __APPLE__
|
||||
|
||||
#if !defined(NO_DL_ITERATE_PHDR)
|
||||
int iterate_callback(struct dl_phdr_info *info, size_t size, void *data) {
|
||||
#if !defined(NO_DL_ITERATE_PHDR)
|
||||
int iterate_callback(struct dl_phdr_info* info, size_t size, void* data) {
|
||||
Dl_info* pInfo = reinterpret_cast<Dl_info*>(data);
|
||||
VerbosePrint("iterate_callback: %lx, %s\n", (long int)info->dlpi_addr, info->dlpi_name);
|
||||
if (reinterpret_cast<void*>(info->dlpi_addr) == pInfo->dli_fbase)
|
||||
pInfo->dli_fname = strdup(info->dlpi_name);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool proc_self_map(Dl_info& info) {
|
||||
char base[100] = {};
|
||||
@ -178,52 +173,51 @@ bool proc_self_map(Dl_info& info) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
sea::SModuleInfo Fn2Mdl(void* fn) {
|
||||
Dl_info dl_info = {};
|
||||
dladdr(fn, &dl_info);
|
||||
VerbosePrint("Fn2Mdl: %p, %s\n", dl_info.dli_fbase, dl_info.dli_fname);
|
||||
if (!dl_info.dli_fname || !strstr(dl_info.dli_fname, ".so")) {
|
||||
#ifndef __APPLE__
|
||||
#if !defined(NO_DL_ITERATE_PHDR)
|
||||
#ifndef __APPLE__
|
||||
#if !defined(NO_DL_ITERATE_PHDR)
|
||||
dl_iterate_phdr(iterate_callback, &dl_info);
|
||||
#endif
|
||||
#endif
|
||||
if (!dl_info.dli_fname || !strstr(dl_info.dli_fname, ".so"))
|
||||
proc_self_map(dl_info);
|
||||
#endif
|
||||
return SModuleInfo{dl_info.dli_fbase, 0, dl_info.dli_fname};
|
||||
#endif
|
||||
return SModuleInfo {dl_info.dli_fbase, 0, dl_info.dli_fname};
|
||||
}
|
||||
|
||||
if (dl_info.dli_fname[0] == '/') {
|
||||
// path is absolute
|
||||
return SModuleInfo{dl_info.dli_fbase, GetFileSize(dl_info.dli_fname), dl_info.dli_fname};
|
||||
return SModuleInfo {dl_info.dli_fbase, GetFileSize(dl_info.dli_fname), dl_info.dli_fname};
|
||||
} else {
|
||||
if (const char * absolute = realpath(dl_info.dli_fname, nullptr)) {
|
||||
SModuleInfo mdlInfo{dl_info.dli_fbase, GetFileSize(absolute), absolute};
|
||||
free((void*) absolute); // NOLINT
|
||||
if (const char* absolute = realpath(dl_info.dli_fname, nullptr)) {
|
||||
SModuleInfo mdlInfo {dl_info.dli_fbase, GetFileSize(absolute), absolute};
|
||||
free((void*)absolute);
|
||||
return mdlInfo;
|
||||
} else {
|
||||
return SModuleInfo{dl_info.dli_fbase, GetFileSize(dl_info.dli_fname), dl_info.dli_fname};
|
||||
return SModuleInfo {dl_info.dli_fbase, GetFileSize(dl_info.dli_fname), dl_info.dli_fname};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* GetProcessName(bool bFullPath) {
|
||||
static char process_name[1024] = {};
|
||||
#ifdef __APPLE__
|
||||
#ifdef __APPLE__
|
||||
uint32_t size = 1023;
|
||||
_NSGetExecutablePath(process_name, &size);
|
||||
#else
|
||||
#else
|
||||
if (!process_name[0])
|
||||
process_name[readlink("/proc/self/exe", process_name, sizeof(process_name)/sizeof(process_name[0]) - 1 )] = 0;
|
||||
#endif //__APPLE__
|
||||
if (bFullPath) return process_name;
|
||||
process_name[readlink("/proc/self/exe", process_name, sizeof(process_name) / sizeof(process_name[0]) - 1)] = 0;
|
||||
#endif //__APPLE__
|
||||
if (bFullPath)
|
||||
return process_name;
|
||||
return strrchr(process_name, '/') + 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace sea
|
||||
|
||||
|
||||
} // namespace sea
|
||||
|
184
thirdparty/itt_collector/sea_itt_lib/Utils.h
vendored
184
thirdparty/itt_collector/sea_itt_lib/Utils.h
vendored
@ -17,17 +17,18 @@
|
||||
**********************************************************************************************************************************************************************************************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <assert.h>
|
||||
#include <mutex>
|
||||
#include <future>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__arm__) && !defined(__aarch64__)
|
||||
#define ARM32
|
||||
@ -36,15 +37,15 @@
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
static std::string get_environ_value(const std::string& name) {
|
||||
#ifdef _WIN32
|
||||
size_t sz;
|
||||
char *v = NULL;
|
||||
char* v = NULL;
|
||||
_dupenv_s(&v, &sz, name.c_str());
|
||||
|
||||
std::string ret = v ? v : "";
|
||||
@ -52,91 +53,92 @@ static std::string get_environ_value(const std::string& name) {
|
||||
|
||||
return ret;
|
||||
#else
|
||||
const char *v = getenv(name.c_str());
|
||||
const char* v = getenv(name.c_str());
|
||||
return v ? v : "";
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
//there is bug in VS2012 implementation: high_resolution_clock is in fact not high res...
|
||||
struct SHiResClock {
|
||||
typedef uint64_t rep;
|
||||
typedef std::nano period;
|
||||
typedef std::chrono::duration<rep, period> duration;
|
||||
typedef std::chrono::time_point<SHiResClock> time_point;
|
||||
static const bool is_steady = true;
|
||||
static uint64_t now64() {
|
||||
static long long frequency = 0;
|
||||
if (!frequency) {
|
||||
QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&frequency));
|
||||
}
|
||||
// there is bug in VS2012 implementation: high_resolution_clock is in fact not high res...
|
||||
struct SHiResClock {
|
||||
typedef uint64_t rep;
|
||||
typedef std::nano period;
|
||||
typedef std::chrono::duration<rep, period> duration;
|
||||
typedef std::chrono::time_point<SHiResClock> time_point;
|
||||
static const bool is_steady = true;
|
||||
static uint64_t now64() {
|
||||
static long long frequency = 0;
|
||||
if (!frequency) {
|
||||
QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&frequency));
|
||||
}
|
||||
|
||||
LARGE_INTEGER count = {};
|
||||
QueryPerformanceCounter(&count);
|
||||
return static_cast<uint64_t>(static_cast<double>(count.QuadPart) / frequency * static_cast<rep>(period::den));
|
||||
}
|
||||
static time_point now() {
|
||||
return time_point(duration(now64()));
|
||||
}
|
||||
};
|
||||
LARGE_INTEGER count = {};
|
||||
QueryPerformanceCounter(&count);
|
||||
return static_cast<uint64_t>(static_cast<double>(count.QuadPart) / frequency * static_cast<rep>(period::den));
|
||||
}
|
||||
static time_point now() {
|
||||
return time_point(duration(now64()));
|
||||
}
|
||||
};
|
||||
|
||||
namespace sea {
|
||||
inline uint64_t GetTime() {
|
||||
LARGE_INTEGER count = {};
|
||||
QueryPerformanceCounter(&count);
|
||||
return count.QuadPart;
|
||||
}
|
||||
inline uint64_t GetTimeFreq() {
|
||||
static LARGE_INTEGER frequency = {};
|
||||
if (!frequency.QuadPart) {
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
}
|
||||
return frequency.QuadPart;
|
||||
}
|
||||
} // namespace sea
|
||||
namespace sea {
|
||||
inline uint64_t GetTime() {
|
||||
LARGE_INTEGER count = {};
|
||||
QueryPerformanceCounter(&count);
|
||||
return count.QuadPart;
|
||||
}
|
||||
inline uint64_t GetTimeFreq() {
|
||||
static LARGE_INTEGER frequency = {};
|
||||
if (!frequency.QuadPart) {
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
}
|
||||
return frequency.QuadPart;
|
||||
}
|
||||
} // namespace sea
|
||||
|
||||
#else
|
||||
|
||||
typedef std::chrono::high_resolution_clock SHiResClock;
|
||||
namespace sea {
|
||||
using namespace std::chrono;
|
||||
inline uint64_t GetTime() {
|
||||
return (uint64_t)duration_cast<nanoseconds>(SHiResClock::now().time_since_epoch()).count();
|
||||
}
|
||||
inline uint64_t GetTimeFreq() {
|
||||
/*
|
||||
TODO:
|
||||
struct timespec res = {};
|
||||
clock_getres(CLOCK_MONOTONIC_RAW, &res);
|
||||
uint64_t freq = 1000000000ULL * (uint64_t)res.tv_sec + (uint64_t)res.tv_nsec;
|
||||
*/
|
||||
static uint64_t freq = SHiResClock::period::num / SHiResClock::period::den;
|
||||
return freq;
|
||||
}
|
||||
} // namespace sea
|
||||
typedef std::chrono::high_resolution_clock SHiResClock;
|
||||
namespace sea {
|
||||
using namespace std::chrono;
|
||||
inline uint64_t GetTime() {
|
||||
return (uint64_t)duration_cast<nanoseconds>(SHiResClock::now().time_since_epoch()).count();
|
||||
}
|
||||
inline uint64_t GetTimeFreq() {
|
||||
/*
|
||||
TODO:
|
||||
struct timespec res = {};
|
||||
clock_getres(CLOCK_MONOTONIC_RAW, &res);
|
||||
uint64_t freq = 1000000000ULL * (uint64_t)res.tv_sec + (uint64_t)res.tv_nsec;
|
||||
*/
|
||||
static uint64_t freq = SHiResClock::period::num / SHiResClock::period::den;
|
||||
return freq;
|
||||
}
|
||||
} // namespace sea
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER //std::mutex won't work in static constructors due to MS bug
|
||||
class CCriticalSection {
|
||||
CRITICAL_SECTION m_cs;
|
||||
public:
|
||||
CCriticalSection() {
|
||||
InitializeCriticalSection(&m_cs);
|
||||
}
|
||||
void lock() {
|
||||
EnterCriticalSection(&m_cs);
|
||||
}
|
||||
void unlock() {
|
||||
LeaveCriticalSection(&m_cs);
|
||||
}
|
||||
~CCriticalSection() {
|
||||
DeleteCriticalSection(&m_cs);
|
||||
}
|
||||
};
|
||||
typedef CCriticalSection TCritSec;
|
||||
#ifdef _MSC_VER // std::mutex won't work in static constructors due to MS bug
|
||||
class CCriticalSection {
|
||||
CRITICAL_SECTION m_cs;
|
||||
|
||||
public:
|
||||
CCriticalSection() {
|
||||
InitializeCriticalSection(&m_cs);
|
||||
}
|
||||
void lock() {
|
||||
EnterCriticalSection(&m_cs);
|
||||
}
|
||||
void unlock() {
|
||||
LeaveCriticalSection(&m_cs);
|
||||
}
|
||||
~CCriticalSection() {
|
||||
DeleteCriticalSection(&m_cs);
|
||||
}
|
||||
};
|
||||
typedef CCriticalSection TCritSec;
|
||||
#else
|
||||
typedef std::recursive_mutex TCritSec;
|
||||
typedef std::recursive_mutex TCritSec;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -145,7 +147,7 @@ static std::string get_environ_value(const std::string& name) {
|
||||
#define thread_local __thread
|
||||
#endif
|
||||
|
||||
template<size_t size>
|
||||
template <size_t size>
|
||||
class CPlacementPool {
|
||||
static CPlacementPool& GetPool() {
|
||||
static thread_local CPlacementPool* pPool = nullptr;
|
||||
@ -174,9 +176,10 @@ public:
|
||||
return GetPool().AllocMem();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template <class T>
|
||||
static void Free(T* ptr) {
|
||||
if (!ptr) return;
|
||||
if (!ptr)
|
||||
return;
|
||||
ptr->~T();
|
||||
return GetPool().FreeMem(ptr);
|
||||
}
|
||||
@ -188,7 +191,7 @@ public:
|
||||
};
|
||||
|
||||
#define placement_new(T) new (CPlacementPool<sizeof(T)>::Alloc()) T
|
||||
template<class T>
|
||||
template <class T>
|
||||
inline void placement_free(T* ptr) {
|
||||
CPlacementPool<sizeof(T)>::Free(ptr);
|
||||
}
|
||||
@ -196,20 +199,19 @@ inline void placement_free(T* ptr) {
|
||||
class CScope {
|
||||
protected:
|
||||
std::function<void(void)> m_fn;
|
||||
|
||||
public:
|
||||
CScope(const std::function<void(void)>& fn)
|
||||
: m_fn(fn)
|
||||
{}
|
||||
CScope(const std::function<void(void)>& fn): m_fn(fn) {}
|
||||
~CScope() {
|
||||
m_fn();
|
||||
}
|
||||
};
|
||||
|
||||
const size_t StackSize = 100;
|
||||
using TStack = void*[StackSize];
|
||||
using TStack = void* [StackSize];
|
||||
size_t GetStack(TStack& stack);
|
||||
std::string GetStackString();
|
||||
|
||||
namespace sea {
|
||||
void SetGlobalCrashHandler();
|
||||
void SetGlobalCrashHandler();
|
||||
}
|
||||
|
400
thirdparty/itt_collector/sea_itt_lib/sea_itt_lib.cpp
vendored
400
thirdparty/itt_collector/sea_itt_lib/sea_itt_lib.cpp
vendored
@ -16,11 +16,13 @@
|
||||
#
|
||||
**********************************************************************************************************************************************************************************************************************************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "IttNotifyStdSrc.h"
|
||||
#include "Utils.h"
|
||||
#include <stdlib.h>
|
||||
#include <cstdio>
|
||||
#include <string.h>
|
||||
#include "jitprofiling.h"
|
||||
|
||||
#define INTEL_LIBITTNOTIFY "INTEL_LIBITTNOTIFY"
|
||||
@ -33,7 +35,7 @@
|
||||
#include <Dbghelp.h>
|
||||
#pragma comment(lib, "dbghelp")
|
||||
#else
|
||||
#define setenv putenv
|
||||
#define setenv putenv
|
||||
#define _strdup strdup
|
||||
#endif
|
||||
|
||||
@ -48,7 +50,7 @@
|
||||
int GlobalInit() {
|
||||
static const char var_name[] = INTEL_LIBITTNOTIFY BIT_SUFFIX;
|
||||
static const char jit_var_name[] = INTEL_JIT_PROFILER BIT_SUFFIX;
|
||||
sea::SModuleInfo mdlinfo = sea::Fn2Mdl((void*)GlobalInit); // NOLINT
|
||||
sea::SModuleInfo mdlinfo = sea::Fn2Mdl((void*)GlobalInit);
|
||||
|
||||
VerbosePrint("IntelSEAPI: %s=%s | Loaded from: %s\n", var_name, get_environ_value(var_name).c_str(), mdlinfo.path.c_str());
|
||||
|
||||
@ -70,7 +72,7 @@ int nSetLib = GlobalInit();
|
||||
void AtExit();
|
||||
|
||||
extern "C" {
|
||||
extern __itt_global ITT_JOIN(INTEL_ITTNOTIFY_PREFIX, _ittapi_global);
|
||||
extern __itt_global ITT_JOIN(INTEL_ITTNOTIFY_PREFIX, _ittapi_global);
|
||||
}
|
||||
|
||||
bool g_bInitialized = false;
|
||||
@ -82,7 +84,7 @@ __itt_global* GetITTGlobal() {
|
||||
void ChainGlobal(__itt_global* pNew) {
|
||||
__itt_global* pCurrent = GetITTGlobal();
|
||||
while (pCurrent->next) {
|
||||
if (pCurrent->next == pNew) //already chained
|
||||
if (pCurrent->next == pNew) // already chained
|
||||
return;
|
||||
pCurrent = pCurrent->next;
|
||||
}
|
||||
@ -93,115 +95,111 @@ void UnchainGlobal(__itt_global* pOld) {
|
||||
__itt_global* pCurrent = GetITTGlobal();
|
||||
while (pCurrent->next) {
|
||||
if (pCurrent->next == pOld) {
|
||||
pCurrent->next = pOld->next; //removing it from list
|
||||
pCurrent->next = pOld->next; // removing it from list
|
||||
return;
|
||||
}
|
||||
pCurrent = pCurrent->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
||||
#define FIX_STR(type, ptr, name) \
|
||||
if (!ptr->name##A) { \
|
||||
if (ptr->name##W) { \
|
||||
size_t len = lstrlenW((const wchar_t*)ptr->name##W); \
|
||||
char* dest = reinterpret_cast<char*>(malloc(len + 2)); \
|
||||
wcstombs_s(&len, dest, len + 1, (const wchar_t*)ptr->name##W, len + 1); \
|
||||
const_cast<type*>(ptr)->name##A = dest; \
|
||||
} else { \
|
||||
const_cast<type*>(ptr)->name##A = _strdup("null"); \
|
||||
} \
|
||||
#define FIX_STR(type, ptr, name) \
|
||||
if (!ptr->name##A) { \
|
||||
if (ptr->name##W) { \
|
||||
size_t len = lstrlenW((const wchar_t*)ptr->name##W); \
|
||||
char* dest = reinterpret_cast<char*>(malloc(len + 2)); \
|
||||
wcstombs_s(&len, dest, len + 1, (const wchar_t*)ptr->name##W, len + 1); \
|
||||
const_cast<type*>(ptr)->name##A = dest; \
|
||||
} else { \
|
||||
const_cast<type*>(ptr)->name##A = _strdup("null"); \
|
||||
} \
|
||||
}
|
||||
|
||||
#else
|
||||
#define FIX_STR(type, ptr, name) \
|
||||
if (!ptr->name##A) { \
|
||||
if (ptr->name##W) { \
|
||||
size_t len = wcslen((const wchar_t*)ptr->name##W); \
|
||||
char* dest = reinterpret_cast<char*>(malloc(len + 2)); \
|
||||
wcstombs(dest, (const wchar_t*)ptr->name##W, len + 1); \
|
||||
const_cast<type*>(ptr)->name##A = dest; \
|
||||
} else { \
|
||||
const_cast<type*>(ptr)->name##A = _strdup("null"); \
|
||||
} \
|
||||
#define FIX_STR(type, ptr, name) \
|
||||
if (!ptr->name##A) { \
|
||||
if (ptr->name##W) { \
|
||||
size_t len = wcslen((const wchar_t*)ptr->name##W); \
|
||||
char* dest = reinterpret_cast<char*>(malloc(len + 2)); \
|
||||
wcstombs(dest, (const wchar_t*)ptr->name##W, len + 1); \
|
||||
const_cast<type*>(ptr)->name##A = dest; \
|
||||
} else { \
|
||||
const_cast<type*>(ptr)->name##A = _strdup("null"); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define FIX_DOMAIN(ptr) FIX_STR(__itt_domain, ptr, name)
|
||||
#define FIX_STRING(ptr) FIX_STR(__itt_string_handle, ptr, str)
|
||||
#define FIX_COUNTER(ptr)\
|
||||
FIX_STR(__itt_counter_info_t, ptr, name);\
|
||||
FIX_STR(__itt_counter_info_t, ptr, domain);\
|
||||
#define FIX_COUNTER(ptr) \
|
||||
FIX_STR(__itt_counter_info_t, ptr, name); \
|
||||
FIX_STR(__itt_counter_info_t, ptr, domain); \
|
||||
sea::FixCounter(ptr);
|
||||
|
||||
|
||||
void __itt_report_error(__itt_error_code, ...) {}
|
||||
|
||||
|
||||
__itt_domain* g_pIntelSEAPIDomain = nullptr;
|
||||
|
||||
extern "C" {
|
||||
|
||||
SEA_EXPORT void ITTAPI __itt_api_init(__itt_global* pGlob, __itt_group_id id) {
|
||||
if (!g_bInitialized) {
|
||||
g_bInitialized = true;
|
||||
sea::SetGlobalCrashHandler();
|
||||
SEA_EXPORT void ITTAPI __itt_api_init(__itt_global* pGlob, __itt_group_id id) {
|
||||
if (!g_bInitialized) {
|
||||
g_bInitialized = true;
|
||||
sea::SetGlobalCrashHandler();
|
||||
|
||||
__itt_global* pGlobal = GetITTGlobal();
|
||||
__itt_mutex_init(&pGlobal->mutex);
|
||||
pGlobal->mutex_initialized = 1;
|
||||
sea::CIttLocker locker;
|
||||
using namespace sea;
|
||||
g_pIntelSEAPIDomain = UNICODE_AGNOSTIC(domain_create)("IntelSEAPI");
|
||||
__itt_api_init(pGlobal, id);
|
||||
pGlobal->api_initialized = 1;
|
||||
}
|
||||
const char* procname = sea::GetProcessName(true);
|
||||
sea::SModuleInfo mdlinfo = sea::Fn2Mdl(pGlob);
|
||||
VerbosePrint("IntelSEAPI init is called from process '%s' at module '%s'\n", procname, mdlinfo.path.c_str());
|
||||
if (GetITTGlobal() != pGlob)
|
||||
ChainGlobal(pGlob);
|
||||
sea::FillApiList(pGlob->api_list_ptr);
|
||||
for (___itt_domain* pDomain = pGlob->domain_list; pDomain; pDomain = pDomain->next) {
|
||||
FIX_DOMAIN(pDomain);
|
||||
sea::InitDomain(pDomain);
|
||||
}
|
||||
for (__itt_string_handle* pStr = pGlob->string_list; pStr; pStr = pStr->next) {
|
||||
FIX_STRING(pStr);
|
||||
sea::ReportString(const_cast<__itt_string_handle *>(pStr));
|
||||
}
|
||||
// counter_list was not yet invented that time
|
||||
if (pGlob->version_build > 20120000) {
|
||||
for (__itt_counter_info_t* pCounter = pGlob->counter_list; pCounter; pCounter = pCounter->next) {
|
||||
FIX_COUNTER(pCounter);
|
||||
VerbosePrint("Fixed counter: %s | %s\n", pCounter->domainA, pCounter->nameA);
|
||||
}
|
||||
}
|
||||
sea::ReportModule(pGlob);
|
||||
static bool bInitialized = false;
|
||||
if (!bInitialized) {
|
||||
bInitialized = true;
|
||||
sea::InitSEA();
|
||||
atexit(AtExit);
|
||||
__itt_global* pGlobal = GetITTGlobal();
|
||||
__itt_mutex_init(&pGlobal->mutex);
|
||||
pGlobal->mutex_initialized = 1;
|
||||
sea::CIttLocker locker;
|
||||
using namespace sea;
|
||||
g_pIntelSEAPIDomain = UNICODE_AGNOSTIC(domain_create)("IntelSEAPI");
|
||||
__itt_api_init(pGlobal, id);
|
||||
pGlobal->api_initialized = 1;
|
||||
}
|
||||
const char* procname = sea::GetProcessName(true);
|
||||
sea::SModuleInfo mdlinfo = sea::Fn2Mdl(pGlob);
|
||||
VerbosePrint("IntelSEAPI init is called from process '%s' at module '%s'\n", procname, mdlinfo.path.c_str());
|
||||
if (GetITTGlobal() != pGlob)
|
||||
ChainGlobal(pGlob);
|
||||
sea::FillApiList(pGlob->api_list_ptr);
|
||||
for (___itt_domain* pDomain = pGlob->domain_list; pDomain; pDomain = pDomain->next) {
|
||||
FIX_DOMAIN(pDomain);
|
||||
sea::InitDomain(pDomain);
|
||||
}
|
||||
for (__itt_string_handle* pStr = pGlob->string_list; pStr; pStr = pStr->next) {
|
||||
FIX_STRING(pStr);
|
||||
sea::ReportString(const_cast<__itt_string_handle*>(pStr));
|
||||
}
|
||||
// counter_list was not yet invented that time
|
||||
if (pGlob->version_build > 20120000) {
|
||||
for (__itt_counter_info_t* pCounter = pGlob->counter_list; pCounter; pCounter = pCounter->next) {
|
||||
FIX_COUNTER(pCounter);
|
||||
VerbosePrint("Fixed counter: %s | %s\n", pCounter->domainA, pCounter->nameA);
|
||||
}
|
||||
}
|
||||
sea::ReportModule(pGlob);
|
||||
static bool bInitialized = false;
|
||||
if (!bInitialized) {
|
||||
bInitialized = true;
|
||||
sea::InitSEA();
|
||||
atexit(AtExit);
|
||||
}
|
||||
}
|
||||
|
||||
SEA_EXPORT void ITTAPI __itt_api_fini(__itt_global* pGlob) {
|
||||
if (pGlob) {
|
||||
UnchainGlobal(pGlob);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_bInitialized) return;
|
||||
g_bInitialized = false;
|
||||
|
||||
sea::FinitaLaComedia();
|
||||
SEA_EXPORT void ITTAPI __itt_api_fini(__itt_global* pGlob) {
|
||||
if (pGlob) {
|
||||
UnchainGlobal(pGlob);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_bInitialized)
|
||||
return;
|
||||
g_bInitialized = false;
|
||||
|
||||
sea::FinitaLaComedia();
|
||||
}
|
||||
}
|
||||
|
||||
void AtExit() {
|
||||
@ -210,141 +208,136 @@ void AtExit() {
|
||||
|
||||
extern "C" {
|
||||
#ifdef STANDARD_SOURCES
|
||||
typedef bool(*receive_t)(uint64_t receiver, uint64_t time, uint16_t count, const stdsrc::uchar_t** names, const stdsrc::uchar_t** values, double progress);
|
||||
typedef uint64_t(*get_receiver_t)(const stdsrc::uchar_t* provider, const stdsrc::uchar_t* opcode, const stdsrc::uchar_t* taskName);
|
||||
typedef bool (*receive_t)(uint64_t receiver, uint64_t time, uint16_t count, const stdsrc::uchar_t** names, const stdsrc::uchar_t** values, double progress);
|
||||
typedef uint64_t (*get_receiver_t)(const stdsrc::uchar_t* provider, const stdsrc::uchar_t* opcode, const stdsrc::uchar_t* taskName);
|
||||
|
||||
SEA_EXPORT bool parse_standard_source(const char* file, get_receiver_t get_receiver, receive_t receive) {
|
||||
STDSRC_CHECK_RET(file, false);
|
||||
class Receiver : public stdsrc::Receiver {
|
||||
protected:
|
||||
uint64_t m_receiver = 0;
|
||||
receive_t m_receive = nullptr;
|
||||
stdsrc::Reader& m_reader;
|
||||
SEA_EXPORT bool parse_standard_source(const char* file, get_receiver_t get_receiver, receive_t receive) {
|
||||
STDSRC_CHECK_RET(file, false);
|
||||
class Receiver : public stdsrc::Receiver {
|
||||
protected:
|
||||
uint64_t m_receiver = 0;
|
||||
receive_t m_receive = nullptr;
|
||||
stdsrc::Reader& m_reader;
|
||||
|
||||
public:
|
||||
Receiver(stdsrc::Reader& reader, uint64_t receiver, receive_t receive)
|
||||
: m_receiver(receiver)
|
||||
, m_reader(reader)
|
||||
, m_receive(receive) {}
|
||||
public:
|
||||
Receiver(stdsrc::Reader& reader, uint64_t receiver, receive_t receive): m_receiver(receiver), m_reader(reader), m_receive(receive) {}
|
||||
|
||||
virtual bool onEvent(uint64_t time, const stdsrc::CVariantTree& props) {
|
||||
size_t size = props.get_bags().size();
|
||||
std::vector<const stdsrc::uchar_t*> names(size), values(size);
|
||||
std::vector<stdsrc::ustring> values_temp(size);
|
||||
names.reserve(size);
|
||||
values.reserve(size);
|
||||
size_t i = 0;
|
||||
for (const auto& pair : props.get_bags()) {
|
||||
const stdsrc::CVariantTree& prop = pair.second;
|
||||
const stdsrc::CVariant& name = prop.get_variant(stdsrc::bagname::Name);
|
||||
names[i] = name.is_empty() ? nullptr : name.get<stdsrc::ustring>().c_str();
|
||||
const stdsrc::CVariant& value = prop.get_variant(stdsrc::bagname::Value);
|
||||
values[i] = value.is_empty() ? nullptr : value.as_str(values_temp[i]).c_str();
|
||||
++i;
|
||||
}
|
||||
return m_receive(m_receiver, time, (uint16_t)size, size ? &names[0] : nullptr, size ? &values[0] : nullptr, m_reader.getProgress());
|
||||
virtual bool onEvent(uint64_t time, const stdsrc::CVariantTree& props) {
|
||||
size_t size = props.get_bags().size();
|
||||
std::vector<const stdsrc::uchar_t*> names(size), values(size);
|
||||
std::vector<stdsrc::ustring> values_temp(size);
|
||||
names.reserve(size);
|
||||
values.reserve(size);
|
||||
size_t i = 0;
|
||||
for (const auto& pair : props.get_bags()) {
|
||||
const stdsrc::CVariantTree& prop = pair.second;
|
||||
const stdsrc::CVariant& name = prop.get_variant(stdsrc::bagname::Name);
|
||||
names[i] = name.is_empty() ? nullptr : name.get<stdsrc::ustring>().c_str();
|
||||
const stdsrc::CVariant& value = prop.get_variant(stdsrc::bagname::Value);
|
||||
values[i] = value.is_empty() ? nullptr : value.as_str(values_temp[i]).c_str();
|
||||
++i;
|
||||
}
|
||||
};
|
||||
return m_receive(m_receiver, time, (uint16_t)size, size ? &names[0] : nullptr, size ? &values[0] : nullptr, m_reader.getProgress());
|
||||
}
|
||||
};
|
||||
|
||||
class Reader : public stdsrc::Reader {
|
||||
get_receiver_t m_get_receiver = nullptr;
|
||||
receive_t m_receive = nullptr;
|
||||
public:
|
||||
Reader(get_receiver_t get_receiver, receive_t receive)
|
||||
: m_get_receiver(get_receiver)
|
||||
, m_receive(receive) {}
|
||||
virtual stdsrc::Receiver::Ptr getReceiver(const stdsrc::ustring& provider, const stdsrc::ustring& opcode, const stdsrc::ustring& taskName,
|
||||
stdsrc::CVariantTree& props) {
|
||||
uint64_t receiver = m_get_receiver(provider.c_str(), opcode.c_str(), taskName.c_str());
|
||||
if (!receiver) return nullptr;
|
||||
return std::make_shared<Receiver>(*this, receiver, m_receive);
|
||||
}
|
||||
};
|
||||
Reader reader(get_receiver, receive);
|
||||
std::string path(file);
|
||||
#ifdef _WIN32
|
||||
if (path.substr(path.size() - 4) == ".etl")
|
||||
return stdsrc::readETLFile(reader, file, stdsrc::etuRaw);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
class Reader : public stdsrc::Reader {
|
||||
get_receiver_t m_get_receiver = nullptr;
|
||||
receive_t m_receive = nullptr;
|
||||
|
||||
public:
|
||||
Reader(get_receiver_t get_receiver, receive_t receive): m_get_receiver(get_receiver), m_receive(receive) {}
|
||||
virtual stdsrc::Receiver::Ptr getReceiver(const stdsrc::ustring& provider, const stdsrc::ustring& opcode, const stdsrc::ustring& taskName,
|
||||
stdsrc::CVariantTree& props) {
|
||||
uint64_t receiver = m_get_receiver(provider.c_str(), opcode.c_str(), taskName.c_str());
|
||||
if (!receiver)
|
||||
return nullptr;
|
||||
return std::make_shared<Receiver>(*this, receiver, m_receive);
|
||||
}
|
||||
};
|
||||
Reader reader(get_receiver, receive);
|
||||
std::string path(file);
|
||||
#ifdef _WIN32
|
||||
if (path.substr(path.size() - 4) == ".etl")
|
||||
return stdsrc::readETLFile(reader, file, stdsrc::etuRaw);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
SEA_EXPORT const char* resolve_pointer(const char* szModulePath, uint64_t addr) {
|
||||
static std::string res;
|
||||
res.clear();
|
||||
static HANDLE hCurProc = GetCurrentProcess();
|
||||
DWORD dwOptions = SymSetOptions((SymGetOptions() |
|
||||
SYMOPT_LOAD_LINES |
|
||||
SYMOPT_UNDNAME |
|
||||
SYMOPT_INCLUDE_32BIT_MODULES |
|
||||
SYMOPT_ALLOW_ABSOLUTE_SYMBOLS) & ~SYMOPT_DEFERRED_LOADS);
|
||||
static BOOL bInitialize = SymInitialize(hCurProc, NULL, TRUE);
|
||||
if (!bInitialize) return nullptr;
|
||||
static std::map<std::string, uint64_t> modules;
|
||||
uint64_t module = 0;
|
||||
if (modules.count(szModulePath)) {
|
||||
module = modules[szModulePath];
|
||||
} else {
|
||||
module = SymLoadModule64(hCurProc, NULL, szModulePath, NULL, 0x800000, 0);
|
||||
modules[szModulePath] = module;
|
||||
}
|
||||
if (!module) return nullptr;
|
||||
IMAGEHLP_LINE64 line = { sizeof(IMAGEHLP_LINE64) };
|
||||
DWORD dwDisplacement = 0;
|
||||
SymGetLineFromAddr64(hCurProc, module + addr, &dwDisplacement, &line);
|
||||
if (line.FileName) {
|
||||
res += std::string(line.FileName) + "(" + std::to_string(line.LineNumber) + ")\n";
|
||||
}
|
||||
|
||||
char buff[sizeof(SYMBOL_INFO) + 1024] = {};
|
||||
SYMBOL_INFO * symbol = (SYMBOL_INFO*)buff; // NOLINT
|
||||
symbol->MaxNameLen = 255;
|
||||
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
SymFromAddr(hCurProc, module + addr, nullptr, symbol);
|
||||
res += symbol->Name;
|
||||
return res.c_str();
|
||||
SEA_EXPORT const char* resolve_pointer(const char* szModulePath, uint64_t addr) {
|
||||
static std::string res;
|
||||
res.clear();
|
||||
static HANDLE hCurProc = GetCurrentProcess();
|
||||
DWORD dwOptions = SymSetOptions((SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS) &
|
||||
~SYMOPT_DEFERRED_LOADS);
|
||||
static BOOL bInitialize = SymInitialize(hCurProc, NULL, TRUE);
|
||||
if (!bInitialize)
|
||||
return nullptr;
|
||||
static std::map<std::string, uint64_t> modules;
|
||||
uint64_t module = 0;
|
||||
if (modules.count(szModulePath)) {
|
||||
module = modules[szModulePath];
|
||||
} else {
|
||||
module = SymLoadModule64(hCurProc, NULL, szModulePath, NULL, 0x800000, 0);
|
||||
modules[szModulePath] = module;
|
||||
}
|
||||
if (!module)
|
||||
return nullptr;
|
||||
IMAGEHLP_LINE64 line = {sizeof(IMAGEHLP_LINE64)};
|
||||
DWORD dwDisplacement = 0;
|
||||
SymGetLineFromAddr64(hCurProc, module + addr, &dwDisplacement, &line);
|
||||
if (line.FileName) {
|
||||
res += std::string(line.FileName) + "(" + std::to_string(line.LineNumber) + ")\n";
|
||||
}
|
||||
|
||||
SEA_EXPORT int NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData) {
|
||||
iJIT_Method_Load* methodData = (iJIT_Method_Load*)EventSpecificData; // NOLINT
|
||||
char buff[sizeof(SYMBOL_INFO) + 1024] = {};
|
||||
SYMBOL_INFO* symbol = (SYMBOL_INFO*)buff;
|
||||
symbol->MaxNameLen = 255;
|
||||
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
SymFromAddr(hCurProc, module + addr, nullptr, symbol);
|
||||
res += symbol->Name;
|
||||
return res.c_str();
|
||||
}
|
||||
|
||||
switch (event_type) {
|
||||
case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED:
|
||||
{
|
||||
sea::WriteJit(&(uint32_t)methodData->method_id, sizeof(uint32_t)); // NOLINT
|
||||
sea::WriteJit(&methodData->method_load_address, sizeof(void*)); // NOLINT
|
||||
sea::WriteJit(&(uint32_t)methodData->method_size, sizeof(uint32_t)); // NOLINT
|
||||
sea::WriteJit(&(uint32_t)methodData->line_number_size, sizeof(uint32_t)); // NOLINT
|
||||
for (unsigned int i = 0; i < methodData->line_number_size; ++i) {
|
||||
const LineNumberInfo& lni = methodData->line_number_table[i];
|
||||
sea::WriteJit(&(uint32_t)lni.Offset, sizeof(uint32_t)); // NOLINT
|
||||
sea::WriteJit(&(uint32_t)lni.LineNumber, sizeof(uint32_t)); // NOLINT
|
||||
}
|
||||
SEA_EXPORT int NotifyEvent(iJIT_JVM_EVENT event_type, void* EventSpecificData) {
|
||||
iJIT_Method_Load* methodData = (iJIT_Method_Load*)EventSpecificData;
|
||||
|
||||
const char * strings[] = { methodData->method_name, methodData->class_file_name, methodData->source_file_name };
|
||||
for (size_t i = 0; i < sizeof(strings) / sizeof(strings[0]); ++i) {
|
||||
const char * str = strings[i] ? strings[i] : "";
|
||||
uint16_t len = (uint16_t)strlen(str);
|
||||
sea::WriteJit(&len, sizeof(len));
|
||||
sea::WriteJit(str, len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
switch (event_type) {
|
||||
case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
|
||||
sea::WriteJit(&(uint32_t)methodData->method_id, sizeof(uint32_t));
|
||||
sea::WriteJit(&methodData->method_load_address, sizeof(void*));
|
||||
sea::WriteJit(&(uint32_t)methodData->method_size, sizeof(uint32_t));
|
||||
sea::WriteJit(&(uint32_t)methodData->line_number_size, sizeof(uint32_t));
|
||||
for (unsigned int i = 0; i < methodData->line_number_size; ++i) {
|
||||
const LineNumberInfo& lni = methodData->line_number_table[i];
|
||||
sea::WriteJit(&(uint32_t)lni.Offset, sizeof(uint32_t));
|
||||
sea::WriteJit(&(uint32_t)lni.LineNumber, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
return 0;
|
||||
const char* strings[] = {methodData->method_name, methodData->class_file_name, methodData->source_file_name};
|
||||
for (size_t i = 0; i < sizeof(strings) / sizeof(strings[0]); ++i) {
|
||||
const char* str = strings[i] ? strings[i] : "";
|
||||
uint16_t len = (uint16_t)strlen(str);
|
||||
sea::WriteJit(&len, sizeof(len));
|
||||
sea::WriteJit(str, len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SEA_EXPORT int Initialize() {
|
||||
__itt_api_init(GetITTGlobal(), __itt_group_none);
|
||||
sea::InitJit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
SEA_EXPORT int Initialize() {
|
||||
__itt_api_init(GetITTGlobal(), __itt_group_none);
|
||||
sea::InitJit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -363,4 +356,3 @@ void Test() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user