linux/tools/testing/selftests/timens/timer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#define _GNU_SOURCE
   3#include <sched.h>
   4
   5#include <sys/syscall.h>
   6#include <sys/types.h>
   7#include <sys/wait.h>
   8#include <time.h>
   9#include <unistd.h>
  10#include <stdlib.h>
  11#include <stdio.h>
  12#include <stdint.h>
  13#include <signal.h>
  14
  15#include "log.h"
  16#include "timens.h"
  17
  18int run_test(int clockid, struct timespec now)
  19{
  20        struct itimerspec new_value;
  21        long long elapsed;
  22        timer_t fd;
  23        int i;
  24
  25        if (check_skip(clockid))
  26                return 0;
  27
  28        for (i = 0; i < 2; i++) {
  29                struct sigevent sevp = {.sigev_notify = SIGEV_NONE};
  30                int flags = 0;
  31
  32                new_value.it_value.tv_sec = 3600;
  33                new_value.it_value.tv_nsec = 0;
  34                new_value.it_interval.tv_sec = 1;
  35                new_value.it_interval.tv_nsec = 0;
  36
  37                if (i == 1) {
  38                        new_value.it_value.tv_sec += now.tv_sec;
  39                        new_value.it_value.tv_nsec += now.tv_nsec;
  40                }
  41
  42                if (timer_create(clockid, &sevp, &fd) == -1) {
  43                        if (errno == ENOSYS) {
  44                                ksft_test_result_skip("Posix Clocks & timers are supported\n");
  45                                return 0;
  46                        }
  47                        return pr_perror("timerfd_create");
  48                }
  49
  50                if (i == 1)
  51                        flags |= TIMER_ABSTIME;
  52                if (timer_settime(fd, flags, &new_value, NULL) == -1)
  53                        return pr_perror("timerfd_settime");
  54
  55                if (timer_gettime(fd, &new_value) == -1)
  56                        return pr_perror("timerfd_gettime");
  57
  58                elapsed = new_value.it_value.tv_sec;
  59                if (abs(elapsed - 3600) > 60) {
  60                        ksft_test_result_fail("clockid: %d elapsed: %lld\n",
  61                                              clockid, elapsed);
  62                        return 1;
  63                }
  64        }
  65
  66        ksft_test_result_pass("clockid=%d\n", clockid);
  67
  68        return 0;
  69}
  70
  71int main(int argc, char *argv[])
  72{
  73        int ret, status, len, fd;
  74        char buf[4096];
  75        pid_t pid;
  76        struct timespec btime_now, mtime_now;
  77
  78        nscheck();
  79
  80        check_supported_timers();
  81
  82        ksft_set_plan(3);
  83
  84        clock_gettime(CLOCK_MONOTONIC, &mtime_now);
  85        clock_gettime(CLOCK_BOOTTIME, &btime_now);
  86
  87        if (unshare_timens())
  88                return 1;
  89
  90        len = snprintf(buf, sizeof(buf), "%d %d 0\n%d %d 0",
  91                        CLOCK_MONOTONIC, 70 * 24 * 3600,
  92                        CLOCK_BOOTTIME, 9 * 24 * 3600);
  93        fd = open("/proc/self/timens_offsets", O_WRONLY);
  94        if (fd < 0)
  95                return pr_perror("/proc/self/timens_offsets");
  96
  97        if (write(fd, buf, len) != len)
  98                return pr_perror("/proc/self/timens_offsets");
  99
 100        close(fd);
 101        mtime_now.tv_sec += 70 * 24 * 3600;
 102        btime_now.tv_sec += 9 * 24 * 3600;
 103
 104        pid = fork();
 105        if (pid < 0)
 106                return pr_perror("Unable to fork");
 107        if (pid == 0) {
 108                ret = 0;
 109                ret |= run_test(CLOCK_BOOTTIME, btime_now);
 110                ret |= run_test(CLOCK_MONOTONIC, mtime_now);
 111                ret |= run_test(CLOCK_BOOTTIME_ALARM, btime_now);
 112
 113                if (ret)
 114                        ksft_exit_fail();
 115                ksft_exit_pass();
 116                return ret;
 117        }
 118
 119        if (waitpid(pid, &status, 0) != pid)
 120                return pr_perror("Unable to wait the child process");
 121
 122        if (WIFEXITED(status))
 123                return WEXITSTATUS(status);
 124
 125        return 1;
 126}
 127