[XRay][compiler-rt] Support TSC emulation even for x86_64

Summary:
Use TSC emulation in cases where RDTSCP isn't available on the host
running an XRay instrumented binary. We can then fall back into
emulation instead of not even installing XRay's runtime functionality.
We only do this for now in the naive/basic logging implementation, but
should be useful in even FDR mode.

Should fix http://llvm.org/PR32148.

Reviewers: pelikan, rnk, sdardis

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D30677

llvm-svn: 297800
This commit is contained in:
Dean Michael Berris 2017-03-15 02:28:00 +00:00
parent 842c707d7c
commit 66443d80f1
2 changed files with 37 additions and 14 deletions

View File

@ -77,7 +77,6 @@ using namespace __xray;
static int __xray_OpenLogFile() XRAY_NEVER_INSTRUMENT {
int F = getLogFD();
auto TSCFrequency = getTSCFrequency();
if (F == -1)
return -1;
// Since we're here, we get to write the header. We set it up so that the
@ -86,7 +85,9 @@ static int __xray_OpenLogFile() XRAY_NEVER_INSTRUMENT {
XRayFileHeader Header;
Header.Version = 1;
Header.Type = FileTypes::NAIVE_LOG;
Header.CycleFrequency = TSCFrequency;
Header.CycleFrequency = probeRequiredCPUFeatures()
? getTSCFrequency()
: __xray::NanosecondsPerSecond;
// FIXME: Actually check whether we have 'constant_tsc' and 'nonstop_tsc'
// before setting the values in the header.
@ -97,8 +98,9 @@ static int __xray_OpenLogFile() XRAY_NEVER_INSTRUMENT {
return F;
}
void __xray_InMemoryRawLog(int32_t FuncId,
XRayEntryType Type) XRAY_NEVER_INSTRUMENT {
template <class RDTSC>
void __xray_InMemoryRawLog(int32_t FuncId, XRayEntryType Type,
RDTSC ReadTSC) XRAY_NEVER_INSTRUMENT {
using Buffer =
std::aligned_storage<sizeof(XRayRecord), alignof(XRayRecord)>::type;
static constexpr size_t BuffLen = 1024;
@ -115,7 +117,7 @@ void __xray_InMemoryRawLog(int32_t FuncId,
// through a pointer offset.
auto &R = reinterpret_cast<__xray::XRayRecord *>(InMemoryBuffer)[Offset];
R.RecordType = RecordTypes::NORMAL;
R.TSC = __xray::readTSC(R.CPU);
R.TSC = ReadTSC(R.CPU);
R.TId = TId;
R.Type = Type;
R.FuncId = FuncId;
@ -129,13 +131,32 @@ void __xray_InMemoryRawLog(int32_t FuncId,
}
}
void __xray_InMemoryRawLogRealTSC(int32_t FuncId,
XRayEntryType Type) XRAY_NEVER_INSTRUMENT {
__xray_InMemoryRawLog(FuncId, Type, __xray::readTSC);
}
void __xray_InMemoryEmulateTSC(int32_t FuncId,
XRayEntryType Type) XRAY_NEVER_INSTRUMENT {
__xray_InMemoryRawLog(FuncId, Type, [](uint8_t &CPU) XRAY_NEVER_INSTRUMENT {
timespec TS;
int result = clock_gettime(CLOCK_REALTIME, &TS);
if (result != 0) {
Report("clock_gettimg(2) return %d, errno=%d.", result, int(errno));
TS = {0, 0};
}
CPU = 0;
return TS.tv_sec * __xray::NanosecondsPerSecond + TS.tv_nsec;
});
}
static auto UNUSED Unused = [] {
if (!probeRequiredCPUFeatures()) {
Report("Required CPU features missing for XRay instrumentation, not "
"installing instrumentation hooks.\n");
return false;
}
auto UseRealTSC = probeRequiredCPUFeatures();
if (!UseRealTSC)
Report("WARNING: Required CPU features missing for XRay instrumentation, "
"using emulation instead.\n");
if (flags()->xray_naive_log)
__xray_set_handler(__xray_InMemoryRawLog);
__xray_set_handler(UseRealTSC ? __xray_InMemoryRawLogRealTSC
: __xray_InMemoryEmulateTSC);
return true;
}();

View File

@ -13,6 +13,10 @@
#ifndef XRAY_EMULATE_TSC_H
#define XRAY_EMULATE_TSC_H
namespace __xray {
static constexpr uint64_t NanosecondsPerSecond = 1000ULL * 1000 * 1000;
}
#if defined(__x86_64__)
#include "xray_x86_64.inc"
#elif defined(__powerpc64__)
@ -37,8 +41,6 @@
namespace __xray {
static constexpr uint64_t NanosecondsPerSecond = 1000ULL * 1000 * 1000;
inline bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; }
ALWAYS_INLINE uint64_t readTSC(uint8_t &CPU) XRAY_NEVER_INSTRUMENT {
@ -60,7 +62,7 @@ inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
} // namespace __xray
#else
"Unsupported CPU Architecture"
#error Target architecture is not supported.
#endif // CPU architecture
#endif // XRAY_EMULATE_TSC_H