diff --git a/regression/apps/Makefile b/regression/apps/Makefile index 5a91525ad..bb6db5644 100644 --- a/regression/apps/Makefile +++ b/regression/apps/Makefile @@ -22,6 +22,7 @@ TEST_APPS := \ hello_c \ hello_pie \ hello_world \ + itimer \ mmap \ mongoose \ network \ diff --git a/regression/apps/itimer/Makefile b/regression/apps/itimer/Makefile new file mode 100644 index 000000000..c603a781a --- /dev/null +++ b/regression/apps/itimer/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MPL-2.0 + +include ../test_common.mk + +EXTRA_C_FLAGS := diff --git a/regression/apps/itimer/setitimer.c b/regression/apps/itimer/setitimer.c new file mode 100644 index 000000000..823ad4dea --- /dev/null +++ b/regression/apps/itimer/setitimer.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MPL-2.0 + +#include +#include +#include +#include +#include +#include +#include + +volatile sig_atomic_t counter = 0; + +void timer_handler(int signum) +{ + counter++; +} + +int main() +{ + struct itimerval timer; + struct sigaction sa; + int target_count = 3; + struct timespec start_time, end_time; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = &timer_handler; + sa.sa_flags = SA_RESTART; + sigaction(SIGALRM, &sa, NULL); + + // Set the interval to 1. + timer.it_value.tv_sec = 1; + timer.it_value.tv_usec = 0; + timer.it_interval.tv_sec = 1; + timer.it_interval.tv_usec = 0; + + // Start timer. + if (setitimer(ITIMER_REAL, &timer, NULL) == -1) { + perror("Error calling setitimer()"); + return EXIT_FAILURE; + } + + if (clock_gettime(CLOCK_REALTIME, &start_time) == -1) { + perror("Error calling clock_gettime()"); + return EXIT_FAILURE; + } + + while (counter < target_count) { + struct itimerval timer_state; + if (getitimer(ITIMER_REAL, &timer_state) == -1) { + perror("Error calling getitimer()"); + return EXIT_FAILURE; + } + + if (timer_state.it_interval.tv_sec == 1 && + timer_state.it_value.tv_sec == 0) { + sleep(1); + } else { + perror("Error record time in the timer"); + return EXIT_FAILURE; + } + } + + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = 0; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = 0; + // Stop timer. + if (setitimer(ITIMER_REAL, &timer, NULL) == -1) { + perror("Error calling setitimer()"); + return EXIT_FAILURE; + } + + if (clock_gettime(CLOCK_REALTIME, &end_time) == -1) { + perror("Error calling clock_gettime()"); + return EXIT_FAILURE; + } + + int elapsed_time = (int)(end_time.tv_sec - start_time.tv_sec); + + printf("Timer was set to go off every second for a total of %d times.\n", + target_count); + printf("Elapsed time: %d seconds.\n", elapsed_time); + + if (elapsed_time == target_count) { + printf("The actual elapsed time matches the expected time.\n"); + } else { + printf("There is a discrepancy between actual and expected time.\n"); + } + + return EXIT_SUCCESS; +} diff --git a/regression/apps/itimer/timer_create.c b/regression/apps/itimer/timer_create.c new file mode 100644 index 000000000..42e5086e8 --- /dev/null +++ b/regression/apps/itimer/timer_create.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MPL-2.0 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#define CLOCKID CLOCK_REALTIME +#define SIG SIGRTMIN + +static void handler(int sig, siginfo_t *si, void *unused) +{ + printf("Caught signal %d\n", sig); +} + +int main(int argc, char *argv[]) +{ + struct sigaction sa; + struct sigevent sev; + timer_t timerid; + struct itimerspec its; + memset(&sa, 0, sizeof(sa)); + + // Set signal handler + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = handler; + sigemptyset(&sa.sa_mask); + if (sigaction(SIG, &sa, NULL) == -1) { + perror("sigaction"); + exit(1); + } + + // Create the timer. + sev.sigev_notify = SIGEV_THREAD_ID; + sev.sigev_signo = SIG; + sev.sigev_value.sival_ptr = &timerid; + sev._sigev_un._tid = syscall(SYS_gettid); + if (timer_create(CLOCKID, &sev, &timerid) == -1) { + perror("timer_create"); + exit(1); + } + + // Enable the timer. + its.it_value.tv_sec = 5; + its.it_value.tv_nsec = 0; + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + if (timer_settime(timerid, 0, &its, NULL) == -1) { + perror("timer_settime"); + exit(1); + } + + pause(); + + return 0; +} diff --git a/regression/apps/scripts/process.sh b/regression/apps/scripts/process.sh index 2b2fa73ab..274d32a8d 100755 --- a/regression/apps/scripts/process.sh +++ b/regression/apps/scripts/process.sh @@ -18,6 +18,8 @@ fork_c/fork getpid/getpid hello_pie/hello hello_world/hello_world +itimer/setitimer +itimer/timer_create mmap/map_shared_anon pthread/pthread_test pty/open_pty diff --git a/regression/syscall_test/Makefile b/regression/syscall_test/Makefile index 387313c93..57a4b7391 100644 --- a/regression/syscall_test/Makefile +++ b/regression/syscall_test/Makefile @@ -29,6 +29,7 @@ TESTS ?= \ statfs_test \ symlink_test \ sync_test \ + timers_test \ truncate_test \ uidgid_test \ unlink_test \ diff --git a/regression/syscall_test/blocklists/timers_test b/regression/syscall_test/blocklists/timers_test new file mode 100644 index 000000000..1f12f0cfa --- /dev/null +++ b/regression/syscall_test/blocklists/timers_test @@ -0,0 +1,9 @@ +TimerTest.ProcessKilledOnCPUSoftLimit +TimerTest.ProcessPingedRepeatedlyAfterCPUSoftLimit +TimerTest.ProcessKilledOnCPUHardLimit +IntervalTimerTest.SingleShotSilent +IntervalTimerTest.PeriodicSilent +IntervalTimerTest.PeriodicThreadDirectedSignal +IntervalTimerTest.RealTimeSignalsAreNotDuplicated +IntervalTimerTest.AlreadyPendingSignal +IntervalTimerTest.IgnoredSignalCountsAsOverrun \ No newline at end of file