From 03f10a8a4574925711a8e83f7a8c944598a69899 Mon Sep 17 00:00:00 2001 From: rcitach Date: Tue, 21 Apr 2026 10:34:04 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20vdso=20readtime=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/libc/compilers/common/ctime.c | 29 ++++++++- components/lwp/arch/common/vdso_kernel.c | 64 +++++++++++++++++-- .../lwp/vdso/user/common/vdso_clock_gettime.c | 5 ++ components/lwp/vdso/vdso_data_page.h | 1 + src/clock.c | 5 +- 5 files changed, 97 insertions(+), 7 deletions(-) diff --git a/components/libc/compilers/common/ctime.c b/components/libc/compilers/common/ctime.c index 5e89097b27..3e1ea77fd7 100644 --- a/components/libc/compilers/common/ctime.c +++ b/components/libc/compilers/common/ctime.c @@ -52,6 +52,10 @@ #define _WARNING_NO_RTC "Cannot find a RTC device!" +#if defined(RT_USING_SMART) && defined(RT_USING_VDSO) +#include +#endif + /* days per month -- nonleap! */ static const short __spm[13] = { @@ -519,12 +523,26 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz) { if (_control_rtc(RT_DEVICE_CTRL_RTC_SET_TIMEVAL, (void *)tv) == RT_EOK) { +#if defined(RT_USING_SMART) && defined(RT_USING_VDSO) + struct timespec ts = { + .tv_sec = tv->tv_sec, + .tv_nsec = tv->tv_usec * 1000L, + }; + rt_vdso_set_realtime(&ts); +#endif return 0; } else { if (_control_rtc(RT_DEVICE_CTRL_RTC_SET_TIME, (void *)&tv->tv_sec) == RT_EOK) { +#if defined(RT_USING_SMART) && defined(RT_USING_VDSO) + struct timespec ts = { + .tv_sec = tv->tv_sec, + .tv_nsec = 0, + }; + rt_vdso_set_realtime(&ts); +#endif return 0; } } @@ -736,7 +754,16 @@ int clock_settime(clockid_t clockid, const struct timespec *tp) { #ifdef RT_USING_RTC case CLOCK_REALTIME: - return _control_rtc(RT_DEVICE_CTRL_RTC_SET_TIMESPEC, (void *)tp); + { + int ret = _control_rtc(RT_DEVICE_CTRL_RTC_SET_TIMESPEC, (void *)tp); + if (ret == RT_EOK) + { +#if defined(RT_USING_SMART) && defined(RT_USING_VDSO) + rt_vdso_set_realtime(tp); +#endif + } + return ret; + } #endif /* RT_USING_RTC */ case CLOCK_REALTIME_COARSE: diff --git a/components/lwp/arch/common/vdso_kernel.c b/components/lwp/arch/common/vdso_kernel.c index 49e4758cfb..f64010e3a1 100644 --- a/components/lwp/arch/common/vdso_kernel.c +++ b/components/lwp/arch/common/vdso_kernel.c @@ -101,6 +101,18 @@ static void rt_vdso_counter_to_timespec(rt_uint64_t counter_value, ts->tv_nsec = monotonic_ns % RT_VDSO_NSEC_PER_SEC; } +static struct timespec rt_vdso_timespec_subtract(const struct timespec *lhs, + const struct timespec *rhs) +{ + struct timespec ret; + + ret.tv_sec = lhs->tv_sec - rhs->tv_sec; + ret.tv_nsec = lhs->tv_nsec - rhs->tv_nsec; + rt_vdso_normalize_timespec(&ret); + + return ret; +} + static struct timespec rt_vdso_add_timespec(const struct timespec *lhs, const struct timespec *rhs) { @@ -129,15 +141,58 @@ static int rt_vdso_read_monotonic_snapshot(struct timespec *monotonic_time, return RT_EOK; } +static void rt_vdso_update_data_page_flags(void) +{ + rt_uint32_t flags = 0; + + if (rt_vdso_realtime_offset_ready) + { + flags |= RT_VDSO_FLAG_REALTIME_VALID; + } + + rt_vdso_kernel_data_page->flags = flags; +} + static void rt_vdso_store_clock_snapshot(const struct timespec *monotonic_time, rt_uint64_t counter_value, rt_uint64_t counter_freq) { rt_vdso_kernel_data_page->counter_last = counter_value; rt_vdso_kernel_data_page->counter_freq = counter_freq; + rt_vdso_update_data_page_flags(); rt_vdso_kernel_data_page->base_time[RT_VDSO_CLOCK_MONOTONIC_INDEX] = *monotonic_time; - rt_vdso_kernel_data_page->base_time[RT_VDSO_CLOCK_REALTIME_INDEX] = - rt_vdso_add_timespec(monotonic_time, &rt_vdso_realtime_offset); + if (rt_vdso_realtime_offset_ready) + { + rt_vdso_kernel_data_page->base_time[RT_VDSO_CLOCK_REALTIME_INDEX] = + rt_vdso_add_timespec(monotonic_time, &rt_vdso_realtime_offset); + } + else + { + rt_vdso_kernel_data_page->base_time[RT_VDSO_CLOCK_REALTIME_INDEX] = *monotonic_time; + } +} + +void rt_vdso_set_realtime(const struct timespec *realtime) +{ + struct timespec monotonic; + rt_uint64_t counter; + rt_uint64_t freq; + + if (rt_vdso_runtime_status != RT_EOK || realtime == RT_NULL) + { + return; + } + + if (rt_vdso_read_monotonic_snapshot(&monotonic, &counter, &freq) != RT_EOK) + { + return; + } + + rt_vdso_data_page_write_begin(rt_vdso_kernel_data_page); + rt_vdso_realtime_offset = rt_vdso_timespec_subtract(realtime, &monotonic); + rt_vdso_realtime_offset_ready = RT_TRUE; + rt_vdso_store_clock_snapshot(&monotonic, counter, freq); + rt_vdso_data_page_write_end(rt_vdso_kernel_data_page); } static void *rt_vdso_map_physical_pages(struct rt_lwp *lwp, void *user_va, @@ -209,7 +264,7 @@ static int rt_vdso_map_binary_pages(enum rt_vdso_binary_id binary_id, if (data_page_base == RT_NULL) { lwp->vdso_vbase = RT_NULL; - return RT_ERROR; + return -RT_ERROR; } image_base = (uint8_t *)data_page_base + data_page_len; @@ -221,7 +276,7 @@ static int rt_vdso_map_binary_pages(enum rt_vdso_binary_id binary_id, { lwp_unmap_user_phy(lwp, data_page_base); lwp->vdso_vbase = RT_NULL; - return RT_ERROR; + return -RT_ERROR; } lwp->vdso_vbase = image_base; @@ -266,6 +321,7 @@ static int rt_vdso_validate_image(void) rt_memset(rt_vdso_data_page_store.raw, 0, sizeof(rt_vdso_data_page_store.raw)); rt_vdso_realtime_offset_ready = RT_FALSE; + rt_memset(&rt_vdso_realtime_offset, 0, sizeof(rt_vdso_realtime_offset)); if (rt_memcmp(rt_vdso_binaries[RT_VDSO_BINARY_COMMON].image_start, RT_VDSO_IMAGE_ELF_MAGIC, RT_VDSO_IMAGE_ELF_MAGIC_LEN)) diff --git a/components/lwp/vdso/user/common/vdso_clock_gettime.c b/components/lwp/vdso/user/common/vdso_clock_gettime.c index 89889d2726..5f8ff66869 100644 --- a/components/lwp/vdso/user/common/vdso_clock_gettime.c +++ b/components/lwp/vdso/user/common/vdso_clock_gettime.c @@ -55,6 +55,11 @@ int rt_vdso_clock_gettime_impl(clockid_t clock, struct timespec *ts) do { seq = rt_vdso_data_read_begin(data_page); + if (index == RT_VDSO_CLOCK_REALTIME_INDEX && + !(data_page->flags & RT_VDSO_FLAG_REALTIME_VALID)) + { + return -ENOSYS; + } base_time = data_page->base_time[index]; last = data_page->counter_last; freq = data_page->counter_freq; diff --git a/components/lwp/vdso/vdso_data_page.h b/components/lwp/vdso/vdso_data_page.h index f57cabeaec..722490db2d 100644 --- a/components/lwp/vdso/vdso_data_page.h +++ b/components/lwp/vdso/vdso_data_page.h @@ -22,6 +22,7 @@ extern "C" { #define RT_VDSO_CLOCK_ID_MAX 16 #define RT_VDSO_NSEC_PER_SEC 1000000000ULL +#define RT_VDSO_FLAG_REALTIME_VALID (1U << 0) enum rt_vdso_clock_data_index { diff --git a/src/clock.c b/src/clock.c index c694f86906..56aa1aceb8 100644 --- a/src/clock.c +++ b/src/clock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2024 RT-Thread Development Team + * Copyright (c) 2006-2026, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -77,7 +77,7 @@ RTM_EXPORT(rt_tick_get); * @brief This function will return delta tick from base. * * @param base to consider - * + * * @return Return delta tick. */ rt_tick_t rt_tick_get_delta(rt_tick_t base) @@ -259,3 +259,4 @@ rt_weak rt_tick_t rt_tick_get_millisecond(void) } /**@}*/ +