[Haiku-commits] r31221 - haiku/trunk/src/apps/debugger

bonefish at BerliOS bonefish at mail.berlios.de
Wed Jun 24 03:46:40 CEST 2009


Author: bonefish
Date: 2009-06-24 03:46:38 +0200 (Wed, 24 Jun 2009)
New Revision: 31221
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31221&view=rev

Added:
   haiku/trunk/src/apps/debugger/ThreadHandler.cpp
   haiku/trunk/src/apps/debugger/ThreadHandler.h
Modified:
   haiku/trunk/src/apps/debugger/Jamfile
   haiku/trunk/src/apps/debugger/Jobs.cpp
   haiku/trunk/src/apps/debugger/Jobs.h
   haiku/trunk/src/apps/debugger/TeamDebugger.cpp
   haiku/trunk/src/apps/debugger/TeamDebugger.h
Log:
* Moved all handling of threads from TeamDebugger into new class ThreadHandler.
* Added new job to get the initial state of a thread.
* Now we also get the states of new threads correctly.


Modified: haiku/trunk/src/apps/debugger/Jamfile
===================================================================
--- haiku/trunk/src/apps/debugger/Jamfile	2009-06-24 00:25:21 UTC (rev 31220)
+++ haiku/trunk/src/apps/debugger/Jamfile	2009-06-24 01:46:38 UTC (rev 31221)
@@ -25,6 +25,7 @@
 #	ElfFile.cpp
 	Jobs.cpp
 	TeamDebugger.cpp
+	ThreadHandler.cpp
 	Worker.cpp
 
 	# arch

Modified: haiku/trunk/src/apps/debugger/Jobs.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/Jobs.cpp	2009-06-24 00:25:21 UTC (rev 31220)
+++ haiku/trunk/src/apps/debugger/Jobs.cpp	2009-06-24 01:46:38 UTC (rev 31221)
@@ -22,6 +22,56 @@
 #include "Thread.h"
 
 
+// #pragma mark - GetThreadStateJob
+
+
+GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface,
+	Thread* thread)
+	:
+	fDebuggerInterface(debuggerInterface),
+	fThread(thread)
+{
+	fThread->AddReference();
+}
+
+
+GetThreadStateJob::~GetThreadStateJob()
+{
+	fThread->RemoveReference();
+}
+
+
+JobKey
+GetThreadStateJob::Key() const
+{
+	return JobKey(fThread, JOB_TYPE_GET_THREAD_STATE);
+}
+
+
+status_t
+GetThreadStateJob::Do()
+{
+	CpuState* state = NULL;
+	status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state);
+	Reference<CpuState> reference(state, true);
+
+	AutoLocker<Team> locker(fThread->GetTeam());
+
+	if (fThread->State() != THREAD_STATE_UNKNOWN)
+		return B_OK;
+
+	if (error == B_OK) {
+		fThread->SetState(THREAD_STATE_STOPPED);
+		fThread->SetCpuState(state);
+	} else if (error == B_BAD_THREAD_STATE) {
+		fThread->SetState(THREAD_STATE_RUNNING);
+	} else
+		return error;
+
+	return B_OK;
+}
+
+
 // #pragma mark - GetCpuStateJob
 
 

Modified: haiku/trunk/src/apps/debugger/Jobs.h
===================================================================
--- haiku/trunk/src/apps/debugger/Jobs.h	2009-06-24 00:25:21 UTC (rev 31220)
+++ haiku/trunk/src/apps/debugger/Jobs.h	2009-06-24 01:46:38 UTC (rev 31221)
@@ -20,6 +20,7 @@
 
 // job types
 enum {
+	JOB_TYPE_GET_THREAD_STATE,
 	JOB_TYPE_GET_CPU_STATE,
 	JOB_TYPE_GET_STACK_TRACE,
 	JOB_TYPE_LOAD_IMAGE_DEBUG_INFO,
@@ -27,6 +28,22 @@
 };
 
 
+class GetThreadStateJob : public Job {
+public:
+								GetThreadStateJob(
+									DebuggerInterface* debuggerInterface,
+									Thread* thread);
+	virtual						~GetThreadStateJob();
+
+	virtual	JobKey				Key() const;
+	virtual	status_t			Do();
+
+private:
+			DebuggerInterface*	fDebuggerInterface;
+			Thread*				fThread;
+};
+
+
 class GetCpuStateJob : public Job {
 public:
 								GetCpuStateJob(

Modified: haiku/trunk/src/apps/debugger/TeamDebugger.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/TeamDebugger.cpp	2009-06-24 00:25:21 UTC (rev 31220)
+++ haiku/trunk/src/apps/debugger/TeamDebugger.cpp	2009-06-24 01:46:38 UTC (rev 31221)
@@ -59,6 +59,13 @@
 	if (fDebugEventListener >= 0)
 		wait_for_thread(fDebugEventListener, NULL);
 
+	ThreadHandler* threadHandler = fThreadHandlers.Clear(true);
+	while (threadHandler != NULL) {
+		ThreadHandler* next = threadHandler->fNext;
+		threadHandler->RemoveReference();
+		threadHandler = next;
+	}
+
 	delete fDebuggerInterface;
 	delete fWorker;
 	delete fDebugModel;
@@ -92,6 +99,11 @@
 
 	fTeam->AddListener(this);
 
+	// init thread handler table
+	error = fThreadHandlers.Init();
+	if (error != B_OK)
+		return error;
+
 	// create our worker
 	fWorker = new(std::nothrow) Worker;
 	if (fWorker == NULL)
@@ -136,7 +148,14 @@
 			if (error != B_OK)
 				return error;
 
-			_UpdateThreadState(thread);
+			ThreadHandler* handler = new(std::nothrow) ThreadHandler(
+				fDebugModel, thread, fWorker, fDebuggerInterface);
+			if (handler == NULL)
+				return B_NO_MEMORY;
+
+			fThreadHandlers.Insert(handler);
+
+			handler->Init();
 		}
 	}
 
@@ -204,7 +223,10 @@
 			if (message->FindInt32("thread", &threadID) != B_OK)
 				break;
 
-			_HandleThreadAction(threadID, message->what);
+			if (ThreadHandler* handler = _GetThreadHandler(threadID)) {
+				handler->HandleThreadAction(message->what);
+				handler->RemoveReference();
+			}
 			break;
 		}
 
@@ -232,7 +254,10 @@
 			if (message->FindInt32("thread", &threadID) != B_OK)
 				break;
 
-			_HandleThreadStateChanged(threadID);
+			if (ThreadHandler* handler = _GetThreadHandler(threadID)) {
+				handler->HandleThreadStateChanged();
+				handler->RemoveReference();
+			}
 			break;
 		}
 		case MSG_THREAD_CPU_STATE_CHANGED:
@@ -241,7 +266,10 @@
 			if (message->FindInt32("thread", &threadID) != B_OK)
 				break;
 
-			_HandleCpuStateChanged(threadID);
+			if (ThreadHandler* handler = _GetThreadHandler(threadID)) {
+				handler->HandleCpuStateChanged();
+				handler->RemoveReference();
+			}
 			break;
 		}
 		case MSG_THREAD_STACK_TRACE_CHANGED:
@@ -250,7 +278,10 @@
 			if (message->FindInt32("thread", &threadID) != B_OK)
 				break;
 
-			_HandleStackTraceChanged(threadID);
+			if (ThreadHandler* handler = _GetThreadHandler(threadID)) {
+				handler->HandleStackTraceChanged();
+				handler->RemoveReference();
+			}
 			break;
 		}
 
@@ -448,35 +479,51 @@
 printf("TeamDebugger::_HandleDebuggerMessage(): %d\n", event->EventType());
 	bool handled = false;
 
+	ThreadHandler* handler = _GetThreadHandler(event->Thread());
+	Reference<ThreadHandler> handlerReference(handler);
+
 	switch (event->EventType()) {
 		case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
 printf("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %ld\n", event->Thread());
-			handled = _HandleThreadDebugged(
-				dynamic_cast<ThreadDebuggedEvent*>(event));
+			if (handler != NULL) {
+				handled = handler->HandleThreadDebugged(
+					dynamic_cast<ThreadDebuggedEvent*>(event));
+			}
 			break;
 		case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
 printf("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %ld\n", event->Thread());
-			handled = _HandleDebuggerCall(
-				dynamic_cast<DebuggerCallEvent*>(event));
+			if (handler != NULL) {
+				handled = handler->HandleDebuggerCall(
+					dynamic_cast<DebuggerCallEvent*>(event));
+			}
 			break;
 		case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
 printf("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %ld\n", event->Thread());
-			handled = _HandleBreakpointHit(
-				dynamic_cast<BreakpointHitEvent*>(event));
+			if (handler != NULL) {
+				handled = handler->HandleBreakpointHit(
+					dynamic_cast<BreakpointHitEvent*>(event));
+			}
 			break;
 		case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
 printf("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %ld\n", event->Thread());
-			handled = _HandleWatchpointHit(
-				dynamic_cast<WatchpointHitEvent*>(event));
+			if (handler != NULL) {
+				handled = handler->HandleWatchpointHit(
+					dynamic_cast<WatchpointHitEvent*>(event));
+			}
 			break;
 		case B_DEBUGGER_MESSAGE_SINGLE_STEP:
 printf("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %ld\n", event->Thread());
-			handled = _HandleSingleStep(dynamic_cast<SingleStepEvent*>(event));
+			if (handler != NULL) {
+				handled = handler->HandleSingleStep(
+					dynamic_cast<SingleStepEvent*>(event));
+			}
 			break;
 		case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
 printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", event->Thread());
-			handled = _HandleExceptionOccurred(
-				dynamic_cast<ExceptionOccurredEvent*>(event));
+			if (handler != NULL) {
+				handled = handler->HandleExceptionOccurred(
+					dynamic_cast<ExceptionOccurredEvent*>(event));
+			}
 			break;
 //		case B_DEBUGGER_MESSAGE_TEAM_CREATED:
 //printf("B_DEBUGGER_MESSAGE_TEAM_CREATED: team: %ld\n", message.team_created.new_team);
@@ -524,63 +571,6 @@
 
 
 bool
-TeamDebugger::_HandleThreadStopped(thread_id threadID, CpuState* cpuState)
-{
-	// get the thread
-	AutoLocker< ::Team> locker(fTeam);
-	::Thread* thread = fTeam->ThreadByID(threadID);
-	if (thread == NULL)
-		return false;
-
-	_SetThreadState(thread, THREAD_STATE_STOPPED, cpuState);
-
-	return true;
-}
-
-
-bool
-TeamDebugger::_HandleThreadDebugged(ThreadDebuggedEvent* event)
-{
-	return _HandleThreadStopped(event->Thread(), NULL);
-}
-
-
-bool
-TeamDebugger::_HandleDebuggerCall(DebuggerCallEvent* event)
-{
-	return _HandleThreadStopped(event->Thread(), NULL);
-}
-
-
-bool
-TeamDebugger::_HandleBreakpointHit(BreakpointHitEvent* event)
-{
-	return _HandleThreadStopped(event->Thread(), event->GetCpuState());
-}
-
-
-bool
-TeamDebugger::_HandleWatchpointHit(WatchpointHitEvent* event)
-{
-	return _HandleThreadStopped(event->Thread(), event->GetCpuState());
-}
-
-
-bool
-TeamDebugger::_HandleSingleStep(SingleStepEvent* event)
-{
-	return _HandleThreadStopped(event->Thread(), event->GetCpuState());
-}
-
-
-bool
-TeamDebugger::_HandleExceptionOccurred(ExceptionOccurredEvent* event)
-{
-	return _HandleThreadStopped(event->Thread(), NULL);
-}
-
-
-bool
 TeamDebugger::_HandleThreadCreated(ThreadCreatedEvent* event)
 {
 	AutoLocker< ::Team> locker(fTeam);
@@ -588,9 +578,18 @@
 	ThreadInfo info;
 	status_t error = fDebuggerInterface->GetThreadInfo(event->NewThread(),
 		info);
-	if (error == B_OK)
-		fTeam->AddThread(info);
+	if (error == B_OK) {
+		::Thread* thread;
+		fTeam->AddThread(info, &thread);
 
+		ThreadHandler* handler = new(std::nothrow) ThreadHandler(
+			fDebugModel, thread, fWorker, fDebuggerInterface);
+		if (handler != NULL) {
+			fThreadHandlers.Insert(handler);
+			handler->Init();
+		}
+	}
+
 	return false;
 }
 
@@ -599,6 +598,10 @@
 TeamDebugger::_HandleThreadDeleted(ThreadDeletedEvent* event)
 {
 	AutoLocker< ::Team> locker(fTeam);
+	if (ThreadHandler* handler = fThreadHandlers.Lookup(event->Thread())) {
+		fThreadHandlers.Remove(handler);
+		handler->RemoveReference();
+	}
 	fTeam->RemoveThread(event->Thread());
 	return false;
 }
@@ -622,32 +625,6 @@
 }
 
 
-void
-TeamDebugger::_UpdateThreadState(::Thread* thread)
-{
-	CpuState* cpuState = NULL;
-	status_t error = fDebuggerInterface->GetCpuState(thread->ID(), cpuState);
-
-	uint32 newState = THREAD_STATE_UNKNOWN;
-	if (error == B_OK) {
-		newState = THREAD_STATE_STOPPED;
-		cpuState->RemoveReference();
-	} else if (error == B_BAD_THREAD_STATE)
-		newState = THREAD_STATE_RUNNING;
-
-	_SetThreadState(thread, newState, cpuState);
-}
-
-
-void
-TeamDebugger::_SetThreadState(::Thread* thread, uint32 state,
-	CpuState* cpuState)
-{
-	thread->SetState(state);
-	thread->SetCpuState(cpuState);
-}
-
-
 status_t
 TeamDebugger::_SetUserBreakpoint(target_addr_t address, bool enabled)
 {
@@ -716,56 +693,6 @@
 
 
 void
-TeamDebugger::_HandleThreadAction(thread_id threadID, uint32 action)
-{
-	AutoLocker< ::Team> locker(fTeam);
-
-	::Thread* thread = fTeam->ThreadByID(threadID);
-	if (thread == NULL || thread->State() == THREAD_STATE_UNKNOWN)
-		return;
-
-	// When stop is requested, thread must be running, otherwise stopped.
-	if (action == MSG_THREAD_STOP
-			? thread->State() != THREAD_STATE_RUNNING
-			: thread->State() != THREAD_STATE_STOPPED) {
-		return;
-	}
-
-	// When continuing the thread update thread state before actually issuing
-	// the command, since we need to unlock.
-	if (action != MSG_THREAD_STOP)
-		_SetThreadState(thread, THREAD_STATE_RUNNING, NULL);
-
-	locker.Unlock();
-
-	switch (action) {
-		case MSG_THREAD_RUN:
-printf("MSG_THREAD_RUN\n");
-			fDebuggerInterface->ContinueThread(threadID);
-			break;
-		case MSG_THREAD_STOP:
-printf("MSG_THREAD_STOP\n");
-			fDebuggerInterface->StopThread(threadID);
-			break;
-		case MSG_THREAD_STEP_OVER:
-printf("MSG_THREAD_STEP_OVER\n");
-			fDebuggerInterface->SingleStepThread(threadID);
-			break;
-		case MSG_THREAD_STEP_INTO:
-printf("MSG_THREAD_STEP_INTO\n");
-			fDebuggerInterface->SingleStepThread(threadID);
-			break;
-		case MSG_THREAD_STEP_OUT:
-printf("MSG_THREAD_STEP_OUT\n");
-			fDebuggerInterface->SingleStepThread(threadID);
-			break;
-
-// TODO: Handle stepping correctly!
-	}
-}
-
-
-void
 TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address, bool enabled)
 {
 printf("TeamDebugger::_HandleSetUserBreakpoint(%#llx, %d)\n", address, enabled);
@@ -806,59 +733,19 @@
 }
 
 
-void
-TeamDebugger::_HandleThreadStateChanged(thread_id threadID)
+ThreadHandler*
+TeamDebugger::_GetThreadHandler(thread_id threadID)
 {
-	AutoLocker< ::Team> teamLocker(fTeam);
+	AutoLocker<TeamDebugModel> locker(fDebugModel);
 
-	::Thread* thread = fTeam->ThreadByID(threadID);
-	if (thread == NULL)
-		return;
-
-	// cancel jobs for this thread
-	fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_CPU_STATE));
-	fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_STACK_TRACE));
-
-	// If the thread is stopped and has no CPU state yet, schedule a job.
-	if (thread->State() == THREAD_STATE_STOPPED
-			&& thread->GetCpuState() == NULL) {
-		fWorker->ScheduleJob(
-			new(std::nothrow) GetCpuStateJob(fDebuggerInterface, thread),
-			this);
-	}
+	ThreadHandler* handler = fThreadHandlers.Lookup(threadID);
+	if (handler != NULL)
+		handler->AddReference();
+	return handler;
 }
 
 
 void
-TeamDebugger::_HandleCpuStateChanged(thread_id threadID)
-{
-	AutoLocker< ::Team> teamLocker(fTeam);
-
-	::Thread* thread = fTeam->ThreadByID(threadID);
-	if (thread == NULL)
-		return;
-
-	// cancel stack trace job for this thread
-	fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_STACK_TRACE));
-
-	// If the thread has a CPU state, but no stack trace yet, schedule a job.
-	if (thread->GetCpuState() != NULL && thread->GetStackTrace() == NULL) {
-		fWorker->ScheduleJob(
-			new(std::nothrow) GetStackTraceJob(fDebuggerInterface,
-				fDebuggerInterface->GetArchitecture(), thread),
-			this);
-	}
-}
-
-
-void
-TeamDebugger::_HandleStackTraceChanged(thread_id threadID)
-{
-printf("TeamDebugger::_HandleStackTraceChanged()\n");
-}
-
-
-void
 TeamDebugger::_NotifyUser(const char* title, const char* text,...)
 {
 	// print the message

Modified: haiku/trunk/src/apps/debugger/TeamDebugger.h
===================================================================
--- haiku/trunk/src/apps/debugger/TeamDebugger.h	2009-06-24 00:25:21 UTC (rev 31220)
+++ haiku/trunk/src/apps/debugger/TeamDebugger.h	2009-06-24 01:46:38 UTC (rev 31221)
@@ -13,6 +13,7 @@
 #include "DebugEvent.h"
 #include "Team.h"
 #include "TeamWindow.h"
+#include "ThreadHandler.h"
 #include "Worker.h"
 
 
@@ -66,21 +67,6 @@
 
 			void				_HandleDebuggerMessage(DebugEvent* event);
 
-			bool				_HandleThreadStopped(thread_id threadID,
-									CpuState* cpuState);
-
-			bool				_HandleThreadDebugged(
-									ThreadDebuggedEvent* event);
-			bool				_HandleDebuggerCall(
-									DebuggerCallEvent* event);
-			bool				_HandleBreakpointHit(
-									BreakpointHitEvent* event);
-			bool				_HandleWatchpointHit(
-									WatchpointHitEvent* event);
-			bool				_HandleSingleStep(
-									SingleStepEvent* event);
-			bool				_HandleExceptionOccurred(
-									ExceptionOccurredEvent* event);
 			bool				_HandleThreadCreated(
 									ThreadCreatedEvent* event);
 			bool				_HandleThreadDeleted(
@@ -90,24 +76,18 @@
 			bool				_HandleImageDeleted(
 									ImageDeletedEvent* event);
 
-			void				_UpdateThreadState(::Thread* thread);
-			void				_SetThreadState(::Thread* thread, uint32 state,
-									CpuState* cpuState);
 
 			status_t			_SetUserBreakpoint(target_addr_t address,
 									bool enabled);
 
-			void				_HandleThreadAction(thread_id threadID,
-									uint32 action);
 			void				_HandleSetUserBreakpoint(target_addr_t address,
 									bool enabled);
 			void				_HandleClearUserBreakpoint(
 									target_addr_t address);
 
-			void				_HandleThreadStateChanged(thread_id threadID);
-			void				_HandleCpuStateChanged(thread_id threadID);
-			void				_HandleStackTraceChanged(thread_id threadID);
 
+			ThreadHandler*		_GetThreadHandler(thread_id threadID);
+
 			void				_NotifyUser(const char* title,
 									const char* text,...);
 
@@ -116,7 +96,8 @@
 			::Team*				fTeam;
 			TeamDebugModel*		fDebugModel;
 			team_id				fTeamID;
-			port_id				fNubPort;
+			ThreadHandlerTable	fThreadHandlers;
+									// protected by the team lock
 			DebuggerInterface*	fDebuggerInterface;
 			Worker*				fWorker;
 			thread_id			fDebugEventListener;

Added: haiku/trunk/src/apps/debugger/ThreadHandler.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/ThreadHandler.cpp	2009-06-24 00:25:21 UTC (rev 31220)
+++ haiku/trunk/src/apps/debugger/ThreadHandler.cpp	2009-06-24 01:46:38 UTC (rev 31221)
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold at gmx.de.
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "ThreadHandler.h"
+
+#include <stdio.h>
+
+#include <new>
+
+#include <AutoLocker.h>
+
+#include "CpuState.h"
+#include "DebuggerInterface.h"
+#include "Jobs.h"
+#include "MessageCodes.h"
+#include "Team.h"
+#include "TeamDebugModel.h"
+#include "Worker.h"
+
+
+ThreadHandler::ThreadHandler(TeamDebugModel* debugModel, Thread* thread,
+	Worker* worker, DebuggerInterface* debuggerInterface)
+	:
+	fDebugModel(debugModel),
+	fThread(thread),
+	fWorker(worker),
+	fDebuggerInterface(debuggerInterface)
+{
+}
+
+
+ThreadHandler::~ThreadHandler()
+{
+}
+
+
+void
+ThreadHandler::Init()
+{
+	fWorker->ScheduleJob(new(std::nothrow) GetThreadStateJob(fDebuggerInterface,
+		fThread));
+}
+
+
+bool
+ThreadHandler::HandleThreadDebugged(ThreadDebuggedEvent* event)
+{
+	return _HandleThreadStopped(NULL);
+}
+
+
+bool
+ThreadHandler::HandleDebuggerCall(DebuggerCallEvent* event)
+{
+	return _HandleThreadStopped(NULL);
+}
+
+
+bool
+ThreadHandler::HandleBreakpointHit(BreakpointHitEvent* event)
+{
+	return _HandleThreadStopped(event->GetCpuState());
+}
+
+
+bool
+ThreadHandler::HandleWatchpointHit(WatchpointHitEvent* event)
+{
+	return _HandleThreadStopped(event->GetCpuState());
+}
+
+
+bool
+ThreadHandler::HandleSingleStep(SingleStepEvent* event)
+{
+	return _HandleThreadStopped(event->GetCpuState());
+}
+
+
+bool
+ThreadHandler::HandleExceptionOccurred(ExceptionOccurredEvent* event)
+{
+	return _HandleThreadStopped(NULL);
+}
+
+
+void
+ThreadHandler::HandleThreadAction(uint32 action)
+{
+	AutoLocker<TeamDebugModel> locker(fDebugModel);
+
+	if (fThread->State() == THREAD_STATE_UNKNOWN)
+		return;
+
+	// When stop is requested, thread must be running, otherwise stopped.
+	if (action == MSG_THREAD_STOP
+			? fThread->State() != THREAD_STATE_RUNNING
+			: fThread->State() != THREAD_STATE_STOPPED) {
+		return;
+	}
+
+	// When continuing the thread update thread state before actually issuing
+	// the command, since we need to unlock.
+	if (action != MSG_THREAD_STOP)
+		_SetThreadState(THREAD_STATE_RUNNING, NULL);
+
+	locker.Unlock();
+
+	switch (action) {
+		case MSG_THREAD_RUN:
+printf("MSG_THREAD_RUN\n");
+			fDebuggerInterface->ContinueThread(ThreadID());
+			break;
+		case MSG_THREAD_STOP:
+printf("MSG_THREAD_STOP\n");
+			fDebuggerInterface->StopThread(ThreadID());
+			break;
+		case MSG_THREAD_STEP_OVER:
+printf("MSG_THREAD_STEP_OVER\n");
+			fDebuggerInterface->SingleStepThread(ThreadID());
+			break;
+		case MSG_THREAD_STEP_INTO:
+printf("MSG_THREAD_STEP_INTO\n");
+			fDebuggerInterface->SingleStepThread(ThreadID());
+			break;
+		case MSG_THREAD_STEP_OUT:
+printf("MSG_THREAD_STEP_OUT\n");
+			fDebuggerInterface->SingleStepThread(ThreadID());
+			break;
+
+// TODO: Handle stepping correctly!
+	}
+}
+
+
+void
+ThreadHandler::HandleThreadStateChanged()
+{
+	AutoLocker<TeamDebugModel> locker(fDebugModel);
+
+	// cancel jobs for this thread
+	fWorker->AbortJob(JobKey(fThread, JOB_TYPE_GET_CPU_STATE));
+	fWorker->AbortJob(JobKey(fThread, JOB_TYPE_GET_STACK_TRACE));
+
+	// If the thread is stopped and has no CPU state yet, schedule a job.
+	if (fThread->State() == THREAD_STATE_STOPPED
+			&& fThread->GetCpuState() == NULL) {
+		fWorker->ScheduleJob(
+			new(std::nothrow) GetCpuStateJob(fDebuggerInterface, fThread));
+	}
+}
+
+
+void
+ThreadHandler::HandleCpuStateChanged()
+{
+	AutoLocker<TeamDebugModel> locker(fDebugModel);
+
+	// cancel stack trace job for this thread
+	fWorker->AbortJob(JobKey(fThread, JOB_TYPE_GET_STACK_TRACE));
+
+	// If the thread has a CPU state, but no stack trace yet, schedule a job.
+	if (fThread->GetCpuState() != NULL && fThread->GetStackTrace() == NULL) {
+		fWorker->ScheduleJob(
+			new(std::nothrow) GetStackTraceJob(fDebuggerInterface,
+				fDebuggerInterface->GetArchitecture(), fThread));
+	}
+}
+
+
+void
+ThreadHandler::HandleStackTraceChanged()
+{
+printf("ThreadHandler::_HandleStackTraceChanged()\n");
+}
+
+
+bool
+ThreadHandler::_HandleThreadStopped(CpuState* cpuState)
+{
+	AutoLocker<TeamDebugModel> locker(fDebugModel);
+
+	_SetThreadState(THREAD_STATE_STOPPED, cpuState);
+
+	return true;
+}
+
+
+void
+ThreadHandler::_SetThreadState(uint32 state, CpuState* cpuState)
+{
+	fThread->SetState(state);
+	fThread->SetCpuState(cpuState);
+}

Added: haiku/trunk/src/apps/debugger/ThreadHandler.h
===================================================================
--- haiku/trunk/src/apps/debugger/ThreadHandler.h	2009-06-24 00:25:21 UTC (rev 31220)
+++ haiku/trunk/src/apps/debugger/ThreadHandler.h	2009-06-24 01:46:38 UTC (rev 31221)
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold at gmx.de.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef THREAD_HANDLER_H
+#define THREAD_HANDLER_H
+
+#include <Referenceable.h>
+#include <util/OpenHashTable.h>
+
+#include "DebugEvent.h"
+#include "Thread.h"
+
+
+class DebuggerInterface;
+class TeamDebugModel;
+class Worker;
+
+
+class ThreadHandler : public Referenceable,
+	public HashTableLink<ThreadHandler> {
+public:
+								ThreadHandler(TeamDebugModel* debugModel,
+									Thread* thread, Worker* worker,
+									DebuggerInterface* debuggerInterface);
+								~ThreadHandler();
+
+			void				Init();
+
+			thread_id			ThreadID() const	{ return fThread->ID(); }
+			Thread*				GetThread() const	{ return fThread; }
+
+			bool				HandleThreadDebugged(
+									ThreadDebuggedEvent* event);
+			bool				HandleDebuggerCall(
+									DebuggerCallEvent* event);
+			bool				HandleBreakpointHit(
+									BreakpointHitEvent* event);
+			bool				HandleWatchpointHit(
+									WatchpointHitEvent* event);
+			bool				HandleSingleStep(
+									SingleStepEvent* event);
+			bool				HandleExceptionOccurred(
+									ExceptionOccurredEvent* event);
+
+			void				HandleThreadAction(uint32 action);
+
+			void				HandleThreadStateChanged();
+			void				HandleCpuStateChanged();
+			void				HandleStackTraceChanged();
+
+private:
+			bool				_HandleThreadStopped(CpuState* cpuState);
+
+			void				_SetThreadState(uint32 state,
+									CpuState* cpuState);
+
+private:
+			TeamDebugModel*		fDebugModel;
+			Thread*				fThread;
+			Worker*				fWorker;
+			DebuggerInterface*	fDebuggerInterface;
+};
+
+
+struct ThreadHandlerHashDefinition {
+	typedef thread_id		KeyType;
+	typedef	ThreadHandler	ValueType;
+
+	size_t HashKey(thread_id key) const
+	{
+		return (size_t)key;
+	}
+
+	size_t Hash(const ThreadHandler* value) const
+	{
+		return HashKey(value->ThreadID());
+	}
+
+	bool Compare(thread_id key, ThreadHandler* value) const
+	{
+		return value->ThreadID() == key;
+	}
+
+	HashTableLink<ThreadHandler>* GetLink(ThreadHandler* value) const
+	{
+		return value;
+	}
+};
+
+typedef OpenHashTable<ThreadHandlerHashDefinition> ThreadHandlerTable;
+
+
+#endif	// THREAD_HANDLER_H




More information about the Haiku-commits mailing list