The patch titled itimers: fix periodic tics precision has been removed from the -mm tree. Its filename was itimers-fix-periodic-tics-precision.patch This patch was dropped because an updated version will be merged The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/ ------------------------------------------------------ Subject: itimers: fix periodic tics precision From: Stanislaw Gruszka <sgruszka@xxxxxxxxxx> Measure interval of tics generated by ITIMER_VIRT and ITIMER_PROF using ktime instead of cputime. Calculate error between requested interval and current one, take it into account when scheduling next tick. This patch introduce possibility where time between two consecutive tics is smaller then requested interval, it preserve however dependency that n tick is generated not earlier than n*interval time - counting from the beginning of periodic signal generation. Signed-off-by: Stanislaw Gruszka <sgruszka@xxxxxxxxxx> Cc: Oleg Nesterov <oleg@xxxxxxxxxx> Cc: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxx> Cc: john stultz <johnstul@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- include/linux/sched.h | 3 ++- kernel/fork.c | 6 ++++-- kernel/itimer.c | 23 +++++++++++++---------- kernel/posix-cpu-timers.c | 24 +++++++++++++++++++++--- 4 files changed, 40 insertions(+), 16 deletions(-) diff -puN include/linux/sched.h~itimers-fix-periodic-tics-precision include/linux/sched.h --- a/include/linux/sched.h~itimers-fix-periodic-tics-precision +++ a/include/linux/sched.h @@ -457,7 +457,8 @@ struct pacct_struct { struct cpu_itimer { cputime_t expires; - cputime_t incr; + ktime_t incr; + u32 err_ns; }; /** diff -puN kernel/fork.c~itimers-fix-periodic-tics-precision kernel/fork.c --- a/kernel/fork.c~itimers-fix-periodic-tics-precision +++ a/kernel/fork.c @@ -790,9 +790,11 @@ static void posix_cpu_timers_init_group( /* Expiration times and increments. */ sig->it[0].expires = cputime_zero; - sig->it[0].incr = cputime_zero; + sig->it[0].incr = ktime_set(0, 0); + sig->it[0].err_ns = 0; sig->it[1].expires = cputime_zero; - sig->it[1].incr = cputime_zero; + sig->it[1].incr = ktime_set(0, 0); + sig->it[1].err_ns = 0; /* Cached expiration times. */ sig->cputime_expires.prof_exp = cputime_zero; diff -puN kernel/itimer.c~itimers-fix-periodic-tics-precision kernel/itimer.c --- a/kernel/itimer.c~itimers-fix-periodic-tics-precision +++ a/kernel/itimer.c @@ -42,15 +42,16 @@ static struct timeval itimer_get_remtime } static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, - struct itimerval *value) + struct itimerval *const value) { - cputime_t cval, cinterval; + cputime_t cval; + ktime_t kt_cinterval; struct cpu_itimer *it = &tsk->signal->it[clock_id]; spin_lock_irq(&tsk->sighand->siglock); cval = it->expires; - cinterval = it->incr; + kt_cinterval = it->incr; if (!cputime_eq(cval, cputime_zero)) { struct task_cputime cputime; cputime_t t; @@ -77,7 +78,7 @@ static void get_cpu_itimer(struct task_s spin_unlock_irq(&tsk->sighand->siglock); cputime_to_timeval(cval, &value->it_value); - cputime_to_timeval(cinterval, &value->it_interval); + value->it_interval = ktime_to_timeval(kt_cinterval); } int do_getitimer(int which, struct itimerval *value) @@ -133,18 +134,20 @@ enum hrtimer_restart it_real_fn(struct h } static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, - struct itimerval *value, struct itimerval *ovalue) + const struct itimerval *const value, + struct itimerval *const ovalue) { - cputime_t cval, cinterval, nval, ninterval; + cputime_t cval, nval; + ktime_t kt_cinterval, kt_ninterval; struct cpu_itimer *it = &tsk->signal->it[clock_id]; nval = timeval_to_cputime(&value->it_value); - ninterval = timeval_to_cputime(&value->it_interval); + kt_ninterval = timeval_to_ktime(value->it_interval); spin_lock_irq(&tsk->sighand->siglock); cval = it->expires; - cinterval = it->incr; + kt_cinterval = it->incr; if (!cputime_eq(cval, cputime_zero) || !cputime_eq(nval, cputime_zero)) { if (cputime_gt(nval, cputime_zero)) @@ -152,13 +155,13 @@ static void set_cpu_itimer(struct task_s set_process_cpu_timer(tsk, clock_id, &nval, &cval); } it->expires = nval; - it->incr = ninterval; + it->incr = kt_ninterval; spin_unlock_irq(&tsk->sighand->siglock); if (ovalue) { cputime_to_timeval(cval, &ovalue->it_value); - cputime_to_timeval(cinterval, &ovalue->it_interval); + ovalue->it_interval = ktime_to_timeval(kt_cinterval); } } diff -puN kernel/posix-cpu-timers.c~itimers-fix-periodic-tics-precision kernel/posix-cpu-timers.c --- a/kernel/posix-cpu-timers.c~itimers-fix-periodic-tics-precision +++ a/kernel/posix-cpu-timers.c @@ -1080,9 +1080,27 @@ static void check_cpu_itimer(struct task return; if (cputime_ge(cur_time, it->expires)) { - it->expires = it->incr; - if (!cputime_eq(it->expires, cputime_zero)) { - it->expires = cputime_add(it->expires, cur_time); + if (it->incr.tv64 != 0) { + ktime_t incr, real_incr, diff; + cputime_t cpu_incr; + struct timespec ts_incr, ts_real_incr; + + incr = ktime_sub_ns(it->incr, it->err_ns); + if (unlikely(incr.tv64 <= 0)) + incr = ktime_set(0, 1); + + ts_incr = ktime_to_timespec(incr); + cpu_incr = timespec_to_cputime(&ts_incr); + + cputime_to_timespec(cpu_incr, &ts_real_incr); + real_incr = timespec_to_ktime(ts_real_incr); + + diff = ktime_sub(real_incr, incr); + it->err_ns = ktime_to_ns(diff); + it->expires = cputime_add(it->expires, cpu_incr); + } else { + it->expires = cputime_zero; + it->err_ns = 0; } __group_send_sig_info(signo, SEND_SIG_PRIV, tsk); _ Patches currently in -mm which might be from sgruszka@xxxxxxxxxx are linux-next.patch itimers-fix-periodic-tics-precision.patch -- To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html