/* * The time is "clock". old is what we think the time is. * Adjust the value by a multiple of jiffies and add the delta to ntp. * "delay" is an approximation how long the synchronization took. If * the time correction is positive, then "delay" is subtracted from * the time difference and only the remaining part is passed to ntp. */ static unsigned long long adjust_time(unsigned long long old, unsigned long long clock, unsigned long long delay) { unsigned long long delta, ticks; struct timex adjust; if (clock > old) { /* It is later than we thought. */ delta = ticks = clock - old; delta = ticks = (delta < delay) ? 0 : delta - delay; delta -= do_div(ticks, CLK_TICKS_PER_JIFFY); adjust.offset = ticks * (1000000 / HZ); } else { /* It is earlier than we thought. */ delta = ticks = old - clock; delta -= do_div(ticks, CLK_TICKS_PER_JIFFY); delta = -delta; adjust.offset = -ticks * (1000000 / HZ); } sched_clock_base_cc += delta; if (adjust.offset != 0) { pr_notice("The ETR interface has adjusted the clock " "by %li microseconds\n", adjust.offset); adjust.modes = ADJ_OFFSET_SINGLESHOT; do_adjtimex(&adjust); } return delta; }
/* * The time is "clock". old is what we think the time is. * Adjust the value by a multiple of jiffies and add the delta to ntp. * "delay" is an approximation how long the synchronization took. If * the time correction is positive, then "delay" is subtracted from * the time difference and only the remaining part is passed to ntp. */ static unsigned long long adjust_time(unsigned long long old, unsigned long long clock, unsigned long long delay) { unsigned long long delta, ticks; struct timex adjust; if (clock > old) { /* It is later than we thought. */ delta = ticks = clock - old; delta = ticks = (delta < delay) ? 0 : delta - delay; delta -= do_div(ticks, CLK_TICKS_PER_JIFFY); adjust.offset = ticks * (1000000 / HZ); } else { /* It is earlier than we thought. */ delta = ticks = old - clock; delta -= do_div(ticks, CLK_TICKS_PER_JIFFY); delta = -delta; adjust.offset = -ticks * (1000000 / HZ); } jiffies_timer_cc += delta; if (adjust.offset != 0) { printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n", adjust.offset); adjust.modes = ADJ_OFFSET_SINGLESHOT; do_adjtimex(&adjust); } return delta; }
asmlinkage long sys32_adjtimex(struct timex32 *txc_p32) { struct timex txc; struct timex32 t32; int ret; extern int do_adjtimex(struct timex *txc); if(copy_from_user(&t32, txc_p32, sizeof(struct timex32))) return -EFAULT; #undef CP #define CP(x) txc.x = t32.x CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror); CP(status); CP(constant); CP(precision); CP(tolerance); CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter); CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt); CP(stbcnt); ret = do_adjtimex(&txc); #undef CP #define CP(x) t32.x = txc.x CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror); CP(status); CP(constant); CP(precision); CP(tolerance); CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter); CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt); CP(stbcnt); return copy_to_user(txc_p32, &t32, sizeof(struct timex32)) ? -EFAULT : ret; }
int sys_adjtimex(struct tcb *tcp) { if (exiting(tcp)) return do_adjtimex(tcp, tcp->u_arg[0]); return 0; }
asmlinkage long sys32_adjtimex(struct timex32 __user *utp) { struct timex txc; int ret; memset(&txc, 0, sizeof(struct timex)); if(get_user(txc.modes, &utp->modes) || __get_user(txc.offset, &utp->offset) || __get_user(txc.freq, &utp->freq) || __get_user(txc.maxerror, &utp->maxerror) || __get_user(txc.esterror, &utp->esterror) || __get_user(txc.status, &utp->status) || __get_user(txc.constant, &utp->constant) || __get_user(txc.precision, &utp->precision) || __get_user(txc.tolerance, &utp->tolerance) || __get_user(txc.time.tv_sec, &utp->time.tv_sec) || __get_user(txc.time.tv_usec, &utp->time.tv_usec) || __get_user(txc.tick, &utp->tick) || __get_user(txc.ppsfreq, &utp->ppsfreq) || __get_user(txc.jitter, &utp->jitter) || __get_user(txc.shift, &utp->shift) || __get_user(txc.stabil, &utp->stabil) || __get_user(txc.jitcnt, &utp->jitcnt) || __get_user(txc.calcnt, &utp->calcnt) || __get_user(txc.errcnt, &utp->errcnt) || __get_user(txc.stbcnt, &utp->stbcnt)) return -EFAULT; ret = do_adjtimex(&txc); /* adjust the conversion of TB to time of day to track adjtimex */ ppc_adjtimex(); if(put_user(txc.modes, &utp->modes) || __put_user(txc.offset, &utp->offset) || __put_user(txc.freq, &utp->freq) || __put_user(txc.maxerror, &utp->maxerror) || __put_user(txc.esterror, &utp->esterror) || __put_user(txc.status, &utp->status) || __put_user(txc.constant, &utp->constant) || __put_user(txc.precision, &utp->precision) || __put_user(txc.tolerance, &utp->tolerance) || __put_user(txc.time.tv_sec, &utp->time.tv_sec) || __put_user(txc.time.tv_usec, &utp->time.tv_usec) || __put_user(txc.tick, &utp->tick) || __put_user(txc.ppsfreq, &utp->ppsfreq) || __put_user(txc.jitter, &utp->jitter) || __put_user(txc.shift, &utp->shift) || __put_user(txc.stabil, &utp->stabil) || __put_user(txc.jitcnt, &utp->jitcnt) || __put_user(txc.calcnt, &utp->calcnt) || __put_user(txc.errcnt, &utp->errcnt) || __put_user(txc.stbcnt, &utp->stbcnt)) ret = -EFAULT; return ret; }
int sys_clock_adjtime(struct tcb *tcp) { if (exiting(tcp)) return do_adjtimex(tcp, tcp->u_arg[1]); printclockname(tcp->u_arg[0]); tprints(", "); return 0; }
asmlinkage long sys_adjtimex(struct timex __user *txc_p) { struct timex txc; /* Local copy of parameter */ int ret; /* Copy the user data space into the kernel copy * structure. But bear in mind that the structures * may change */ if(copy_from_user(&txc, txc_p, sizeof(struct timex))) return -EFAULT; ret = do_adjtimex(&txc); return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret; }
static int posix_clock_realtime_adj(const clockid_t which_clock, struct timex *t) { return do_adjtimex(t); }