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 <time.h>
0008 #include <unistd.h>
0009 #include <stdlib.h>
0010 #include <stdio.h>
0011 #include <stdint.h>
0012 #include <pthread.h>
0013 #include <signal.h>
0014 #include <string.h>
0015 
0016 #include "log.h"
0017 #include "timens.h"
0018 
0019 void test_sig(int sig)
0020 {
0021     if (sig == SIGUSR2)
0022         pthread_exit(NULL);
0023 }
0024 
0025 struct thread_args {
0026     struct timespec *now, *rem;
0027     pthread_mutex_t *lock;
0028     int clockid;
0029     int abs;
0030 };
0031 
0032 void *call_nanosleep(void *_args)
0033 {
0034     struct thread_args *args = _args;
0035 
0036     clock_nanosleep(args->clockid, args->abs ? TIMER_ABSTIME : 0, args->now, args->rem);
0037     pthread_mutex_unlock(args->lock);
0038     return NULL;
0039 }
0040 
0041 int run_test(int clockid, int abs)
0042 {
0043     struct timespec now = {}, rem;
0044     struct thread_args args = { .now = &now, .rem = &rem, .clockid = clockid};
0045     struct timespec start;
0046     pthread_mutex_t lock;
0047     pthread_t thread;
0048     int j, ok, ret;
0049 
0050     signal(SIGUSR1, test_sig);
0051     signal(SIGUSR2, test_sig);
0052 
0053     pthread_mutex_init(&lock, NULL);
0054     pthread_mutex_lock(&lock);
0055 
0056     if (clock_gettime(clockid, &start) == -1) {
0057         if (errno == EINVAL && check_skip(clockid))
0058             return 0;
0059         return pr_perror("clock_gettime");
0060     }
0061 
0062 
0063     if (abs) {
0064         now.tv_sec = start.tv_sec;
0065         now.tv_nsec = start.tv_nsec;
0066     }
0067 
0068     now.tv_sec += 3600;
0069     args.abs = abs;
0070     args.lock = &lock;
0071     ret = pthread_create(&thread, NULL, call_nanosleep, &args);
0072     if (ret != 0) {
0073         pr_err("Unable to create a thread: %s", strerror(ret));
0074         return 1;
0075     }
0076 
0077     /* Wait when the thread will call clock_nanosleep(). */
0078     ok = 0;
0079     for (j = 0; j < 8; j++) {
0080         /* The maximum timeout is about 5 seconds. */
0081         usleep(10000 << j);
0082 
0083         /* Try to interrupt clock_nanosleep(). */
0084         pthread_kill(thread, SIGUSR1);
0085 
0086         usleep(10000 << j);
0087         /* Check whether clock_nanosleep() has been interrupted or not. */
0088         if (pthread_mutex_trylock(&lock) == 0) {
0089             /**/
0090             ok = 1;
0091             break;
0092         }
0093     }
0094     if (!ok)
0095         pthread_kill(thread, SIGUSR2);
0096     pthread_join(thread, NULL);
0097     pthread_mutex_destroy(&lock);
0098 
0099     if (!ok) {
0100         ksft_test_result_pass("clockid: %d abs:%d timeout\n", clockid, abs);
0101         return 1;
0102     }
0103 
0104     if (rem.tv_sec < 3300 || rem.tv_sec > 3900) {
0105         pr_fail("clockid: %d abs: %d remain: %ld\n",
0106             clockid, abs, rem.tv_sec);
0107         return 1;
0108     }
0109     ksft_test_result_pass("clockid: %d abs:%d\n", clockid, abs);
0110 
0111     return 0;
0112 }
0113 
0114 int main(int argc, char *argv[])
0115 {
0116     int ret, nsfd;
0117 
0118     nscheck();
0119 
0120     ksft_set_plan(4);
0121 
0122     check_supported_timers();
0123 
0124     if (unshare_timens())
0125         return 1;
0126 
0127     if (_settime(CLOCK_MONOTONIC, 7 * 24 * 3600))
0128         return 1;
0129     if (_settime(CLOCK_BOOTTIME, 9 * 24 * 3600))
0130         return 1;
0131 
0132     nsfd = open("/proc/self/ns/time_for_children", O_RDONLY);
0133     if (nsfd < 0)
0134         return pr_perror("Unable to open timens_for_children");
0135 
0136     if (setns(nsfd, CLONE_NEWTIME))
0137         return pr_perror("Unable to set timens");
0138 
0139     ret = 0;
0140     ret |= run_test(CLOCK_MONOTONIC, 0);
0141     ret |= run_test(CLOCK_MONOTONIC, 1);
0142     ret |= run_test(CLOCK_BOOTTIME_ALARM, 0);
0143     ret |= run_test(CLOCK_BOOTTIME_ALARM, 1);
0144 
0145     if (ret)
0146         ksft_exit_fail();
0147     ksft_exit_pass();
0148     return ret;
0149 }