diff options
Diffstat (limited to 'kernel/exit.c')
| -rw-r--r-- | kernel/exit.c | 31 | 
1 files changed, 28 insertions, 3 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 84021b24f79e..35e0a31a0315 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -60,6 +60,7 @@  #include <linux/writeback.h>  #include <linux/shm.h>  #include <linux/kcov.h> +#include <linux/kmsan.h>  #include <linux/random.h>  #include <linux/rcuwait.h>  #include <linux/compat.h> @@ -183,6 +184,10 @@ void put_task_struct_rcu_user(struct task_struct *task)  		call_rcu(&task->rcu, delayed_put_task_struct);  } +void __weak release_thread(struct task_struct *dead_task) +{ +} +  void release_task(struct task_struct *p)  {  	struct task_struct *leader; @@ -374,10 +379,10 @@ static void coredump_task_exit(struct task_struct *tsk)  			complete(&core_state->startup);  		for (;;) { -			set_current_state(TASK_UNINTERRUPTIBLE); +			set_current_state(TASK_UNINTERRUPTIBLE|TASK_FREEZABLE);  			if (!self.task) /* see coredump_finish() */  				break; -			freezable_schedule(); +			schedule();  		}  		__set_current_state(TASK_RUNNING);  	} @@ -466,6 +471,7 @@ assign_new_owner:  		goto retry;  	}  	WRITE_ONCE(mm->owner, c); +	lru_gen_migrate_mm(mm);  	task_unlock(c);  	put_task_struct(c);  } @@ -733,14 +739,33 @@ static void check_stack_usage(void)  static inline void check_stack_usage(void) {}  #endif +static void synchronize_group_exit(struct task_struct *tsk, long code) +{ +	struct sighand_struct *sighand = tsk->sighand; +	struct signal_struct *signal = tsk->signal; + +	spin_lock_irq(&sighand->siglock); +	signal->quick_threads--; +	if ((signal->quick_threads == 0) && +	    !(signal->flags & SIGNAL_GROUP_EXIT)) { +		signal->flags = SIGNAL_GROUP_EXIT; +		signal->group_exit_code = code; +		signal->group_stop_count = 0; +	} +	spin_unlock_irq(&sighand->siglock); +} +  void __noreturn do_exit(long code)  {  	struct task_struct *tsk = current;  	int group_dead; +	synchronize_group_exit(tsk, code); +  	WARN_ON(tsk->plug);  	kcov_task_exit(tsk); +	kmsan_task_exit(tsk);  	coredump_task_exit(tsk);  	ptrace_event(PTRACE_EVENT_EXIT, code); @@ -905,7 +930,7 @@ do_group_exit(int exit_code)  		exit_code = sig->group_exit_code;  	else if (sig->group_exec_task)  		exit_code = 0; -	else if (!thread_group_empty(current)) { +	else {  		struct sighand_struct *const sighand = current->sighand;  		spin_lock_irq(&sighand->siglock);  |