summaryrefslogtreecommitdiff
path: root/ldso/ldso/dl-vdso-calls.h
diff options
context:
space:
mode:
authorDmitry Chestnykh <dm.chestnykh@gmail.com>2024-04-15 15:31:58 +0300
committerWaldemar Brodkorb <wbx@openadk.org>2024-04-18 14:52:06 +0200
commit3a36a3100af2ee1cca69345af83228757e8c55fe (patch)
tree6ec6990dba241b65a925eb581ef59bcb3a74e843 /ldso/ldso/dl-vdso-calls.h
parent0694e42c9c9789bd87fba7e6639b21d2f28e09d4 (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.h68
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