Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
ed366de
Documentation
LICENSES
arch
block
certs
crypto
drivers
fs
include
init
io_uring
ipc
kernel
lib
mm
net
rust
samples
scripts
security
sound
tools
accounting
arch
bootconfig
bpf
build
certs
cgroup
counter
crypto
debugging
firewire
firmware
gpio
hv
iio
include
kvm
laptop
leds
lib
memory-model
mm
net
objtool
pci
pcmcia
perf
power
rcu
scripts
spi
testing
crypto
cxl
fault-injection
ktest
kunit
memblock
nvdimm
radix-tree
scatterlist
selftests
alsa
amd-pstate
arm64
bpf
breakpoints
cachestat
capabilities
cgroup
clone3
connector
core
cpu-hotplug
cpufreq
damon
devices
dma
dmabuf-heaps
drivers
dt
efivarfs
exec
fchmodat2
filelock
filesystems
firmware
fpu
ftrace
futex
gpio
hid
ia64
intel_pstate
iommu
ipc
ir
kcmp
kexec
kmod
kselftest
kvm
landlock
lib
livepatch
lkdtm
locking
lsm
media_tests
membarrier
memfd
memory-hotplug
mincore
mm
mount
mount_setattr
move_mount_set_group
mqueue
nci
net
netfilter
nolibc
nsfs
ntb
openat2
perf_events
pid_namespace
pidfd
power_supply
powerpc
prctl
proc
pstore
ptp
ptrace
rcutorture
resctrl
riscv
rlimits
rseq
rtc
rust
safesetid
sched
seccomp
sgx
sigaltstack
size
sparc64
splice
static_keys
sync
syscall_user_dispatch
sysctl
tc-testing
tdx
thermal
timens
timers
.gitignore
Makefile
adjtick.c
alarmtimer-suspend.c
change_skew.c
clocksource-switch.c
freq-step.c
inconsistency-check.c
leap-a-day.c
leapcrash.c
mqueue-lat.c
nanosleep.c
nsleep-lat.c
posix_timers.c
raw_skew.c
rtcpie.c
set-2038.c
set-tai.c
set-timer-lat.c
set-tz.c
settings
skew_consistency.c
threadtest.c
valid-adjtimex.c
tmpfs
tpm2
tty
uevent
user
user_events
vDSO
watchdog
wireguard
x86
zram
.gitignore
Makefile
gen_kselftest_tar.sh
kselftest.h
kselftest_deps.sh
kselftest_harness.h
kselftest_install.sh
kselftest_module.h
lib.mk
run_kselftest.sh
vsock
thermal
time
tracing
usb
verification
virtio
wmi
workqueue
Makefile
usr
virt
.clang-format
.cocciconfig
.editorconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
.rustfmt.toml
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
tools
/
testing
/
selftests
/
timers
/
posix_timers.c
Blame
Blame
Latest commit
History
History
290 lines (236 loc) · 5.91 KB
Breadcrumbs
linux
/
tools
/
testing
/
selftests
/
timers
/
posix_timers.c
Top
File metadata and controls
Code
Blame
290 lines (236 loc) · 5.91 KB
Raw
// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2013 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com> * * Selftests for a few posix timers interface. * * Kernel loop code stolen from Steven Rostedt <srostedt@redhat.com> */ #include <sys/time.h> #include <stdio.h> #include <signal.h> #include <unistd.h> #include <time.h> #include <pthread.h> #include "../kselftest.h" #define DELAY 2 #define USECS_PER_SEC 1000000 static volatile int done; /* Busy loop in userspace to elapse ITIMER_VIRTUAL */ static void user_loop(void) { while (!done); } /* * Try to spend as much time as possible in kernelspace * to elapse ITIMER_PROF. */ static void kernel_loop(void) { void *addr = sbrk(0); int err = 0; while (!done && !err) { err = brk(addr + 4096); err |= brk(addr); } } /* * Sleep until ITIMER_REAL expiration. */ static void idle_loop(void) { pause(); } static void sig_handler(int nr) { done = 1; } /* * Check the expected timer expiration matches the GTOD elapsed delta since * we armed the timer. Keep a 0.5 sec error margin due to various jitter. */ static int check_diff(struct timeval start, struct timeval end) { long long diff; diff = end.tv_usec - start.tv_usec; diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC; if (llabs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) { printf("Diff too high: %lld..", diff); return -1; } return 0; } static int check_itimer(int which) { const char *name; int err; struct timeval start, end; struct itimerval val = { .it_value.tv_sec = DELAY, }; if (which == ITIMER_VIRTUAL) name = "ITIMER_VIRTUAL"; else if (which == ITIMER_PROF) name = "ITIMER_PROF"; else if (which == ITIMER_REAL) name = "ITIMER_REAL"; else return -1; done = 0; if (which == ITIMER_VIRTUAL) signal(SIGVTALRM, sig_handler); else if (which == ITIMER_PROF) signal(SIGPROF, sig_handler); else if (which == ITIMER_REAL) signal(SIGALRM, sig_handler); err = gettimeofday(&start, NULL); if (err < 0) { ksft_perror("Can't call gettimeofday()"); return -1; } err = setitimer(which, &val, NULL); if (err < 0) { ksft_perror("Can't set timer"); return -1; } if (which == ITIMER_VIRTUAL) user_loop(); else if (which == ITIMER_PROF) kernel_loop(); else if (which == ITIMER_REAL) idle_loop(); err = gettimeofday(&end, NULL); if (err < 0) { ksft_perror("Can't call gettimeofday()"); return -1; } ksft_test_result(check_diff(start, end) == 0, "%s\n", name); return 0; } static int check_timer_create(int which) { const char *type; int err; timer_t id; struct timeval start, end; struct itimerspec val = { .it_value.tv_sec = DELAY, }; if (which == CLOCK_THREAD_CPUTIME_ID) { type = "thread"; } else if (which == CLOCK_PROCESS_CPUTIME_ID) { type = "process"; } else { ksft_print_msg("Unknown timer_create() type %d\n", which); return -1; } done = 0; err = timer_create(which, NULL, &id); if (err < 0) { ksft_perror("Can't create timer"); return -1; } signal(SIGALRM, sig_handler); err = gettimeofday(&start, NULL); if (err < 0) { ksft_perror("Can't call gettimeofday()"); return -1; } err = timer_settime(id, 0, &val, NULL); if (err < 0) { ksft_perror("Can't set timer"); return -1; } user_loop(); err = gettimeofday(&end, NULL); if (err < 0) { ksft_perror("Can't call gettimeofday()"); return -1; } ksft_test_result(check_diff(start, end) == 0, "timer_create() per %s\n", type); return 0; } static pthread_t ctd_thread; static volatile int ctd_count, ctd_failed; static void ctd_sighandler(int sig) { if (pthread_self() != ctd_thread) ctd_failed = 1; ctd_count--; } static void *ctd_thread_func(void *arg) { struct itimerspec val = { .it_value.tv_sec = 0, .it_value.tv_nsec = 1000 * 1000, .it_interval.tv_sec = 0, .it_interval.tv_nsec = 1000 * 1000, }; timer_t id; /* 1/10 seconds to ensure the leader sleeps */ usleep(10000); ctd_count = 100; if (timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id)) return "Can't create timer\n"; if (timer_settime(id, 0, &val, NULL)) return "Can't set timer\n"; while (ctd_count > 0 && !ctd_failed) ; if (timer_delete(id)) return "Can't delete timer\n"; return NULL; } /* * Test that only the running thread receives the timer signal. */ static int check_timer_distribution(void) { const char *errmsg; signal(SIGALRM, ctd_sighandler); errmsg = "Can't create thread\n"; if (pthread_create(&ctd_thread, NULL, ctd_thread_func, NULL)) goto err; errmsg = "Can't join thread\n"; if (pthread_join(ctd_thread, (void **)&errmsg) || errmsg) goto err; if (!ctd_failed) ksft_test_result_pass("check signal distribution\n"); else if (ksft_min_kernel_version(6, 3)) ksft_test_result_fail("check signal distribution\n"); else ksft_test_result_skip("check signal distribution (old kernel)\n"); return 0; err: ksft_print_msg("%s", errmsg); return -1; } int main(int argc, char **argv) { ksft_print_header(); ksft_set_plan(6); ksft_print_msg("Testing posix timers. False negative may happen on CPU execution \n"); ksft_print_msg("based timers if other threads run on the CPU...\n"); if (check_itimer(ITIMER_VIRTUAL) < 0) return ksft_exit_fail(); if (check_itimer(ITIMER_PROF) < 0) return ksft_exit_fail(); if (check_itimer(ITIMER_REAL) < 0) return ksft_exit_fail(); if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0) return ksft_exit_fail(); /* * It's unfortunately hard to reliably test a timer expiration * on parallel multithread cputime. We could arm it to expire * on DELAY * nr_threads, with nr_threads busy looping, then wait * the normal DELAY since the time is elapsing nr_threads faster. * But for that we need to ensure we have real physical free CPUs * to ensure true parallelism. So test only one thread until we * find a better solution. */ if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0) return ksft_exit_fail(); if (check_timer_distribution() < 0) return ksft_exit_fail(); ksft_finished(); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
You can’t perform that action at this time.