diff options
| -rw-r--r-- | kernel/posix-cpu-timers.c | 7 | ||||
| -rw-r--r-- | kernel/sched_stats.h | 15 | 
2 files changed, 16 insertions, 6 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 153dcb2639c..895337b16a2 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1308,9 +1308,10 @@ 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 = tsk->signal; +	struct signal_struct *sig; -	if (unlikely(!sig)) +	/* tsk == current, ensure it is safe to use ->signal/sighand */ +	if (unlikely(tsk->exit_state))  		return 0;  	if (!task_cputime_zero(&tsk->cputime_expires)) { @@ -1323,6 +1324,8 @@ static inline int fastpath_timer_check(struct task_struct *tsk)  		if (task_cputime_expired(&task_sample, &tsk->cputime_expires))  			return 1;  	} + +	sig = tsk->signal;  	if (!task_cputime_zero(&sig->cputime_expires)) {  		struct task_cputime group_sample; diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h index ee71bec1da6..7dbf72a2b02 100644 --- a/kernel/sched_stats.h +++ b/kernel/sched_stats.h @@ -298,9 +298,11 @@ static inline void account_group_user_time(struct task_struct *tsk,  {  	struct signal_struct *sig; -	sig = tsk->signal; -	if (unlikely(!sig)) +	/* tsk == current, ensure it is safe to use ->signal */ +	if (unlikely(tsk->exit_state))  		return; + +	sig = tsk->signal;  	if (sig->cputime.totals) {  		struct task_cputime *times; @@ -325,9 +327,11 @@ static inline void account_group_system_time(struct task_struct *tsk,  {  	struct signal_struct *sig; -	sig = tsk->signal; -	if (unlikely(!sig)) +	/* tsk == current, ensure it is safe to use ->signal */ +	if (unlikely(tsk->exit_state))  		return; + +	sig = tsk->signal;  	if (sig->cputime.totals) {  		struct task_cputime *times; @@ -353,8 +357,11 @@ static inline void account_group_exec_runtime(struct task_struct *tsk,  	struct signal_struct *sig;  	sig = tsk->signal; +	/* see __exit_signal()->task_rq_unlock_wait() */ +	barrier();  	if (unlikely(!sig))  		return; +  	if (sig->cputime.totals) {  		struct task_cputime *times;  |