diff options
Diffstat (limited to 'kernel/posix-cpu-timers.c')
| -rw-r--r-- | kernel/posix-cpu-timers.c | 98 | 
1 files changed, 46 insertions, 52 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index bece7c0b67b..9b2d5e4dc8c 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -14,11 +14,11 @@   */  void update_rlimit_cpu(unsigned long rlim_new)  { -	cputime_t cputime; +	cputime_t cputime = secs_to_cputime(rlim_new); +	struct signal_struct *const sig = current->signal; -	cputime = secs_to_cputime(rlim_new); -	if (cputime_eq(current->signal->it_prof_expires, cputime_zero) || -	    cputime_gt(current->signal->it_prof_expires, cputime)) { +	if (cputime_eq(sig->it[CPUCLOCK_PROF].expires, cputime_zero) || +	    cputime_gt(sig->it[CPUCLOCK_PROF].expires, cputime)) {  		spin_lock_irq(¤t->sighand->siglock);  		set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL);  		spin_unlock_irq(¤t->sighand->siglock); @@ -613,6 +613,9 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now)  				break;  			}  		} else { +			struct signal_struct *const sig = p->signal; +			union cpu_time_count *exp = &timer->it.cpu.expires; +  			/*  			 * For a process timer, set the cached expiration time.  			 */ @@ -620,30 +623,27 @@ 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(sig->it[CPUCLOCK_VIRT].expires,  						cputime_zero) && -				    cputime_lt(p->signal->it_virt_expires, -					       timer->it.cpu.expires.cpu)) +				    cputime_lt(sig->it[CPUCLOCK_VIRT].expires, +					       exp->cpu))  					break; -				p->signal->cputime_expires.virt_exp = -					timer->it.cpu.expires.cpu; +				sig->cputime_expires.virt_exp = exp->cpu;  				break;  			case CPUCLOCK_PROF: -				if (!cputime_eq(p->signal->it_prof_expires, +				if (!cputime_eq(sig->it[CPUCLOCK_PROF].expires,  						cputime_zero) && -				    cputime_lt(p->signal->it_prof_expires, -					       timer->it.cpu.expires.cpu)) +				    cputime_lt(sig->it[CPUCLOCK_PROF].expires, +					       exp->cpu))  					break; -				i = p->signal->rlim[RLIMIT_CPU].rlim_cur; +				i = sig->rlim[RLIMIT_CPU].rlim_cur;  				if (i != RLIM_INFINITY && -				    i <= cputime_to_secs(timer->it.cpu.expires.cpu)) +				    i <= cputime_to_secs(exp->cpu))  					break; -				p->signal->cputime_expires.prof_exp = -					timer->it.cpu.expires.cpu; +				sig->cputime_expires.prof_exp = exp->cpu;  				break;  			case CPUCLOCK_SCHED: -				p->signal->cputime_expires.sched_exp = -					timer->it.cpu.expires.sched; +				sig->cputime_expires.sched_exp = exp->sched;  				break;  			}  		} @@ -1070,6 +1070,27 @@ static void stop_process_timers(struct task_struct *tsk)  	spin_unlock_irqrestore(&cputimer->lock, flags);  } +static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, +			     cputime_t *expires, cputime_t cur_time, int signo) +{ +	if (cputime_eq(it->expires, cputime_zero)) +		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); + +		__group_send_sig_info(signo, SEND_SIG_PRIV, tsk); +	} + +	if (!cputime_eq(it->expires, cputime_zero) && +	    (cputime_eq(*expires, cputime_zero) || +	     cputime_lt(it->expires, *expires))) { +		*expires = it->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 @@ -1089,10 +1110,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[CPUCLOCK_PROF].expires, 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[CPUCLOCK_VIRT].expires, cputime_zero) &&  	    list_empty(&timers[CPUCLOCK_SCHED])) {  		stop_process_timers(tsk);  		return; @@ -1152,38 +1173,11 @@ 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; -		} -	} +	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF], &prof_expires, ptime, +			 SIGPROF); +	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_expires, utime, +			 SIGVTALRM); +  	if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {  		unsigned long psecs = cputime_to_secs(ptime);  		cputime_t x;  |