From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932139AbZDBQrb (ORCPT ); Thu, 2 Apr 2009 12:47:31 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1765761AbZDBQqr (ORCPT ); Thu, 2 Apr 2009 12:46:47 -0400 Received: from mx2.mail.elte.hu ([157.181.151.9]:45452 "EHLO mx2.mail.elte.hu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754506AbZDBQqp (ORCPT ); Thu, 2 Apr 2009 12:46:45 -0400 Date: Thu, 2 Apr 2009 18:46:18 +0200 From: Ingo Molnar To: Stanislaw Gruszka , Thomas Gleixner , Oleg Nesterov Cc: linux-kernel@vger.kernel.org Subject: Re: [PATCH 2/2] itimers: fix periodic tics precision Message-ID: <20090402164618.GC7385@elte.hu> References: <20090402141153.267a58a1@dhcp-lab-109.englab.brq.redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20090402141153.267a58a1@dhcp-lab-109.englab.brq.redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-ELTE-VirusStatus: clean X-ELTE-SpamScore: -1.5 X-ELTE-SpamLevel: X-ELTE-SpamCheck: no X-ELTE-SpamVersion: ELTE 2.0 X-ELTE-SpamCheck-Details: score=-1.5 required=5.9 tests=BAYES_00 autolearn=no SpamAssassin version=3.2.3 -1.5 BAYES_00 BODY: Bayesian spam probability is 0 to 1% [score: 0.0000] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org (Cc:s added) * Stanislaw Gruszka wrote: > 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 > --- > include/linux/sched.h | 3 ++- > kernel/fork.c | 6 ++++-- > kernel/itimer.c | 21 +++++++++++++-------- > kernel/posix-cpu-timers.c | 24 +++++++++++++++++++++--- > 4 files changed, 40 insertions(+), 14 deletions(-) > > diff --git a/include/linux/sched.h b/include/linux/sched.h > index b4c19c2..c6e1946 100644 > --- a/include/linux/sched.h > +++ b/include/linux/sched.h > @@ -529,7 +529,8 @@ struct signal_struct { > > /* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */ > cputime_t it_expires[2]; > - cputime_t it_incr[2]; > + ktime_t it_incr[2]; > + u32 it_err_ns[2]; > > /* > * Thread group totals for process CPU timers. > diff --git a/kernel/fork.c b/kernel/fork.c > index 6c7044a..b1bb3e4 100644 > --- a/kernel/fork.c > +++ b/kernel/fork.c > @@ -805,8 +805,10 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig) > /* Expiration times and increments. */ > sig->it_expires[IT_VIRT] = cputime_zero; > sig->it_expires[IT_PROF] = cputime_zero; > - sig->it_incr[IT_VIRT] = cputime_zero; > - sig->it_incr[IT_PROF] = cputime_zero; > + sig->it_incr[IT_VIRT] = ktime_set(0, 0); > + sig->it_incr[IT_PROF] = ktime_set(0, 0); > + sig->it_err_ns[IT_VIRT] = 0; > + sig->it_err_ns[IT_PROF] = 0; > > /* Cached expiration times. */ > sig->cputime_expires.prof_exp = cputime_zero; > diff --git a/kernel/itimer.c b/kernel/itimer.c > index ec64fea..ad06bd5 100644 > --- a/kernel/itimer.c > +++ b/kernel/itimer.c > @@ -44,11 +44,13 @@ static struct timeval itimer_get_remtime(struct hrtimer *timer) > static void get_cpu_itimer(struct task_struct *tsk, enum itimer_number i, > struct itimerval *value) > { > - cputime_t cval, cinterval; > + cputime_t cval; > + ktime_t kt_cinterval; > > spin_lock_irq(&tsk->sighand->siglock); > + > cval = tsk->signal->it_expires[i]; > - cinterval = tsk->signal->it_incr[i]; > + kt_cinterval = tsk->signal->it_incr[i]; > if (!cputime_eq(cval, cputime_zero)) { > struct task_cputime cputime; > cputime_t utime; > @@ -61,9 +63,11 @@ static void get_cpu_itimer(struct task_struct *tsk, enum itimer_number i, > cval = cputime_sub(cval, utime); > } > } > + > 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) > @@ -121,15 +125,16 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer) > static void set_cpu_itimer(struct task_struct *tsk, enum itimer_number i, > struct itimerval *value, struct itimerval *ovalue) > { > - cputime_t cval, cinterval, nval, ninterval; > + cputime_t cval, nval; > + ktime_t kt_cinterval, kt_ninterval; > > 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 = tsk->signal->it_expires[i]; > - cinterval = tsk->signal->it_incr[i]; > + kt_cinterval = tsk->signal->it_incr[i]; > if (!cputime_eq(cval, cputime_zero) || > !cputime_eq(nval, cputime_zero)) { > if (cputime_gt(nval, cputime_zero)) > @@ -137,13 +142,13 @@ static void set_cpu_itimer(struct task_struct *tsk, enum itimer_number i, > set_process_cpu_timer(tsk, i, &nval, &cval); > } > tsk->signal->it_expires[i] = nval; > - tsk->signal->it_incr[i] = ninterval; > + tsk->signal->it_incr[i] = 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 --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c > index 76e125c..9c3ea39 100644 > --- a/kernel/posix-cpu-timers.c > +++ b/kernel/posix-cpu-timers.c > @@ -1080,10 +1080,28 @@ static cputime_t check_cpu_itimer(struct task_struct *tsk, enum itimer_number i, > if (cputime_ge(cur_time, sig->it_expires[i])) { > int signo; > > - sig->it_expires[i] = sig->it_incr[i]; > - if (!cputime_eq(sig->it_expires[i], cputime_zero)) { > + if (sig->it_incr[i].tv64 != 0) { > + ktime_t incr, real_incr, diff; > + cputime_t cpu_incr; > + struct timespec ts_incr, ts_real_incr; > + > + incr = ktime_sub_ns(sig->it_incr[i], sig->it_err_ns[i]); > + 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); > + sig->it_err_ns[i] = ktime_to_ns(diff); > sig->it_expires[i] = cputime_add(sig->it_expires[i], > - cur_time); > + cpu_incr); > + } else { > + sig->it_expires[i] = cputime_zero; > + sig->it_err_ns[i] = 0; > } > > signo = (i == IT_VIRT) ? SIGVTALRM : SIGPROF; > -- > 1.6.0.6 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/