linux/tools/testing/selftests/timens/gettime_perf.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#define _GNU_SOURCE
   3#include <sys/types.h>
   4#include <sys/stat.h>
   5#include <errno.h>
   6#include <fcntl.h>
   7#include <sched.h>
   8#include <time.h>
   9#include <stdio.h>
  10#include <unistd.h>
  11#include <sys/syscall.h>
  12#include <dlfcn.h>
  13
  14#include "log.h"
  15#include "timens.h"
  16
  17typedef int (*vgettime_t)(clockid_t, struct timespec *);
  18
  19vgettime_t vdso_clock_gettime;
  20
  21static void fill_function_pointers(void)
  22{
  23        void *vdso = dlopen("linux-vdso.so.1",
  24                            RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
  25        if (!vdso)
  26                vdso = dlopen("linux-gate.so.1",
  27                              RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
  28        if (!vdso) {
  29                pr_err("[WARN]\tfailed to find vDSO\n");
  30                return;
  31        }
  32
  33        vdso_clock_gettime = (vgettime_t)dlsym(vdso, "__vdso_clock_gettime");
  34        if (!vdso_clock_gettime)
  35                pr_err("Warning: failed to find clock_gettime in vDSO\n");
  36
  37}
  38
  39static void test(clock_t clockid, char *clockstr, bool in_ns)
  40{
  41        struct timespec tp, start;
  42        long i = 0;
  43        const int timeout = 3;
  44
  45        vdso_clock_gettime(clockid, &start);
  46        tp = start;
  47        for (tp = start; start.tv_sec + timeout > tp.tv_sec ||
  48                         (start.tv_sec + timeout == tp.tv_sec &&
  49                          start.tv_nsec > tp.tv_nsec); i++) {
  50                vdso_clock_gettime(clockid, &tp);
  51        }
  52
  53        ksft_test_result_pass("%s:\tclock: %10s\tcycles:\t%10ld\n",
  54                              in_ns ? "ns" : "host", clockstr, i);
  55}
  56
  57int main(int argc, char *argv[])
  58{
  59        time_t offset = 10;
  60        int nsfd;
  61
  62        ksft_set_plan(8);
  63
  64        fill_function_pointers();
  65
  66        test(CLOCK_MONOTONIC, "monotonic", false);
  67        test(CLOCK_MONOTONIC_COARSE, "monotonic-coarse", false);
  68        test(CLOCK_MONOTONIC_RAW, "monotonic-raw", false);
  69        test(CLOCK_BOOTTIME, "boottime", false);
  70
  71        nscheck();
  72
  73        if (unshare_timens())
  74                return 1;
  75
  76        nsfd = open("/proc/self/ns/time_for_children", O_RDONLY);
  77        if (nsfd < 0)
  78                return pr_perror("Can't open a time namespace");
  79
  80        if (_settime(CLOCK_MONOTONIC, offset))
  81                return 1;
  82        if (_settime(CLOCK_BOOTTIME, offset))
  83                return 1;
  84
  85        if (setns(nsfd, CLONE_NEWTIME))
  86                return pr_perror("setns");
  87
  88        test(CLOCK_MONOTONIC, "monotonic", true);
  89        test(CLOCK_MONOTONIC_COARSE, "monotonic-coarse", true);
  90        test(CLOCK_MONOTONIC_RAW, "monotonic-raw", true);
  91        test(CLOCK_BOOTTIME, "boottime", true);
  92
  93        ksft_exit_pass();
  94        return 0;
  95}
  96