diff options
author | Dmitry Chestnykh <dm.chestnykh@gmail.com> | 2024-04-15 15:31:58 +0300 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2024-04-18 14:52:06 +0200 |
commit | 3a36a3100af2ee1cca69345af83228757e8c55fe (patch) | |
tree | 6ec6990dba241b65a925eb581ef59bcb3a74e843 /ldso/ldso/dl-vdso-calls.h | |
parent | 0694e42c9c9789bd87fba7e6639b21d2f28e09d4 (diff) |
Fix vDSO support for all supported architectures.
- Cleanup dl-vdso.c code.
- Pass `void *` as first arg to `load_vdso()`, using 32-bit type
is completely wrong on 64bit architectures.
- Split libc code and vDSO-related code.
Move arch-specific implementations into separate files.
The performance improvement is for example 50-60 times on ARMv7
and about 4 times on x86_64.
Signed-off-by: Dmitry Chestnykh <dm.chestnykh@gmail.com>
Diffstat (limited to 'ldso/ldso/dl-vdso-calls.h')
-rw-r--r-- | ldso/ldso/dl-vdso-calls.h | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/ldso/ldso/dl-vdso-calls.h b/ldso/ldso/dl-vdso-calls.h new file mode 100644 index 000000000..c72f2dadf --- /dev/null +++ b/ldso/ldso/dl-vdso-calls.h @@ -0,0 +1,68 @@ +#ifndef _DL_VDSO_CALLS_H +#define _DL_VDSO_CALLS_H + +#include <sys/time.h> +#include <sys/syscall.h> +#include <errno.h> +#include <time.h> + +void __attribute__((weak)) *_get__dl__vdso_clock_gettime(void); +#if defined(__UCLIBC_USE_TIME64__) +#include "internal/time64_helpers.h" +void __attribute__((weak)) *_get__dl__vdso_clock_gettime64(void); +typedef int (*clock_gettime_func)(clockid_t clock_id, struct __ts64_struct *tp); +#else +typedef int (*clock_gettime_func)(clockid_t clock_id, struct timespec *tp); +#endif + +extern int __libc_clock_gettime(clockid_t clock_id, struct timespec *tp); + +static int __attribute__ ((used)) __generic_vdso_clock_gettime(clockid_t clock_id, struct timespec *tp); +static int __attribute__ ((used)) __generic_vdso_clock_gettime(clockid_t clock_id, struct timespec *tp) +{ + void *impl = NULL; +#if defined(__UCLIBC_USE_TIME64__) + if (&_get__dl__vdso_clock_gettime64 && (impl = _get__dl__vdso_clock_gettime64())) { + struct __ts64_struct __ts64; + int __ret = ((clock_gettime_func)impl)(clock_id, &__ts64); + if (__ret != 0) { + __set_errno(-__ret); + return -1; + } + + if (tp) { + tp->tv_sec = __ts64.tv_sec; + tp->tv_nsec = __ts64.tv_nsec; + } + return 0; + } + + /* fallback to syscall */ + return __libc_clock_gettime(clock_id, tp); +#else + if (&_get__dl__vdso_clock_gettime && (impl = _get__dl__vdso_clock_gettime())) { + int __ret = ((clock_gettime_func)impl)(clock_id, tp); + if (__ret != 0) { + __set_errno(-__ret); + return -1; + } + + return 0; + } + + /* fallback to syscall */ + return __libc_clock_gettime(clock_id, tp); +#endif +} + +static int __attribute__ ((used)) __generic_vdso_gettimeofday(struct timeval *tv, __timezone_ptr_t tz) +{ + struct timespec ts; + int __res = __generic_vdso_clock_gettime(CLOCK_REALTIME, &ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = (suseconds_t)ts.tv_nsec / 1000; + + return __res; +} + +#endif /* _DL_VDSO_CALLS_H */
\ No newline at end of file |