rem: } else cachedDeathSem = team->death_sem;
add: }
context: thread_exit(void){	cpu_status state;	struct thread *thread = thread_get_current_thread();	struct process_group *freeGroup = NULL;	struct team *team = thread->team;	struct death_entry *death = NULL;	thread_id mainParentThread = -1;	bool deleteTeam = false;	uint32 death_stack;	sem_id cachedDeathSem, parentDeadSem = -1, groupDeadSem = -1;	status_t status;	struct thread_debug_info debugInfo;	team_id teamID = team->id;	if (!are_interrupts_enabled())		dprintf("thread_exit() called with interrupts disabled!\n");	TRACE(("thread 0x%lx exiting %s w/return code 0x%x\n", thread->id,		thread->exit.reason == THREAD_RETURN_INTERRUPTED ? "due to signal" : "normally",		(int)thread->exit.status));	// boost our priority to get this over with	thread->priority = B_URGENT_DISPLAY_PRIORITY;	// stop debugging for this thread	state = disable_interrupts();	GRAB_THREAD_LOCK();	debugInfo = thread->debug_info;	clear_thread_debug_info(&thread->debug_info, true);	RELEASE_THREAD_LOCK();	restore_interrupts(state);	destroy_thread_debug_info(&debugInfo);	// shutdown the thread messaging	status = acquire_sem_etc(thread->msg.write_sem, 1, B_RELATIVE_TIMEOUT, 0);	if (status == B_WOULD_BLOCK) {		// there is data waiting for us, so let us eat it		thread_id sender;		delete_sem(thread->msg.write_sem);			// first, let's remove all possibly waiting writers		receive_data_etc(&sender, NULL, 0, B_RELATIVE_TIMEOUT);	} else {		// we probably own the semaphore here, and we're the last to do so		delete_sem(thread->msg.write_sem);	}	// now we can safely remove the msg.read_sem	delete_sem(thread->msg.read_sem);	// Cancel previously installed alarm timer, if any	cancel_timer(&thread->alarm);	// delete the user stack area first, we won't need it anymore	if (team->aspace != NULL && thread->user_stack_area >= 0) {		area_id area = thread->user_stack_area;		thread->user_stack_area = -1;		delete_area_etc(team, area);	}	if (team != team_get_kernel_team()) {		if (team->main_thread == thread) {			// this was the main thread in this team, so we will delete that as well			deleteTeam = true;			// put a death entry into the dead children list of our parent			death = (struct death_entry *)malloc(sizeof(struct death_entry));			if (death != NULL) {				death->team = team->id;				death->thread = thread->id;				death->status = thread->exit.status;				death->reason = thread->exit.reason;			}		}		// remove this thread from the current team and add it to the kernel		// put the thread into the kernel team until it dies		state = disable_interrupts();		GRAB_TEAM_LOCK();		// remember how long this thread lasted		team->dead_threads_kernel_time += thread->kernel_time;		team->dead_threads_user_time += thread->user_time;		remove_thread_from_team(team, thread);		insert_thread_into_team(team_get_kernel_team(), thread);		if (deleteTeam) {			struct team *parent = team->parent;			// remember who our parent was so we can send a signal			mainParentThread = parent->main_thread->id;			if (death != NULL) {				// insert death entry into the parent's list				list_add_link_to_tail(&parent->dead_children.list, death);				if (++parent->dead_children.count > MAX_DEAD_CHILDREN) {					death = list_remove_head_item(&parent->dead_children.list);					parent->dead_children.count--;				} else					death = NULL;				parentDeadSem = parent->dead_children.sem;				groupDeadSem = team->group->dead_child_sem;			}			// remember how long this team lasted			parent->dead_children.kernel_time += team->dead_threads_kernel_time;			parent->dead_children.user_time += team->dead_threads_user_time;			team_remove_team(team, &freeGroup);		}		RELEASE_TEAM_LOCK();		// swap address spaces, to make sure we're running on the kernel's pgdir		vm_aspace_swap(team_get_kernel_team()->kaspace);		restore_interrupts(state);		TRACE(("thread_exit: thread 0x%lx now a kernel thread!\n", thread->id));	}	// delete the team if we're its main thread	if (deleteTeam) {		// notify listeners that a new death entry is available		// ToDo: should that be moved to handle_signal() (for SIGCHLD)?		release_sem_etc(parentDeadSem, 0, B_RELEASE_ALL | B_DO_NOT_RESCHEDULE);		release_sem_etc(groupDeadSem, 0, B_RELEASE_ALL | B_DO_NOT_RESCHEDULE);		team_delete_process_group(freeGroup);		team_delete_team(team);		// we need to remove any death entry that made it to here		if (death != NULL)			free(death);		send_signal_etc(mainParentThread, SIGCHLD, B_DO_NOT_RESCHEDULE);		cachedDeathSem = -1;	} else		cachedDeathSem = team->death_sem;	// fill all death entries and delete the sem that others will use to wait on us	{		sem_id cachedExitSem = thread->exit.sem;		cpu_status state;		state = disable_interrupts();		GRAB_THREAD_LOCK();		// make sure no one will grab this semaphore again		thread->exit.sem = -1;		// fill all death entries		death = NULL;		while ((death = list_get_next_item(&thread->exit.waiters, death)) != NULL) {			death->status = thread->exit.status;			death->reason = thread->exit.reason;		}		RELEASE_THREAD_LOCK();		restore_interrupts(state);		delete_sem(cachedExitSem);	}	{		struct thread_exit_args args;		args.int_state = get_death_stack(&death_stack);			// this disables interrups for us		args.thread = thread;		args.old_kernel_stack = thread->kernel_stack_area;		args.death_stack = death_stack;		args.death_sem = cachedDeathSem;		args.original_team_id = teamID;		// set the new kernel stack officially to the death stack, wont be really switched until		// the next function is called. This bookkeeping must be done now before a context switch		// happens, or the processor will interrupt to the old stack		thread->kernel_stack_area = sDeathStacks[death_stack].area;		thread->kernel_stack_base = sDeathStacks[death_stack].address;		// we will continue in thread_exit2(), on the new stack		arch_thread_switch_kstack_and_call(thread, thread->kernel_stack_base + KERNEL_STACK_SIZE,			thread_exit2, &args);	}	panic("never can get here\n");}