diff --git a/include/posix/time.h b/include/posix/time.h index e0b53a5d38e..ddf51c80316 100644 --- a/include/posix/time.h +++ b/include/posix/time.h @@ -49,18 +49,8 @@ static inline s32_t _ts_to_ms(const struct timespec *to) return (to->tv_sec * MSEC_PER_SEC) + (to->tv_nsec / NSEC_PER_MSEC); } -/** - * @brief Set clock time. - * - * See IEEE 1003.1 - */ -static inline int clock_settime(clockid_t clock_id, const struct timespec *ts) -{ - errno = ENOSYS; - return -1; -} - int clock_gettime(clockid_t clock_id, struct timespec *ts); +int clock_settime(clockid_t clock_id, const struct timespec *ts); /* Timer APIs */ int timer_create(clockid_t clockId, struct sigevent *evp, timer_t *timerid); int timer_delete(timer_t timerid); diff --git a/lib/posix/clock.c b/lib/posix/clock.c index 1798157451a..d179243c573 100644 --- a/lib/posix/clock.c +++ b/lib/posix/clock.c @@ -57,6 +57,40 @@ int clock_gettime(clockid_t clock_id, struct timespec *ts) return 0; } +/** + * @brief Set the time of the specified clock. + * + * See IEEE 1003.1. + * + * Note that only the `CLOCK_REALTIME` clock can be set using this + * call. + */ +int clock_settime(clockid_t clock_id, const struct timespec *tp) +{ + struct timespec base; + int res; + + if (clock_id != CLOCK_REALTIME) { + errno = EINVAL; + return -1; + } + + res = clock_gettime(clock_id, &base); + if (res != 0) { + return res; + } + + s64_t delta = (s64_t)NSEC_PER_SEC * (tp->tv_sec - base.tv_sec) + + (tp->tv_nsec - base.tv_nsec); + + base.tv_sec = delta / NSEC_PER_SEC; + base.tv_nsec = delta % NSEC_PER_SEC; + + rt_clock_base = base; + + return 0; +} + /** * @brief Get current real time. *