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]
Date:	Thu, 2 Apr 2009 18:45:24 +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 1/2] itimers: merge ITIMER_VIRT and ITIMER_PROF common
	code


(added more Cc:s)

* Stanislaw Gruszka <sgruszka@...hat.com> wrote:

> Both cpu itimers have same data flow in the few places, this patch make
> unification of code related with VIRT and PROF itimers.
> 
> Signed-off-by: Stanislaw Gruszka <sgruszka@...hat.com>
> ---
>  include/linux/sched.h     |    6 +-
>  kernel/fork.c             |    8 +-
>  kernel/itimer.c           |  136 +++++++++++++++++++--------------------------
>  kernel/posix-cpu-timers.c |   81 ++++++++++++++-------------
>  4 files changed, 107 insertions(+), 124 deletions(-)
> 
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 29df637..b4c19c2 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -440,6 +440,8 @@ struct pacct_struct {
>  	unsigned long		ac_minflt, ac_majflt;
>  };
>  
> +enum itimer_number {IT_VIRT = 0, IT_PROF = 1};
> +
>  /**
>   * struct task_cputime - collected CPU time counts
>   * @utime:		time spent in user mode, in &cputime_t units
> @@ -526,8 +528,8 @@ struct signal_struct {
>  	ktime_t it_real_incr;
>  
>  	/* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */
> -	cputime_t it_prof_expires, it_virt_expires;
> -	cputime_t it_prof_incr, it_virt_incr;
> +	cputime_t it_expires[2];
> +	cputime_t it_incr[2];
>  
>  	/*
>  	 * Thread group totals for process CPU timers.
> diff --git a/kernel/fork.c b/kernel/fork.c
> index 47c1584..6c7044a 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -803,10 +803,10 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig)
>  	thread_group_cputime_init(sig);
>  
>  	/* Expiration times and increments. */
> -	sig->it_virt_expires = cputime_zero;
> -	sig->it_virt_incr = cputime_zero;
> -	sig->it_prof_expires = cputime_zero;
> -	sig->it_prof_incr = cputime_zero;
> +	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;
>  
>  	/* Cached expiration times. */
>  	sig->cputime_expires.prof_exp = cputime_zero;
> diff --git a/kernel/itimer.c b/kernel/itimer.c
> index 58762f7..ec64fea 100644
> --- a/kernel/itimer.c
> +++ b/kernel/itimer.c
> @@ -41,10 +41,34 @@ static struct timeval itimer_get_remtime(struct hrtimer *timer)
>  	return ktime_to_timeval(rem);
>  }
>  
> +static void get_cpu_itimer(struct task_struct *tsk, enum itimer_number i,
> +			   struct itimerval *value)
> +{
> +	cputime_t cval, cinterval;
> +
> +	spin_lock_irq(&tsk->sighand->siglock);
> +	cval = tsk->signal->it_expires[i];
> +	cinterval = tsk->signal->it_incr[i];
> +	if (!cputime_eq(cval, cputime_zero)) {
> +		struct task_cputime cputime;
> +		cputime_t utime;
> +
> +		thread_group_cputimer(tsk, &cputime);
> +		utime = cputime.utime;
> +		if (cputime_le(cval, utime)) { /* about to fire */
> +			cval = jiffies_to_cputime(1);
> +		} else {
> +			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);
> +}
> +
>  int do_getitimer(int which, struct itimerval *value)
>  {
>  	struct task_struct *tsk = current;
> -	cputime_t cinterval, cval;
>  
>  	switch (which) {
>  	case ITIMER_REAL:
> @@ -55,44 +79,10 @@ int do_getitimer(int which, struct itimerval *value)
>  		spin_unlock_irq(&tsk->sighand->siglock);
>  		break;
>  	case ITIMER_VIRTUAL:
> -		spin_lock_irq(&tsk->sighand->siglock);
> -		cval = tsk->signal->it_virt_expires;
> -		cinterval = tsk->signal->it_virt_incr;
> -		if (!cputime_eq(cval, cputime_zero)) {
> -			struct task_cputime cputime;
> -			cputime_t utime;
> -
> -			thread_group_cputimer(tsk, &cputime);
> -			utime = cputime.utime;
> -			if (cputime_le(cval, utime)) { /* about to fire */
> -				cval = jiffies_to_cputime(1);
> -			} else {
> -				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);
> +		get_cpu_itimer(tsk, IT_VIRT, value);
>  		break;
>  	case ITIMER_PROF:
> -		spin_lock_irq(&tsk->sighand->siglock);
> -		cval = tsk->signal->it_prof_expires;
> -		cinterval = tsk->signal->it_prof_incr;
> -		if (!cputime_eq(cval, cputime_zero)) {
> -			struct task_cputime times;
> -			cputime_t ptime;
> -
> -			thread_group_cputimer(tsk, &times);
> -			ptime = cputime_add(times.utime, times.stime);
> -			if (cputime_le(cval, ptime)) { /* about to fire */
> -				cval = jiffies_to_cputime(1);
> -			} else {
> -				cval = cputime_sub(cval, ptime);
> -			}
> -		}
> -		spin_unlock_irq(&tsk->sighand->siglock);
> -		cputime_to_timeval(cval, &value->it_value);
> -		cputime_to_timeval(cinterval, &value->it_interval);
> +		get_cpu_itimer(tsk, IT_PROF, value);
>  		break;
>  	default:
>  		return(-EINVAL);
> @@ -128,6 +118,35 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer)
>  	return HRTIMER_NORESTART;
>  }
>  
> +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;
> +
> +	nval = timeval_to_cputime(&value->it_value);
> +	ninterval = timeval_to_cputime(&value->it_interval);
> +
> +	spin_lock_irq(&tsk->sighand->siglock);
> +
> +	cval = tsk->signal->it_expires[i];
> +	cinterval = tsk->signal->it_incr[i];
> +	if (!cputime_eq(cval, cputime_zero) ||
> +	    !cputime_eq(nval, cputime_zero)) {
> +		if (cputime_gt(nval, cputime_zero))
> +			nval = cputime_add(nval, jiffies_to_cputime(1));
> +		set_process_cpu_timer(tsk, i, &nval, &cval);
> +	}
> +	tsk->signal->it_expires[i] = nval;
> +	tsk->signal->it_incr[i] = ninterval;
> +
> +	spin_unlock_irq(&tsk->sighand->siglock);
> +
> +	if (ovalue) {
> +		cputime_to_timeval(cval, &ovalue->it_value);
> +		cputime_to_timeval(cinterval, &ovalue->it_interval);
> +	}
> +}
> +
>  /*
>   * Returns true if the timeval is in canonical form
>   */
> @@ -139,7 +158,6 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
>  	struct task_struct *tsk = current;
>  	struct hrtimer *timer;
>  	ktime_t expires;
> -	cputime_t cval, cinterval, nval, ninterval;
>  
>  	/*
>  	 * Validate the timevals in value.
> @@ -174,48 +192,10 @@ again:
>  		spin_unlock_irq(&tsk->sighand->siglock);
>  		break;
>  	case ITIMER_VIRTUAL:
> -		nval = timeval_to_cputime(&value->it_value);
> -		ninterval = timeval_to_cputime(&value->it_interval);
> -		spin_lock_irq(&tsk->sighand->siglock);
> -		cval = tsk->signal->it_virt_expires;
> -		cinterval = tsk->signal->it_virt_incr;
> -		if (!cputime_eq(cval, cputime_zero) ||
> -		    !cputime_eq(nval, cputime_zero)) {
> -			if (cputime_gt(nval, cputime_zero))
> -				nval = cputime_add(nval,
> -						   jiffies_to_cputime(1));
> -			set_process_cpu_timer(tsk, CPUCLOCK_VIRT,
> -					      &nval, &cval);
> -		}
> -		tsk->signal->it_virt_expires = nval;
> -		tsk->signal->it_virt_incr = ninterval;
> -		spin_unlock_irq(&tsk->sighand->siglock);
> -		if (ovalue) {
> -			cputime_to_timeval(cval, &ovalue->it_value);
> -			cputime_to_timeval(cinterval, &ovalue->it_interval);
> -		}
> +		set_cpu_itimer(tsk, IT_VIRT, value, ovalue);
>  		break;
>  	case ITIMER_PROF:
> -		nval = timeval_to_cputime(&value->it_value);
> -		ninterval = timeval_to_cputime(&value->it_interval);
> -		spin_lock_irq(&tsk->sighand->siglock);
> -		cval = tsk->signal->it_prof_expires;
> -		cinterval = tsk->signal->it_prof_incr;
> -		if (!cputime_eq(cval, cputime_zero) ||
> -		    !cputime_eq(nval, cputime_zero)) {
> -			if (cputime_gt(nval, cputime_zero))
> -				nval = cputime_add(nval,
> -						   jiffies_to_cputime(1));
> -			set_process_cpu_timer(tsk, CPUCLOCK_PROF,
> -					      &nval, &cval);
> -		}
> -		tsk->signal->it_prof_expires = nval;
> -		tsk->signal->it_prof_incr = ninterval;
> -		spin_unlock_irq(&tsk->sighand->siglock);
> -		if (ovalue) {
> -			cputime_to_timeval(cval, &ovalue->it_value);
> -			cputime_to_timeval(cinterval, &ovalue->it_interval);
> -		}
> +		set_cpu_itimer(tsk, IT_PROF, value, ovalue);
>  		break;
>  	default:
>  		return -EINVAL;
> diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
> index 8e5d9a6..76e125c 100644
> --- a/kernel/posix-cpu-timers.c
> +++ b/kernel/posix-cpu-timers.c
> @@ -17,8 +17,8 @@ void update_rlimit_cpu(unsigned long rlim_new)
>  	cputime_t cputime;
>  
>  	cputime = secs_to_cputime(rlim_new);
> -	if (cputime_eq(current->signal->it_prof_expires, cputime_zero) ||
> -	    cputime_lt(current->signal->it_prof_expires, cputime)) {
> +	if (cputime_eq(current->signal->it_expires[IT_PROF], cputime_zero) ||
> +	    cputime_lt(current->signal->it_expires[IT_PROF], cputime)) {
>  		spin_lock_irq(&current->sighand->siglock);
>  		set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL);
>  		spin_unlock_irq(&current->sighand->siglock);
> @@ -619,18 +619,18 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
>  			default:
>  				BUG();
>  			case CPUCLOCK_VIRT:
> -				if (!cputime_eq(p->signal->it_virt_expires,
> +				if (!cputime_eq(p->signal->it_expires[IT_VIRT],
>  						cputime_zero) &&
> -				    cputime_lt(p->signal->it_virt_expires,
> +				    cputime_lt(p->signal->it_expires[IT_VIRT],
>  					       timer->it.cpu.expires.cpu))
>  					break;
>  				p->signal->cputime_expires.virt_exp =
>  					timer->it.cpu.expires.cpu;
>  				break;
>  			case CPUCLOCK_PROF:
> -				if (!cputime_eq(p->signal->it_prof_expires,
> +				if (!cputime_eq(p->signal->it_expires[IT_PROF],
>  						cputime_zero) &&
> -				    cputime_lt(p->signal->it_prof_expires,
> +				    cputime_lt(p->signal->it_expires[IT_PROF],
>  					       timer->it.cpu.expires.cpu))
>  					break;
>  				i = p->signal->rlim[RLIMIT_CPU].rlim_cur;
> @@ -1069,6 +1069,36 @@ static void stop_process_timers(struct task_struct *tsk)
>  	spin_unlock_irqrestore(&cputimer->lock, flags);
>  }
>  
> +static cputime_t check_cpu_itimer(struct task_struct *tsk, enum itimer_number i,
> +				  cputime_t expires, cputime_t cur_time)
> +{
> +	struct signal_struct *const sig = tsk->signal;
> +
> +	if (cputime_eq(sig->it_expires[i], cputime_zero))
> +		return expires;
> +
> +	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)) {
> +			sig->it_expires[i] = cputime_add(sig->it_expires[i],
> +							 cur_time);
> +		}
> +
> +		signo = (i == IT_VIRT) ? SIGVTALRM : SIGPROF;
> +		__group_send_sig_info(signo, SEND_SIG_PRIV, tsk);
> +	}
> +
> +	if (!cputime_eq(sig->it_expires[i], cputime_zero) &&
> +	    (cputime_eq(expires, cputime_zero) ||
> +	     cputime_lt(sig->it_expires[i], expires))) {
> +		expires = sig->it_expires[i];
> +	}
> +
> +	return expires;
> +}
> +
>  /*
>   * Check for any per-thread CPU timers that have fired and move them
>   * off the tsk->*_timers list onto the firing list.  Per-thread timers
> @@ -1088,10 +1118,10 @@ static void check_process_timers(struct task_struct *tsk,
>  	 * Don't sample the current process CPU clocks if there are no timers.
>  	 */
>  	if (list_empty(&timers[CPUCLOCK_PROF]) &&
> -	    cputime_eq(sig->it_prof_expires, cputime_zero) &&
> +	    cputime_eq(sig->it_expires[IT_PROF], cputime_zero) &&
>  	    sig->rlim[RLIMIT_CPU].rlim_cur == RLIM_INFINITY &&
>  	    list_empty(&timers[CPUCLOCK_VIRT]) &&
> -	    cputime_eq(sig->it_virt_expires, cputime_zero) &&
> +	    cputime_eq(sig->it_expires[IT_VIRT], cputime_zero) &&
>  	    list_empty(&timers[CPUCLOCK_SCHED])) {
>  		stop_process_timers(tsk);
>  		return;
> @@ -1151,38 +1181,9 @@ static void check_process_timers(struct task_struct *tsk,
>  	/*
>  	 * Check for the special case process timers.
>  	 */
> -	if (!cputime_eq(sig->it_prof_expires, cputime_zero)) {
> -		if (cputime_ge(ptime, sig->it_prof_expires)) {
> -			/* ITIMER_PROF fires and reloads.  */
> -			sig->it_prof_expires = sig->it_prof_incr;
> -			if (!cputime_eq(sig->it_prof_expires, cputime_zero)) {
> -				sig->it_prof_expires = cputime_add(
> -					sig->it_prof_expires, ptime);
> -			}
> -			__group_send_sig_info(SIGPROF, SEND_SIG_PRIV, tsk);
> -		}
> -		if (!cputime_eq(sig->it_prof_expires, cputime_zero) &&
> -		    (cputime_eq(prof_expires, cputime_zero) ||
> -		     cputime_lt(sig->it_prof_expires, prof_expires))) {
> -			prof_expires = sig->it_prof_expires;
> -		}
> -	}
> -	if (!cputime_eq(sig->it_virt_expires, cputime_zero)) {
> -		if (cputime_ge(utime, sig->it_virt_expires)) {
> -			/* ITIMER_VIRTUAL fires and reloads.  */
> -			sig->it_virt_expires = sig->it_virt_incr;
> -			if (!cputime_eq(sig->it_virt_expires, cputime_zero)) {
> -				sig->it_virt_expires = cputime_add(
> -					sig->it_virt_expires, utime);
> -			}
> -			__group_send_sig_info(SIGVTALRM, SEND_SIG_PRIV, tsk);
> -		}
> -		if (!cputime_eq(sig->it_virt_expires, cputime_zero) &&
> -		    (cputime_eq(virt_expires, cputime_zero) ||
> -		     cputime_lt(sig->it_virt_expires, virt_expires))) {
> -			virt_expires = sig->it_virt_expires;
> -		}
> -	}
> +	prof_expires = check_cpu_itimer(tsk, IT_PROF, prof_expires, ptime);
> +	virt_expires = check_cpu_itimer(tsk, IT_VIRT, virt_expires, utime);
> +
>  	if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
>  		unsigned long psecs = cputime_to_secs(ptime);
>  		cputime_t x;
> -- 
> 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