Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #define _GNU_SOURCE
0003 #include <sched.h>
0004 
0005 #include <sys/timerfd.h>
0006 #include <sys/syscall.h>
0007 #include <sys/types.h>
0008 #include <sys/wait.h>
0009 #include <time.h>
0010 #include <unistd.h>
0011 #include <stdlib.h>
0012 #include <stdio.h>
0013 #include <stdint.h>
0014 
0015 #include "log.h"
0016 #include "timens.h"
0017 
0018 static int tclock_gettime(clock_t clockid, struct timespec *now)
0019 {
0020     if (clockid == CLOCK_BOOTTIME_ALARM)
0021         clockid = CLOCK_BOOTTIME;
0022     return clock_gettime(clockid, now);
0023 }
0024 
0025 int run_test(int clockid, struct timespec now)
0026 {
0027     struct itimerspec new_value;
0028     long long elapsed;
0029     int fd, i;
0030 
0031     if (check_skip(clockid))
0032         return 0;
0033 
0034     if (tclock_gettime(clockid, &now))
0035         return pr_perror("clock_gettime(%d)", clockid);
0036 
0037     for (i = 0; i < 2; i++) {
0038         int flags = 0;
0039 
0040         new_value.it_value.tv_sec = 3600;
0041         new_value.it_value.tv_nsec = 0;
0042         new_value.it_interval.tv_sec = 1;
0043         new_value.it_interval.tv_nsec = 0;
0044 
0045         if (i == 1) {
0046             new_value.it_value.tv_sec += now.tv_sec;
0047             new_value.it_value.tv_nsec += now.tv_nsec;
0048         }
0049 
0050         fd = timerfd_create(clockid, 0);
0051         if (fd == -1)
0052             return pr_perror("timerfd_create(%d)", clockid);
0053 
0054         if (i == 1)
0055             flags |= TFD_TIMER_ABSTIME;
0056 
0057         if (timerfd_settime(fd, flags, &new_value, NULL))
0058             return pr_perror("timerfd_settime(%d)", clockid);
0059 
0060         if (timerfd_gettime(fd, &new_value))
0061             return pr_perror("timerfd_gettime(%d)", clockid);
0062 
0063         elapsed = new_value.it_value.tv_sec;
0064         if (abs(elapsed - 3600) > 60) {
0065             ksft_test_result_fail("clockid: %d elapsed: %lld\n",
0066                           clockid, elapsed);
0067             return 1;
0068         }
0069 
0070         close(fd);
0071     }
0072 
0073     ksft_test_result_pass("clockid=%d\n", clockid);
0074 
0075     return 0;
0076 }
0077 
0078 int main(int argc, char *argv[])
0079 {
0080     int ret, status, len, fd;
0081     char buf[4096];
0082     pid_t pid;
0083     struct timespec btime_now, mtime_now;
0084 
0085     nscheck();
0086 
0087     check_supported_timers();
0088 
0089     ksft_set_plan(3);
0090 
0091     clock_gettime(CLOCK_MONOTONIC, &mtime_now);
0092     clock_gettime(CLOCK_BOOTTIME, &btime_now);
0093 
0094     if (unshare_timens())
0095         return 1;
0096 
0097     len = snprintf(buf, sizeof(buf), "%d %d 0\n%d %d 0",
0098             CLOCK_MONOTONIC, 70 * 24 * 3600,
0099             CLOCK_BOOTTIME, 9 * 24 * 3600);
0100     fd = open("/proc/self/timens_offsets", O_WRONLY);
0101     if (fd < 0)
0102         return pr_perror("/proc/self/timens_offsets");
0103 
0104     if (write(fd, buf, len) != len)
0105         return pr_perror("/proc/self/timens_offsets");
0106 
0107     close(fd);
0108     mtime_now.tv_sec += 70 * 24 * 3600;
0109     btime_now.tv_sec += 9 * 24 * 3600;
0110 
0111     pid = fork();
0112     if (pid < 0)
0113         return pr_perror("Unable to fork");
0114     if (pid == 0) {
0115         ret = 0;
0116         ret |= run_test(CLOCK_BOOTTIME, btime_now);
0117         ret |= run_test(CLOCK_MONOTONIC, mtime_now);
0118         ret |= run_test(CLOCK_BOOTTIME_ALARM, btime_now);
0119 
0120         if (ret)
0121             ksft_exit_fail();
0122         ksft_exit_pass();
0123         return ret;
0124     }
0125 
0126     if (waitpid(pid, &status, 0) != pid)
0127         return pr_perror("Unable to wait the child process");
0128 
0129     if (WIFEXITED(status))
0130         return WEXITSTATUS(status);
0131 
0132     return 1;
0133 }