162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#define _GNU_SOURCE 362306a36Sopenharmony_ci#include <sched.h> 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <sys/timerfd.h> 662306a36Sopenharmony_ci#include <sys/syscall.h> 762306a36Sopenharmony_ci#include <time.h> 862306a36Sopenharmony_ci#include <unistd.h> 962306a36Sopenharmony_ci#include <stdlib.h> 1062306a36Sopenharmony_ci#include <stdio.h> 1162306a36Sopenharmony_ci#include <stdint.h> 1262306a36Sopenharmony_ci#include <pthread.h> 1362306a36Sopenharmony_ci#include <signal.h> 1462306a36Sopenharmony_ci#include <string.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "log.h" 1762306a36Sopenharmony_ci#include "timens.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_civoid test_sig(int sig) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci if (sig == SIGUSR2) 2262306a36Sopenharmony_ci pthread_exit(NULL); 2362306a36Sopenharmony_ci} 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct thread_args { 2662306a36Sopenharmony_ci struct timespec *now, *rem; 2762306a36Sopenharmony_ci pthread_mutex_t *lock; 2862306a36Sopenharmony_ci int clockid; 2962306a36Sopenharmony_ci int abs; 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_civoid *call_nanosleep(void *_args) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci struct thread_args *args = _args; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci clock_nanosleep(args->clockid, args->abs ? TIMER_ABSTIME : 0, args->now, args->rem); 3762306a36Sopenharmony_ci pthread_mutex_unlock(args->lock); 3862306a36Sopenharmony_ci return NULL; 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciint run_test(int clockid, int abs) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci struct timespec now = {}, rem; 4462306a36Sopenharmony_ci struct thread_args args = { .now = &now, .rem = &rem, .clockid = clockid}; 4562306a36Sopenharmony_ci struct timespec start; 4662306a36Sopenharmony_ci pthread_mutex_t lock; 4762306a36Sopenharmony_ci pthread_t thread; 4862306a36Sopenharmony_ci int j, ok, ret; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci signal(SIGUSR1, test_sig); 5162306a36Sopenharmony_ci signal(SIGUSR2, test_sig); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci pthread_mutex_init(&lock, NULL); 5462306a36Sopenharmony_ci pthread_mutex_lock(&lock); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (clock_gettime(clockid, &start) == -1) { 5762306a36Sopenharmony_ci if (errno == EINVAL && check_skip(clockid)) 5862306a36Sopenharmony_ci return 0; 5962306a36Sopenharmony_ci return pr_perror("clock_gettime"); 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (abs) { 6462306a36Sopenharmony_ci now.tv_sec = start.tv_sec; 6562306a36Sopenharmony_ci now.tv_nsec = start.tv_nsec; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci now.tv_sec += 3600; 6962306a36Sopenharmony_ci args.abs = abs; 7062306a36Sopenharmony_ci args.lock = &lock; 7162306a36Sopenharmony_ci ret = pthread_create(&thread, NULL, call_nanosleep, &args); 7262306a36Sopenharmony_ci if (ret != 0) { 7362306a36Sopenharmony_ci pr_err("Unable to create a thread: %s", strerror(ret)); 7462306a36Sopenharmony_ci return 1; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci /* Wait when the thread will call clock_nanosleep(). */ 7862306a36Sopenharmony_ci ok = 0; 7962306a36Sopenharmony_ci for (j = 0; j < 8; j++) { 8062306a36Sopenharmony_ci /* The maximum timeout is about 5 seconds. */ 8162306a36Sopenharmony_ci usleep(10000 << j); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* Try to interrupt clock_nanosleep(). */ 8462306a36Sopenharmony_ci pthread_kill(thread, SIGUSR1); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci usleep(10000 << j); 8762306a36Sopenharmony_ci /* Check whether clock_nanosleep() has been interrupted or not. */ 8862306a36Sopenharmony_ci if (pthread_mutex_trylock(&lock) == 0) { 8962306a36Sopenharmony_ci /**/ 9062306a36Sopenharmony_ci ok = 1; 9162306a36Sopenharmony_ci break; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci if (!ok) 9562306a36Sopenharmony_ci pthread_kill(thread, SIGUSR2); 9662306a36Sopenharmony_ci pthread_join(thread, NULL); 9762306a36Sopenharmony_ci pthread_mutex_destroy(&lock); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if (!ok) { 10062306a36Sopenharmony_ci ksft_test_result_pass("clockid: %d abs:%d timeout\n", clockid, abs); 10162306a36Sopenharmony_ci return 1; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (rem.tv_sec < 3300 || rem.tv_sec > 3900) { 10562306a36Sopenharmony_ci pr_fail("clockid: %d abs: %d remain: %ld\n", 10662306a36Sopenharmony_ci clockid, abs, rem.tv_sec); 10762306a36Sopenharmony_ci return 1; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci ksft_test_result_pass("clockid: %d abs:%d\n", clockid, abs); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci return 0; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciint main(int argc, char *argv[]) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci int ret, nsfd; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci nscheck(); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci ksft_set_plan(4); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci check_supported_timers(); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (unshare_timens()) 12562306a36Sopenharmony_ci return 1; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (_settime(CLOCK_MONOTONIC, 7 * 24 * 3600)) 12862306a36Sopenharmony_ci return 1; 12962306a36Sopenharmony_ci if (_settime(CLOCK_BOOTTIME, 9 * 24 * 3600)) 13062306a36Sopenharmony_ci return 1; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci nsfd = open("/proc/self/ns/time_for_children", O_RDONLY); 13362306a36Sopenharmony_ci if (nsfd < 0) 13462306a36Sopenharmony_ci return pr_perror("Unable to open timens_for_children"); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (setns(nsfd, CLONE_NEWTIME)) 13762306a36Sopenharmony_ci return pr_perror("Unable to set timens"); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci ret = 0; 14062306a36Sopenharmony_ci ret |= run_test(CLOCK_MONOTONIC, 0); 14162306a36Sopenharmony_ci ret |= run_test(CLOCK_MONOTONIC, 1); 14262306a36Sopenharmony_ci ret |= run_test(CLOCK_BOOTTIME_ALARM, 0); 14362306a36Sopenharmony_ci ret |= run_test(CLOCK_BOOTTIME_ALARM, 1); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci if (ret) 14662306a36Sopenharmony_ci ksft_exit_fail(); 14762306a36Sopenharmony_ci ksft_exit_pass(); 14862306a36Sopenharmony_ci return ret; 14962306a36Sopenharmony_ci} 150