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
This commit is contained in:
Ingo Weinhold
2009-06-17 01:02:33 +00:00
parent 995aa3f06a
commit bbe9c7b15e
+42 -18
View File
@@ -950,25 +950,24 @@ user_debug_thread_created(thread_id threadID)
void void
user_debug_thread_deleted(team_id teamID, thread_id threadID) 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 // get the team debug flags and debugger port
cpu_status state = disable_interrupts(); InterruptsSpinLocker teamLocker(gTeamSpinlock);
GRAB_TEAM_LOCK();
struct team *team = team_get_team_struct_locked(teamID); struct team *team = team_get_team_struct_locked(teamID);
if (team == NULL)
return;
int32 teamDebugFlags = 0; SpinLocker debugInfoLocker(team->debug_info.lock);
port_id debuggerPort = -1;
if (team) {
GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
teamDebugFlags = atomic_get(&team->debug_info.flags); int32 teamDebugFlags = atomic_get(&team->debug_info.flags);
debuggerPort = team->debug_info.debugger_port; 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); debugInfoLocker.Unlock();
} teamLocker.Unlock();
RELEASE_TEAM_LOCK();
restore_interrupts(state);
// check, if a debugger is installed and is interested in thread events // check, if a debugger is installed and is interested in thread events
if (~teamDebugFlags if (~teamDebugFlags
@@ -976,16 +975,41 @@ user_debug_thread_deleted(team_id teamID, thread_id threadID)
return; return;
} }
// notify the debugger // acquire the debugger write lock
if (debuggerPort >= 0) { 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; debug_thread_deleted message;
message.origin.thread = threadID; message.origin.thread = threadID;
message.origin.team = teamID; message.origin.team = teamID;
message.origin.nub_port = -1; message.origin.nub_port = -1;
debugger_write(debuggerPort, B_DEBUGGER_MESSAGE_THREAD_DELETED,
&message, sizeof(message), true); write_port_etc(debuggerPort, B_DEBUGGER_MESSAGE_THREAD_DELETED,
// TODO: Would it be OK to wait here? &message, sizeof(message), B_KILL_CAN_INTERRUPT, 0);
} }
// release the debugger write lock
release_sem(writeLock);
} }