diff --git a/include/zephyr/posix/time.h b/include/zephyr/posix/time.h index a20cf313fcd4..057d55f0e3a7 100644 --- a/include/zephyr/posix/time.h +++ b/include/zephyr/posix/time.h @@ -94,6 +94,7 @@ int timer_delete(timer_t timerid); int timer_gettime(timer_t timerid, struct itimerspec *its); int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue); +int timer_getoverrun(timer_t timerid); int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); #ifdef __cplusplus diff --git a/lib/posix/Kconfig.timer b/lib/posix/Kconfig.timer index c738064bb106..28173692e0ce 100644 --- a/lib/posix/Kconfig.timer +++ b/lib/posix/Kconfig.timer @@ -14,3 +14,10 @@ config TIMER_CREATE_WAIT help This controls how long to wait for resources to come available to create a new timer in POSIX compliant application + +config TIMER_DELAYTIMER_MAX + int "Maximum count returned my timer_getoverrun() in POSIX application" + default 20 + help + This controls the maximum number of times a timer can overrun before + timer_getoverrun() in POSIX compliant application. diff --git a/lib/posix/timer.c b/lib/posix/timer.c index 2d43ffc2a913..b00250ba50c7 100644 --- a/lib/posix/timer.c +++ b/lib/posix/timer.c @@ -179,6 +179,29 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, return 0; } +/** + * @brief Returns the timer expiration overrun count. + * + * See IEEE 1003.1 + */ +int timer_getoverrun(timer_t timerid) +{ + struct timer_obj *timer = (struct timer_obj *) timerid; + + if (timer == NULL) { + errno = EINVAL; + return -1; + } + + int overruns = k_timer_status_get(&timer->ztimer) - 1; + + if (overruns > CONFIG_TIMER_DELAYTIMER_MAX) { + overruns = CONFIG_TIMER_DELAYTIMER_MAX; + } + + return overruns; +} + /** * @brief Delete a per-process timer. * diff --git a/tests/posix/common/src/timer.c b/tests/posix/common/src/timer.c index c736ace18c70..0b5f07f8fb93 100644 --- a/tests/posix/common/src/timer.c +++ b/tests/posix/common/src/timer.c @@ -68,6 +68,7 @@ ZTEST(posix_apis, test_timer) sleep(SECS_TO_SLEEP); clock_gettime(CLOCK_MONOTONIC, &te); + zassert_equal(ret, 0, "Number of timer overruns is incorrect"); timer_delete(timerid); if (te.tv_nsec >= ts.tv_nsec) { @@ -83,7 +84,32 @@ ZTEST(posix_apis, test_timer) (value.it_interval.tv_sec * NSEC_PER_SEC + value.it_interval.tv_nsec)) / NSEC_PER_SEC; + /*TESTPOINT: Check if POSIX timer test passed*/ zassert_equal(total_secs_timer, secs_elapsed, "POSIX timer test has failed"); } + +ZTEST(posix_apis, test_timer_overrun) +{ + timer_t timerid; + struct sigevent sig = { 0 }; + struct itimerspec value; + + sig.sigev_notify = SIGEV_NONE; + + timer_create(CLOCK_MONOTONIC, &sig, &timerid); + + /*Set the timer to expire every 500 milliseconds*/ + value.it_interval.tv_sec = 0; + value.it_interval.tv_nsec = 500000000; + value.it_value.tv_sec = 0; + value.it_value.tv_nsec = 500000000; + timer_settime(timerid, 0, &value, NULL); + k_sleep(K_MSEC(2500)); + + int overruns = timer_getoverrun(timerid); + + timer_delete(timerid); + zassert_equal(overruns, 4, "Number of overruns is incorrect"); +}