summaryrefslogtreecommitdiff
path: root/lib/xray/xray_inmemory_log.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xray/xray_inmemory_log.cc')
-rw-r--r--lib/xray/xray_inmemory_log.cc52
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;