rem: case B_DEBUGGED_THREAD_GET_WHY_STOPPED: { port_id replyPort = commandMessage.get_why_stopped.reply_port;   debug_thread_stopped stoppedMessage; prepare_thread_stopped_message(stoppedMessage, whyStopped, nubPort, additionalData);   error = kill_interruptable_write_port(replyPort, event, &stoppedMessage, sizeof(stoppedMessage));  break; }
context: thread_hit_debug_event_internal(uint32 event, const void *message, int32 size,	debug_why_stopped whyStopped, void *additionalData, bool requireDebugger,	bool &restart){	restart = false;	struct thread *thread = thread_get_current_thread();	TRACE(("thread_hit_debug_event(): thread: %ld, event: %lu, message: %p, "		"size: %ld\n", thread->id, event, message, size));	// check, if there's a debug port already	bool setPort = !(atomic_get(&thread->debug_info.flags)		& B_THREAD_DEBUG_INITIALIZED);	// create a port, if there is none yet	port_id port = -1;	if (setPort) {		char nameBuffer[128];		snprintf(nameBuffer, sizeof(nameBuffer), "nub to thread %ld",			thread->id);		port = create_port(1, nameBuffer);		if (port < 0) {			dprintf("thread_hit_debug_event(): Failed to create debug port: "				"%s\n", strerror(port));			return port;		}		setPort = true;	}	// check the debug info structures once more: get the debugger port, set	// the thread's debug port, and update the thread's debug flags	port_id deletePort = port;	port_id debuggerPort = -1;	port_id nubPort = -1;	status_t error = B_OK;	cpu_status state = disable_interrupts();	GRAB_THREAD_LOCK();	GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);	uint32 threadFlags = thread->debug_info.flags;	threadFlags &= ~B_THREAD_DEBUG_STOP;	bool debuggerInstalled		= (thread->team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED);	if (debuggerInstalled || !requireDebugger) {		if (debuggerInstalled) {			debuggerPort = thread->team->debug_info.debugger_port;			nubPort = thread->team->debug_info.nub_port;		}		if (setPort) {			if (threadFlags & B_THREAD_DEBUG_INITIALIZED) {				// someone created a port for us (the port we've created will				// be deleted below)				port = thread->debug_info.debug_port;			} else {				thread->debug_info.debug_port = port;				deletePort = -1;	// keep the port				threadFlags |= B_THREAD_DEBUG_INITIALIZED;			}		} else {			if (threadFlags & B_THREAD_DEBUG_INITIALIZED) {				port = thread->debug_info.debug_port;			} else {				// someone deleted our port				error = B_ERROR;			}		}	} else		error = B_ERROR;	// update the flags	if (error == B_OK)		threadFlags |= B_THREAD_DEBUG_STOPPED;	atomic_set(&thread->debug_info.flags, threadFlags);	RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);	RELEASE_THREAD_LOCK();	restore_interrupts(state);	// delete the superfluous port	if (deletePort >= 0)		delete_port(deletePort);	if (error != B_OK) {		TRACE(("thread_hit_debug_event() error: thread: %ld, error: %lx\n",			thread->id, error));		return error;	}	// send a message to the debugger port	if (debuggerInstalled) {		TRACE(("thread_hit_debug_event(): thread: %ld, sending message to "			"debugger port %ld\n", thread->id, debuggerPort));		error = debugger_write(debuggerPort, event, message, size, false);	}	status_t result = B_THREAD_DEBUG_HANDLE_EVENT;	bool singleStep = false;	if (error == B_OK) {		bool done = false;		while (!done) {			// read a command from the debug port			int32 command;			debugged_thread_message_data commandMessage;			ssize_t commandMessageSize = kill_interruptable_read_port(port,				&command, &commandMessage, sizeof(commandMessage));			if (commandMessageSize < 0) {				error = commandMessageSize;				TRACE(("thread_hit_debug_event(): thread: %ld, failed "					"to receive message from port %ld: %lx\n",					thread->id, port, error));				break;			}			switch (command) {				case B_DEBUGGED_THREAD_MESSAGE_CONTINUE:					TRACE(("thread_hit_debug_event(): thread: %ld: "						"B_DEBUGGED_THREAD_MESSAGE_CONTINUE\n",						thread->id));					result = commandMessage.continue_thread.handle_event;					singleStep = commandMessage.continue_thread.single_step;					done = true;					break;				case B_DEBUGGED_THREAD_GET_WHY_STOPPED:				{					port_id replyPort						= commandMessage.get_why_stopped.reply_port;					// prepare the message					debug_thread_stopped stoppedMessage;					prepare_thread_stopped_message(stoppedMessage, whyStopped,						nubPort, additionalData);					// send it					error = kill_interruptable_write_port(replyPort, event,						&stoppedMessage, sizeof(stoppedMessage));					break;				}				case B_DEBUGGED_THREAD_SET_CPU_STATE:				{					TRACE(("thread_hit_debug_event(): thread: %ld: "						"B_DEBUGGED_THREAD_SET_CPU_STATE\n",						thread->id));					arch_set_debug_cpu_state(						&commandMessage.set_cpu_state.cpu_state);										break;				}				case B_DEBUGGED_THREAD_DEBUGGER_CHANGED:				{					// Check, if the debugger really changed, i.e. is different					// than the one we know. 					team_debug_info teamDebugInfo;					get_team_debug_info(teamDebugInfo);					if (teamDebugInfo.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {						if (!debuggerInstalled							|| teamDebugInfo.debugger_port != debuggerPort) {							// debugger was installed or has changed: restart							// this function							restart = true;							done = true;						}					} else {						if (debuggerInstalled) {							// debugger is gone: continue the thread normally							done = true;						}					}					break;				}			}		}	} else {		TRACE(("thread_hit_debug_event(): thread: %ld, failed to send "			"message to debugger port %ld: %lx\n", thread->id,			debuggerPort, error));	}	// update the thread debug info	bool destroyThreadInfo = false;	thread_debug_info threadDebugInfo;	state = disable_interrupts();	GRAB_THREAD_LOCK();	// check, if the team is still being debugged	int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags);	if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {		// update the single-step flag		if (singleStep) {			atomic_or(&thread->debug_info.flags,				B_THREAD_DEBUG_SINGLE_STEP);		} else {			atomic_and(&thread->debug_info.flags,				~B_THREAD_DEBUG_SINGLE_STEP);		}		// unset the "stopped" state		atomic_and(&thread->debug_info.flags, ~B_THREAD_DEBUG_STOPPED);	} else {		// the debugger is gone: cleanup our info completely		threadDebugInfo = thread->debug_info;		clear_thread_debug_info(&thread->debug_info, false);		destroyThreadInfo = true;	}	RELEASE_THREAD_LOCK();	restore_interrupts(state);	if (destroyThreadInfo)		destroy_thread_debug_info(&threadDebugInfo);	return (error == B_OK ? result : error);}