libtopo/timestamp.c

64 lines
1.2 KiB
C

#include <stdint.h>
#ifdef __amd64__
#include <immintrin.h>
#include <x86intrin.h>
#include <sys/sysctl.h>
#endif
#include <errno.h>
#include "topo.h"
#include "topop.h"
#define S2NS (1000000000UL)
#ifdef __amd64__
static uint64_t
tsc2ns(uint64_t tsc, uint64_t tsc_freq)
{
return (uint64_t)(
(double)tsc / (double)tsc_freq * S2NS);
}
#endif
int
topo_ts_init(struct topo_desc * desc, int verbose)
{
#ifdef __amd64__
int rc;
size_t sz = sizeof(desc->tsc_freq);
// init nm_tsc2ns
if ((rc = sysctlbyname("machdep.tsc_freq", &desc->tsc_freq, &sz, NULL, 0)) < 0) {
fprintf(stderr,"libtopo: failed to query tsc frequency via sysctl (%d)\n", errno);
} else {
if (verbose) {
fprintf(stdout,"libtopo: tsc frequency = %lu\n", desc->tsc_freq);
}
}
return rc;
#else
(void)desc;
(void)verbose;
return 0;
#endif
}
uint64_t
topo_desc_uptime_ns(struct topo_desc * desc)
{
#ifdef __amd64__
unsigned int dummy;
_mm_lfence();
uint64_t tsc = __rdtscp(&dummy);
_mm_lfence();
return tsc2ns(tsc, desc->tsc_freq);
#else
(void)desc;
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return ((uint64_t)tp.tv_sec * S2NS + (uint64_t)tp.tv_nsec);
#endif
}