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:
Ilya Churaev 2021-03-23 15:08:51 +03:00 committed by GitHub
parent 3672fb9817
commit 3ee41375a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1166 additions and 1231 deletions

View File

@ -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
View 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
---

View File

@ -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})

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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;
}
};
};

View File

@ -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

View File

@ -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();
}

View File

@ -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