diff options
Diffstat (limited to 'src/linux')
| -rw-r--r-- | src/linux/clock_adjtime.c | 110 | 
1 files changed, 110 insertions, 0 deletions
| diff --git a/src/linux/clock_adjtime.c b/src/linux/clock_adjtime.c index 7d6b0349..2f531397 100644 --- a/src/linux/clock_adjtime.c +++ b/src/linux/clock_adjtime.c @@ -1,9 +1,119 @@  #include <sys/timex.h>  #include <time.h> +#include <errno.h>  #include "syscall.h" +#define IS32BIT(x) !((x)+0x80000000ULL>>32) + +struct ktimex64 { +	unsigned modes; +	int :32; +	long long offset, freq, maxerror, esterror; +	int status; +	int :32; +	long long constant, precision, tolerance; +	long long time_sec, time_usec; +	long long tick, ppsfreq, jitter; +	int shift; +	int :32; +	long long stabil, jitcnt, calcnt, errcnt, stbcnt; +	int tai; +	int __padding[11]; +}; + +struct ktimex { +	unsigned modes; +	long offset, freq, maxerror, esterror; +	int status; +	long constant, precision, tolerance; +	long time_sec, time_usec; +	long tick, ppsfreq, jitter; +	int shift; +	long stabil, jitcnt, calcnt, errcnt, stbcnt; +	int tai; +	int __padding[11]; +}; +  int clock_adjtime (clockid_t clock_id, struct timex *utx)  { +	int r = -ENOSYS; +#ifdef SYS_clock_adjtime64 +	if (SYS_clock_adjtime == SYS_clock_adjtime64 || +	    (utx->modes & ADJ_SETOFFSET) && !IS32BIT(utx->time.tv_sec)) { +		struct ktimex64 ktx = { +			.modes = utx->modes, +			.offset = utx->offset, +			.freq = utx->freq, +			.maxerror = utx->maxerror, +			.esterror = utx->esterror, +			.status = utx->status, +			.constant = utx->constant, +			.precision = utx->precision, +			.tolerance = utx->tolerance, +			.time_sec = utx->time.tv_sec, +			.time_usec = utx->time.tv_usec, +			.tick = utx->tick, +			.ppsfreq = utx->ppsfreq, +			.jitter = utx->jitter, +			.shift = utx->shift, +			.stabil = utx->stabil, +			.jitcnt = utx->jitcnt, +			.calcnt = utx->calcnt, +			.errcnt = utx->errcnt, +			.stbcnt = utx->stbcnt, +			.tai = utx->tai, +		}; +		r = __syscall(SYS_clock_adjtime, clock_id, &ktx); +		if (r>=0) { +			utx->modes = ktx.modes; +			utx->offset = ktx.offset; +			utx->freq = ktx.freq; +			utx->maxerror = ktx.maxerror; +			utx->esterror = ktx.esterror; +			utx->status = ktx.status; +			utx->constant = ktx.constant; +			utx->precision = ktx.precision; +			utx->tolerance = ktx.tolerance; +			utx->time.tv_sec = ktx.time_sec; +			utx->time.tv_usec = ktx.time_usec; +			utx->tick = ktx.tick; +			utx->ppsfreq = ktx.ppsfreq; +			utx->jitter = ktx.jitter; +			utx->shift = ktx.shift; +			utx->stabil = ktx.stabil; +			utx->jitcnt = ktx.jitcnt; +			utx->calcnt = ktx.calcnt; +			utx->errcnt = ktx.errcnt; +			utx->stbcnt = ktx.stbcnt; +			utx->tai = ktx.tai; +		} +	} +	if (SYS_clock_adjtime == SYS_clock_adjtime64 || r!=-ENOSYS) +		return __syscall_ret(r); +	if ((utx->modes & ADJ_SETOFFSET) && !IS32BIT(utx->time.tv_sec)) +		return __syscall_ret(-ENOTSUP); +#endif +	if (sizeof(time_t) > sizeof(long)) { +		union { +			struct timex utx; +			struct ktimex ktx; +		} u = { *utx }; +		u.ktx.time_sec = utx->time.tv_sec; +		u.ktx.time_usec = utx->time.tv_usec; +#ifdef SYS_adjtimex +		if (clock_id==CLOCK_REALTIME) r = __syscall(SYS_adjtimex, &u); +		else +#endif +		r = __syscall(SYS_clock_adjtime, clock_id, &u); +		if (r>=0) { +			*utx = u.utx; +			utx->time.tv_sec = u.ktx.time_sec; +			utx->time.tv_usec = u.ktx.time_usec; +		} +		return __syscall_ret(r); +	} +#ifdef SYS_adjtimex  	if (clock_id==CLOCK_REALTIME) return syscall(SYS_adjtimex, utx); +#endif  	return syscall(SYS_clock_adjtime, clock_id, utx);  } | 
