9 static void *volatile vdso_func
;
12 static void *volatile vdso_func_32
;
13 static int cgt_time32_wrap(clockid_t clk
, struct timespec
*ts
)
16 int (*f
)(clockid_t
, long[2]) =
17 (int (*)(clockid_t
, long[2]))vdso_func_32
;
20 /* Fallback to syscalls if time32 overflowed. Maybe
21 * we lucked out and somehow migrated to a kernel with
22 * time64 syscalls available. */
24 a_cas_p(&vdso_func
, (void *)cgt_time32_wrap
, 0);
28 ts
->tv_nsec
= ts32
[1];
34 static int cgt_init(clockid_t clk
, struct timespec
*ts
)
36 void *p
= __vdsosym(VDSO_CGT_VER
, VDSO_CGT_SYM
);
39 void *q
= __vdsosym(VDSO_CGT32_VER
, VDSO_CGT32_SYM
);
41 a_cas_p(&vdso_func_32
, 0, q
);
45 #ifdef VDSO_CGT_WORKAROUND
46 if (!__vdsosym(VDSO_CGT32_VER
, VDSO_CGT32_SYM
)) p
= 0;
49 int (*f
)(clockid_t
, struct timespec
*) =
50 (int (*)(clockid_t
, struct timespec
*))p
;
51 a_cas_p(&vdso_func
, (void *)cgt_init
, p
);
52 return f
? f(clk
, ts
) : -ENOSYS
;
55 static void *volatile vdso_func
= (void *)cgt_init
;
59 int __clock_gettime(clockid_t clk
, struct timespec
*ts
)
64 int (*f
)(clockid_t
, struct timespec
*) =
65 (int (*)(clockid_t
, struct timespec
*))vdso_func
;
69 if (r
== -EINVAL
) return __syscall_ret(r
);
70 /* Fall through on errors other than EINVAL. Some buggy
71 * vdso implementations return ENOSYS for clocks they
72 * can't handle, rather than making the syscall. This
73 * also handles the case where cgt_init fails to find
74 * a vdso function to use. */
78 #ifdef SYS_clock_gettime64
80 if (sizeof(time_t) > 4)
81 r
= __syscall(SYS_clock_gettime64
, clk
, ts
);
82 if (SYS_clock_gettime
== SYS_clock_gettime64
|| r
!=-ENOSYS
)
83 return __syscall_ret(r
);
85 r
= __syscall(SYS_clock_gettime
, clk
, ts32
);
86 #ifdef SYS_gettimeofday
87 if (r
==-ENOSYS
&& clk
==CLOCK_REALTIME
) {
88 r
= __syscall(SYS_gettimeofday
, ts32
, 0);
94 ts
->tv_nsec
= ts32
[1];
97 return __syscall_ret(r
);
99 r
= __syscall(SYS_clock_gettime
, clk
, ts
);
100 #ifdef SYS_gettimeofday
102 if (clk
== CLOCK_REALTIME
) {
103 __syscall(SYS_gettimeofday
, ts
, 0);
104 ts
->tv_nsec
= (int)ts
->tv_nsec
* 1000;
110 return __syscall_ret(r
);
114 weak_alias(__clock_gettime
, clock_gettime
);