Kai Nacke b7279ed5b3
[SystemZ][XRay] Make xray work with gcc (#126154)
It seems that depending on the platform, gcc acceptts or does not accept
`-mvx` without specifying an architecture actually having vector
instructions. The solution which seems to work across different versions
of gcc and clang is to specify the least architecture which has vector
instructions.

In addition, initialization of the unused variable CPU prevents a
compiler warning from gcc.
2025-02-06 19:00:20 -05:00

121 lines
3.5 KiB
C++

//===-- xray_tsc.h ----------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of XRay, a dynamic runtime instrumentation system.
//
//===----------------------------------------------------------------------===//
#ifndef XRAY_EMULATE_TSC_H
#define XRAY_EMULATE_TSC_H
#include "sanitizer_common/sanitizer_common.h"
namespace __xray {
static constexpr uint64_t NanosecondsPerSecond = 1000ULL * 1000 * 1000;
}
#if SANITIZER_FUCHSIA
#include <zircon/syscalls.h>
namespace __xray {
inline bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; }
ALWAYS_INLINE uint64_t readTSC(uint8_t &CPU) XRAY_NEVER_INSTRUMENT {
CPU = 0;
return _zx_ticks_get();
}
inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
return _zx_ticks_per_second();
}
} // namespace __xray
#else // SANITIZER_FUCHSIA
#if defined(__x86_64__)
#include "xray_x86_64.inc"
#elif defined(__powerpc64__)
#include "xray_powerpc64.inc"
#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
defined(__hexagon__) || defined(__loongarch_lp64) || defined(__riscv)
// Emulated TSC.
// 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.
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "xray_defs.h"
#include <cerrno>
#include <cstdint>
#include <time.h>
namespace __xray {
inline bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; }
ALWAYS_INLINE uint64_t readTSC(uint8_t &CPU) XRAY_NEVER_INSTRUMENT {
timespec TS;
int result = clock_gettime(CLOCK_REALTIME, &TS);
if (result != 0) {
Report("clock_gettime(2) returned %d, errno=%d.", result, int(errno));
TS.tv_sec = 0;
TS.tv_nsec = 0;
}
CPU = 0;
return TS.tv_sec * NanosecondsPerSecond + TS.tv_nsec;
}
inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
return NanosecondsPerSecond;
}
} // namespace __xray
#elif defined(__s390x__)
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "xray_defs.h"
#include <cerrno>
#include <cstdint>
#include <time.h>
namespace __xray {
inline bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; }
ALWAYS_INLINE uint64_t readTSC(uint8_t &CPU) XRAY_NEVER_INSTRUMENT {
CPU = 0;
#if __has_builtin(__builtin_readcyclecounter)
return __builtin_readcyclecounter();
#else
uint64_t Cycles;
asm volatile("stckf %0" : : "Q"(Cycles) : "cc");
return Cycles;
#endif
}
inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
return NanosecondsPerSecond;
}
} // namespace __xray
#else
#error Target architecture is not supported.
#endif // CPU architecture
#endif // SANITIZER_FUCHSIA
#endif // XRAY_EMULATE_TSC_H