1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

Make the TSC architecture-agnostic and adjust CMakeLists

- Add a separate section for architecture-agnostic timing using CLOCK MONOTONIC (Linux specific)
- Add a specific variant for the initialization of the TSC structure
- Move the file to the linux-only section in the CMakeLists file

Signed-off-by: Leonardo Carreras <leonardo.carreras@eonerc.rwth-aachen.de>
This commit is contained in:
Leonardo Carreras 2025-02-03 16:41:13 +00:00
parent a290af4f3a
commit e2818c33a5
3 changed files with 45 additions and 16 deletions

View file

@ -1,4 +1,4 @@
/* Measure time and sleep with IA-32 time-stamp counter.
/* Measure time and sleep with IA-32 time-stamp counter (x86) or a generic cycle-based timing.
*
* Author: Steffen Vogel <post@steffenvogel.de>
* SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
@ -7,11 +7,10 @@
#pragma once
#if !(__x86_64__ || __i386__)
#error this header is for x86 only
#endif
#include <cinttypes>
#if defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>
#include <x86intrin.h>
@ -24,17 +23,41 @@
#define bit_TSC_INVARIANT (1 << 8)
#define bit_RDTSCP (1 << 27)
#else
#include <time.h>
#ifndef NSEC_PER_SEC
#define NSEC_PER_SEC 1000000000L
#endif
#ifndef CLOCK_MONOTONIC_RAW
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC // Fallback for macOS/BSD
#endif
#endif
struct Tsc {
uint64_t frequency;
#if defined(__x86_64__) || defined(__i386__)
bool rdtscp_supported;
bool is_invariant;
#endif
};
#if defined(__x86_64__) || defined(__i386__)
__attribute__((unused)) static uint64_t tsc_now(struct Tsc *t) {
uint32_t tsc_aux;
return t->rdtscp_supported ? __rdtscp(&tsc_aux) : __rdtsc();
}
#else
// Fallback for CLOCK_MONOTONIC_RAW (linux/BSD/mac specific)
__attribute__((unused)) static uint64_t tsc_now(struct Tsc *t) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
return (ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec) * t->frequency / NSEC_PER_SEC;
}
#endif
int tsc_init(struct Tsc *t) __attribute__((warn_unused_result));

View file

@ -33,10 +33,6 @@ add_library(villas-common SHARED
version.cpp
)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
target_sources(villas-common PRIVATE tsc.cpp)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL Linux)
target_sources(villas-common PRIVATE
kernel/devices/ip_device.cpp
@ -46,6 +42,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux)
kernel/vfio_device.cpp
kernel/vfio_group.cpp
kernel/vfio_container.cpp
tsc.cpp
)
endif()

View file

@ -7,9 +7,8 @@
#include <villas/tsc.hpp>
using namespace villas;
int tsc_init(struct Tsc *t) {
#if defined(__x86_64__) || defined(__i386__)
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
// Check if TSC is supported
@ -32,15 +31,25 @@ int tsc_init(struct Tsc *t) {
if (ecx != 0)
t->frequency = ecx * ebx / eax;
else {
int ret;
#ifdef __linux__
ret = kernel::get_cpu_frequency(&t->frequency);
int ret = kernel::get_cpu_frequency(&t->frequency);
if (ret)
return ret;
#endif
}
return 0;
#elif defined(__aarch64__)
// Read counter frequency from system register
uint64_t cntfrq;
asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq));
t->frequency = cntfrq;
#else
#ifdef __linux__
int ret = kernel::get_cpu_frequency(&t->frequency);
if (ret)
return ret;
#endif
#endif
return (int)(t->frequency);
}
uint64_t tsc_rate_to_cycles(struct Tsc *t, double rate) {