 /* PF_DEAD causes final put_task_struct after we schedule. */ preempt_disable(); tsk->flags |= PF_DEAD; 
static void exit_notify(struct task_struct *tsk){	int state;	struct task_struct *t;	struct list_head ptrace_dead, *_p, *_n;	if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)	    && !thread_group_empty(tsk)) {		/*		 * This occurs when there was a race between our exit		 * syscall and a group signal choosing us as the one to		 * wake up.  It could be that we are the only thread		 * alerted to check for pending signals, but another thread		 * should be woken now to take the signal since we will not.		 * Now we'll wake all the threads in the group just to make		 * sure someone gets all the pending signals.		 */		read_lock(&tasklist_lock);		spin_lock_irq(&tsk->sighand->siglock);		for (t = next_thread(tsk); t != tsk; t = next_thread(t))			if (!signal_pending(t) && !(t->flags & PF_EXITING)) {				recalc_sigpending_tsk(t);				if (signal_pending(t))					signal_wake_up(t, 0);			}		spin_unlock_irq(&tsk->sighand->siglock);		read_unlock(&tasklist_lock);	}	write_lock_irq(&tasklist_lock);	/*	 * This does two things:	 *  	 * A.  Make init inherit all the child processes	 * B.  Check to see if any process groups have become orphaned	 *	as a result of our exiting, and if they have any stopped	 *	jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)	 */	INIT_LIST_HEAD(&ptrace_dead);	forget_original_parent(tsk, &ptrace_dead);	BUG_ON(!list_empty(&tsk->children));	BUG_ON(!list_empty(&tsk->ptrace_children));	/*	 * Check to see if any process groups have become orphaned	 * as a result of our exiting, and if they have any stopped	 * jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)	 *	 * Case i: Our father is in a different pgrp than we are	 * and we were the only connection outside, so our pgrp	 * is about to become orphaned.	 */	 	t = tsk->real_parent;		if ((process_group(t) != process_group(tsk)) &&	    (t->signal->session == tsk->signal->session) &&	    will_become_orphaned_pgrp(process_group(tsk), tsk) &&	    has_stopped_jobs(process_group(tsk))) {		__kill_pg_info(SIGHUP, (void *)1, process_group(tsk));		__kill_pg_info(SIGCONT, (void *)1, process_group(tsk));	}	/* Let father know we died 	 *	 * Thread signals are configurable, but you aren't going to use	 * that to send signals to arbitary processes. 	 * That stops right now.	 *	 * If the parent exec id doesn't match the exec id we saved	 * when we started then we know the parent has changed security	 * domain.	 *	 * If our self_exec id doesn't match our parent_exec_id then	 * we have changed execution domain as these two values started	 * the same after a fork.	 *		 */		if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 &&	    ( tsk->parent_exec_id != t->self_exec_id  ||	      tsk->self_exec_id != tsk->parent_exec_id)	    && !capable(CAP_KILL))		tsk->exit_signal = SIGCHLD;	/* If something other than our normal parent is ptracing us, then	 * send it a SIGCHLD instead of honoring exit_signal.  exit_signal	 * only has special meaning to our real parent.	 */	if (tsk->exit_signal != -1 && thread_group_empty(tsk)) {		int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD;		do_notify_parent(tsk, signal);	} else if (tsk->ptrace) {		do_notify_parent(tsk, SIGCHLD);	}	state = EXIT_ZOMBIE;	if (tsk->exit_signal == -1 &&	    (likely(tsk->ptrace == 0) ||	     unlikely(tsk->parent->signal->flags & SIGNAL_GROUP_EXIT)))		state = EXIT_DEAD;	tsk->exit_state = state;	write_unlock_irq(&tasklist_lock);	list_for_each_safe(_p, _n, &ptrace_dead) {		list_del_init(_p);		t = list_entry(_p,struct task_struct,ptrace_list);		release_task(t);	}	/* If the process is dead, release it - nobody will wait for it */	if (state == EXIT_DEAD)		release_task(tsk);	/* PF_DEAD causes final put_task_struct after we schedule. */	preempt_disable();	tsk->flags |= PF_DEAD;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/7407251a0e2ed099e4b12b742b635503e981507c/exit.c/clean/kernel/exit.c