diff options
Diffstat (limited to 'lib/xray/xray_inmemory_log.cc')
-rw-r--r-- | lib/xray/xray_inmemory_log.cc | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/lib/xray/xray_inmemory_log.cc b/lib/xray/xray_inmemory_log.cc index f4fd20846..286ba7122 100644 --- a/lib/xray/xray_inmemory_log.cc +++ b/lib/xray/xray_inmemory_log.cc @@ -24,7 +24,14 @@ #include <sys/types.h> #include <thread> #include <unistd.h> -#include <x86intrin.h> + +#if defined(__x86_64__) + #include <x86intrin.h> +#elif defined(__arm__) + static const int64_t NanosecondsPerSecond = 1000LL*1000*1000; +#else + #error "Unsupported CPU Architecture" +#endif /* CPU architecture */ #include "sanitizer_common/sanitizer_libc.h" #include "xray/xray_records.h" @@ -61,6 +68,7 @@ static void retryingWriteAll(int Fd, char *Begin, char *End) { } } +#if defined(__x86_64__) static std::pair<ssize_t, bool> retryingReadSome(int Fd, char *Begin, char *End) { auto BytesToRead = std::distance(Begin, End); @@ -103,6 +111,8 @@ static bool readValueFromFile(const char *Filename, long long *Value) { return Result; } +#endif /* CPU architecture */ + class ThreadExitFlusher { int Fd; XRayRecord *Start; @@ -164,6 +174,7 @@ void __xray_InMemoryRawLog(int32_t FuncId, XRayEntryType Type) { // Get the cycle frequency from SysFS on Linux. long long CPUFrequency = -1; +#if defined(__x86_64__) if (readValueFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &CPUFrequency)) { CPUFrequency *= 1000; @@ -174,6 +185,20 @@ void __xray_InMemoryRawLog(int32_t FuncId, XRayEntryType Type) { } else { Report("Unable to determine CPU frequency for TSC accounting."); } +#elif defined(__arm__) + // There is no instruction like RDTSCP in user mode on ARM. ARM's CP15 does + // not have a constant frequency like TSC on x86(_64), it may go faster + // or slower depending on CPU turbo or power saving mode. Furthermore, + // to read from CP15 on ARM a kernel modification or a driver is needed. + // We can not require this from users of compiler-rt. + // So on ARM we use clock_gettime() which gives the result in nanoseconds. + // To get the measurements per second, we scale this by the number of + // nanoseconds per second, pretending that the TSC frequency is 1GHz and + // one TSC tick is 1 nanosecond. + CPUFrequency = NanosecondsPerSecond; +#else + #error "Unsupported CPU Architecture" +#endif /* CPU architecture */ // Since we're here, we get to write the header. We set it up so that the // header will only be written once, at the start, and let the threads @@ -201,10 +226,29 @@ void __xray_InMemoryRawLog(int32_t FuncId, XRayEntryType Type) { // First we get the useful data, and stuff it into the already aligned buffer // through a pointer offset. auto &R = reinterpret_cast<__xray::XRayRecord *>(InMemoryBuffer)[Offset]; - unsigned CPU; R.RecordType = RecordTypes::NORMAL; - R.TSC = __rdtscp(&CPU); - R.CPU = CPU; +#if defined(__x86_64__) + { + unsigned CPU; + R.TSC = __rdtscp(&CPU); + R.CPU = CPU; + } +#elif defined(__arm__) + { + timespec TS; + int result = clock_gettime(CLOCK_REALTIME, &TS); + if(result != 0) + { + Report("clock_gettime() returned %d, errno=%d.", result, int(errno)); + TS.tv_sec = 0; + TS.tv_nsec = 0; + } + R.TSC = TS.tv_sec * NanosecondsPerSecond + TS.tv_nsec; + R.CPU = 0; + } +#else + #error "Unsupported CPU Architecture" +#endif /* CPU architecture */ R.TId = TId; R.Type = Type; R.FuncId = FuncId; |