diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/time/clock_gettime.c | 32 | 
1 files changed, 32 insertions, 0 deletions
diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c index 46083759..63e9f9c8 100644 --- a/src/time/clock_gettime.c +++ b/src/time/clock_gettime.c @@ -8,9 +8,41 @@  static void *volatile vdso_func; +#ifdef VDSO_CGT32_SYM +static void *volatile vdso_func_32; +static int cgt_time32_wrap(clockid_t clk, struct timespec *ts) +{ +	long ts32[2]; +	int (*f)(clockid_t, long[2]) = +		(int (*)(clockid_t, long[2]))vdso_func_32; +	int r = f(clk, ts32); +	if (!r) { +		/* Fallback to syscalls if time32 overflowed. Maybe +		 * we lucked out and somehow migrated to a kernel with +		 * time64 syscalls available. */ +		if (ts32[0] < 0) { +			a_cas_p(&vdso_func, (void *)cgt_time32_wrap, 0); +			return -ENOSYS; +		} +		ts->tv_sec = ts32[0]; +		ts->tv_nsec = ts32[1]; +	} +	return r; +} +#endif +  static int cgt_init(clockid_t clk, struct timespec *ts)  {  	void *p = __vdsosym(VDSO_CGT_VER, VDSO_CGT_SYM); +#ifdef VDSO_CGT32_SYM +	if (!p) { +		void *q = __vdsosym(VDSO_CGT32_VER, VDSO_CGT32_SYM); +		if (q) { +			a_cas_p(&vdso_func_32, 0, q); +			p = cgt_time32_wrap; +		} +	} +#endif  	int (*f)(clockid_t, struct timespec *) =  		(int (*)(clockid_t, struct timespec *))p;  	a_cas_p(&vdso_func, (void *)cgt_init, p);  | 
