From bbe9c7b15eea3db937ae74dfcfa0cd04bb3fe470 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 17 Jun 2009 01:02:33 +0000 Subject: [PATCH] Rewrote user_debug_thread_deleted(): * It was broken since the support for debugger handovers. Using debugger_write() couldn't work, since the thread didn't belong to the debugged team anymore (but to the kernel) and thus getting the debug info for team would always fail. This makes B_DEBUGGER_MESSAGE_THREAD_DELETED notifications work again. * Allow the thread to block. Locking/writing to the port was non-blocking before, but there shouldn't be a problem, if the thread has to wait. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31076 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/debug/user_debugger.cpp | 60 ++++++++++++++++------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/system/kernel/debug/user_debugger.cpp b/src/system/kernel/debug/user_debugger.cpp index caeae4891d..bd745de3e3 100644 --- a/src/system/kernel/debug/user_debugger.cpp +++ b/src/system/kernel/debug/user_debugger.cpp @@ -950,25 +950,24 @@ user_debug_thread_created(thread_id threadID) void user_debug_thread_deleted(team_id teamID, thread_id threadID) { + // Things are a bit complicated here, since this thread no longer belongs to + // the debugged team (but to the kernel). So we can't use debugger_write(). + // get the team debug flags and debugger port - cpu_status state = disable_interrupts(); - GRAB_TEAM_LOCK(); + InterruptsSpinLocker teamLocker(gTeamSpinlock); struct team *team = team_get_team_struct_locked(teamID); + if (team == NULL) + return; - int32 teamDebugFlags = 0; - port_id debuggerPort = -1; - if (team) { - GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info); + SpinLocker debugInfoLocker(team->debug_info.lock); - teamDebugFlags = atomic_get(&team->debug_info.flags); - debuggerPort = team->debug_info.debugger_port; + int32 teamDebugFlags = atomic_get(&team->debug_info.flags); + port_id debuggerPort = team->debug_info.debugger_port; + sem_id writeLock = team->debug_info.debugger_write_lock; - RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info); - } - - RELEASE_TEAM_LOCK(); - restore_interrupts(state); + debugInfoLocker.Unlock(); + teamLocker.Unlock(); // check, if a debugger is installed and is interested in thread events if (~teamDebugFlags @@ -976,16 +975,41 @@ user_debug_thread_deleted(team_id teamID, thread_id threadID) return; } - // notify the debugger - if (debuggerPort >= 0) { + // acquire the debugger write lock + status_t error = acquire_sem_etc(writeLock, 1, B_KILL_CAN_INTERRUPT, 0); + if (error != B_OK) + return; + + // re-get the team debug info -- we need to check whether anything changed + teamLocker.Lock(); + + team = team_get_team_struct_locked(teamID); + if (team == NULL) + return; + + debugInfoLocker.Lock(); + + teamDebugFlags = atomic_get(&team->debug_info.flags); + port_id newDebuggerPort = team->debug_info.debugger_port; + + debugInfoLocker.Unlock(); + teamLocker.Unlock(); + + // Send the message only if the debugger hasn't changed in the meantime or + // the team is about to be handed over. + if (newDebuggerPort == debuggerPort + || (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_HANDOVER) == 0) { debug_thread_deleted message; message.origin.thread = threadID; message.origin.team = teamID; message.origin.nub_port = -1; - debugger_write(debuggerPort, B_DEBUGGER_MESSAGE_THREAD_DELETED, - &message, sizeof(message), true); - // TODO: Would it be OK to wait here? + + write_port_etc(debuggerPort, B_DEBUGGER_MESSAGE_THREAD_DELETED, + &message, sizeof(message), B_KILL_CAN_INTERRUPT, 0); } + + // release the debugger write lock + release_sem(writeLock); }