[Haiku-commits] r31076 - haiku/trunk/src/system/kernel/debug

bonefish at mail.berlios.de bonefish at mail.berlios.de
Wed Jun 17 03:02:34 CEST 2009


Author: bonefish
Date: 2009-06-17 03:02:33 +0200 (Wed, 17 Jun 2009)
New Revision: 31076
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31076&view=rev

Modified:
   haiku/trunk/src/system/kernel/debug/user_debugger.cpp
Log:
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.



Modified: haiku/trunk/src/system/kernel/debug/user_debugger.cpp
===================================================================
--- haiku/trunk/src/system/kernel/debug/user_debugger.cpp	2009-06-17 00:28:36 UTC (rev 31075)
+++ haiku/trunk/src/system/kernel/debug/user_debugger.cpp	2009-06-17 01:02:33 UTC (rev 31076)
@@ -950,42 +950,66 @@
 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);
-	}
+	debugInfoLocker.Unlock();
+	teamLocker.Unlock();
 
-	RELEASE_TEAM_LOCK();
-	restore_interrupts(state);
-
 	// check, if a debugger is installed and is interested in thread events
 	if (~teamDebugFlags
 		& (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_THREADS)) {
 		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);
 }
 
 




More information about the Haiku-commits mailing list