lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20090402164618.GC7385@elte.hu>
Date:	Thu, 2 Apr 2009 18:46:18 +0200
From:	Ingo Molnar <mingo@...e.hu>
To:	Stanislaw Gruszka <sgruszka@...hat.com>,
	Thomas Gleixner <tglx@...utronix.de>,
	Oleg Nesterov <oleg@...hat.com>
Cc:	linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/2] itimers: fix periodic tics precision


(Cc:s added)

* Stanislaw Gruszka <sgruszka@...hat.com> 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 <sgruszka@...hat.com>
> ---
>  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@...r.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ