diff options
Diffstat (limited to 'kernel/posix-cpu-timers.c')
| -rw-r--r-- | kernel/posix-cpu-timers.c | 51 | 
1 files changed, 43 insertions, 8 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index a278cad1d5d..8fd709c9bb5 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -155,11 +155,19 @@ static void bump_cpu_timer(struct k_itimer *timer,  static inline cputime_t prof_ticks(struct task_struct *p)  { -	return p->utime + p->stime; +	cputime_t utime, stime; + +	task_cputime(p, &utime, &stime); + +	return utime + stime;  }  static inline cputime_t virt_ticks(struct task_struct *p)  { -	return p->utime; +	cputime_t utime; + +	task_cputime(p, &utime, NULL); + +	return utime;  }  static int @@ -471,18 +479,23 @@ static void cleanup_timers(struct list_head *head,   */  void posix_cpu_timers_exit(struct task_struct *tsk)  { +	cputime_t utime, stime; +  	add_device_randomness((const void*) &tsk->se.sum_exec_runtime,  						sizeof(unsigned long long)); +	task_cputime(tsk, &utime, &stime);  	cleanup_timers(tsk->cpu_timers, -		       tsk->utime, tsk->stime, tsk->se.sum_exec_runtime); +		       utime, stime, tsk->se.sum_exec_runtime);  }  void posix_cpu_timers_exit_group(struct task_struct *tsk)  {  	struct signal_struct *const sig = tsk->signal; +	cputime_t utime, stime; +	task_cputime(tsk, &utime, &stime);  	cleanup_timers(tsk->signal->cpu_timers, -		       tsk->utime + sig->utime, tsk->stime + sig->stime, +		       utime + sig->utime, stime + sig->stime,  		       tsk->se.sum_exec_runtime + sig->sum_sched_runtime);  } @@ -1226,11 +1239,14 @@ static inline int task_cputime_expired(const struct task_cputime *sample,  static inline int fastpath_timer_check(struct task_struct *tsk)  {  	struct signal_struct *sig; +	cputime_t utime, stime; + +	task_cputime(tsk, &utime, &stime);  	if (!task_cputime_zero(&tsk->cputime_expires)) {  		struct task_cputime task_sample = { -			.utime = tsk->utime, -			.stime = tsk->stime, +			.utime = utime, +			.stime = stime,  			.sum_exec_runtime = tsk->se.sum_exec_runtime  		}; @@ -1401,8 +1417,10 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,  		while (!signal_pending(current)) {  			if (timer.it.cpu.expires.sched == 0) {  				/* -				 * Our timer fired and was reset. +				 * Our timer fired and was reset, below +				 * deletion can not fail.  				 */ +				posix_cpu_timer_del(&timer);  				spin_unlock_irq(&timer.it_lock);  				return 0;  			} @@ -1420,9 +1438,26 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,  		 * We were interrupted by a signal.  		 */  		sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp); -		posix_cpu_timer_set(&timer, 0, &zero_it, it); +		error = posix_cpu_timer_set(&timer, 0, &zero_it, it); +		if (!error) { +			/* +			 * Timer is now unarmed, deletion can not fail. +			 */ +			posix_cpu_timer_del(&timer); +		}  		spin_unlock_irq(&timer.it_lock); +		while (error == TIMER_RETRY) { +			/* +			 * We need to handle case when timer was or is in the +			 * middle of firing. In other cases we already freed +			 * resources. +			 */ +			spin_lock_irq(&timer.it_lock); +			error = posix_cpu_timer_del(&timer); +			spin_unlock_irq(&timer.it_lock); +		} +  		if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {  			/*  			 * It actually did fire already.  |