Author: bonefish Date: 2009-10-15 06:40:33 +0200 (Thu, 15 Oct 2009) New Revision: 33591 Changeset: http://dev.haiku-os.org/changeset/33591/haiku Modified: haiku/trunk/src/apps/debugger/ThreadHandler.cpp haiku/trunk/src/apps/debugger/ThreadHandler.h haiku/trunk/src/apps/debugger/gui/team_window/ThreadListView.cpp haiku/trunk/src/apps/debugger/gui/team_window/ThreadListView.h haiku/trunk/src/apps/debugger/model/Thread.cpp haiku/trunk/src/apps/debugger/model/Thread.h Log: * Added a stopped reason and additional info to Thread. ThreadHandler sets both accordingly. * The threads view shows the thread states now. Also added tool tips with additional info. Modified: haiku/trunk/src/apps/debugger/ThreadHandler.cpp =================================================================== --- haiku/trunk/src/apps/debugger/ThreadHandler.cpp 2009-10-15 04:40:04 UTC (rev 33590) +++ haiku/trunk/src/apps/debugger/ThreadHandler.cpp 2009-10-15 04:40:33 UTC (rev 33591) @@ -93,14 +93,16 @@ bool ThreadHandler::HandleThreadDebugged(ThreadDebuggedEvent* event) { - return _HandleThreadStopped(NULL); + return _HandleThreadStopped(NULL, THREAD_STOPPED_DEBUGGED); } bool ThreadHandler::HandleDebuggerCall(DebuggerCallEvent* event) { - return _HandleThreadStopped(NULL); + BString message; + fDebuggerInterface->ReadMemoryString(event->Message(), 1024, message); + return _HandleThreadStopped(NULL, THREAD_STOPPED_DEBUGGER_CALL, message); } @@ -155,14 +157,15 @@ } } - return _HandleThreadStopped(cpuState); + return _HandleThreadStopped(cpuState, THREAD_STOPPED_BREAKPOINT); } bool ThreadHandler::HandleWatchpointHit(WatchpointHitEvent* event) { - return _HandleThreadStopped(event->GetCpuState()); + return _HandleThreadStopped(event->GetCpuState(), + THREAD_STOPPED_WATCHPOINT); } @@ -175,14 +178,17 @@ return true; } - return _HandleThreadStopped(event->GetCpuState()); + return _HandleThreadStopped(event->GetCpuState(), + THREAD_STOPPED_SINGLE_STEP); } bool ThreadHandler::HandleExceptionOccurred(ExceptionOccurredEvent* event) { - return _HandleThreadStopped(NULL); + char buffer[256]; + get_debug_exception_string(event->Exception(), buffer, sizeof(buffer)); + return _HandleThreadStopped(NULL, THREAD_STOPPED_EXCEPTION, buffer); } @@ -209,8 +215,10 @@ // 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); + if (action != MSG_THREAD_STOP) { + _SetThreadState(THREAD_STATE_RUNNING, NULL, THREAD_STOPPED_UNKNOWN, + BString()); + } locker.Unlock(); @@ -372,22 +380,25 @@ bool -ThreadHandler::_HandleThreadStopped(CpuState* cpuState) +ThreadHandler::_HandleThreadStopped(CpuState* cpuState, uint32 stoppedReason, + const BString& stoppedReasonInfo) { _ClearContinuationState(); AutoLocker<Team> locker(fThread->GetTeam()); - _SetThreadState(THREAD_STATE_STOPPED, cpuState); + _SetThreadState(THREAD_STATE_STOPPED, cpuState, stoppedReason, + stoppedReasonInfo); return true; } void -ThreadHandler::_SetThreadState(uint32 state, CpuState* cpuState) +ThreadHandler::_SetThreadState(uint32 state, CpuState* cpuState, + uint32 stoppedReason, const BString& stoppedReasonInfo) { - fThread->SetState(state); + fThread->SetState(state, stoppedReason, stoppedReasonInfo); fThread->SetCpuState(cpuState); } Modified: haiku/trunk/src/apps/debugger/ThreadHandler.h =================================================================== --- haiku/trunk/src/apps/debugger/ThreadHandler.h 2009-10-15 04:40:04 UTC (rev 33590) +++ haiku/trunk/src/apps/debugger/ThreadHandler.h 2009-10-15 04:40:33 UTC (rev 33591) @@ -64,10 +64,14 @@ virtual status_t GetImageDebugInfo(Image* image, ImageDebugInfo*& _info); - bool _HandleThreadStopped(CpuState* cpuState); + bool _HandleThreadStopped(CpuState* cpuState, + uint32 stoppedReason, + const BString& stoppedReasonInfo + = BString()); void _SetThreadState(uint32 state, - CpuState* cpuState); + CpuState* cpuState, uint32 stoppedReason, + const BString& stoppedReasonInfo); Statement* _GetStatementAtInstructionPointer( StackFrame* frame); Modified: haiku/trunk/src/apps/debugger/gui/team_window/ThreadListView.cpp =================================================================== --- haiku/trunk/src/apps/debugger/gui/team_window/ThreadListView.cpp 2009-10-15 04:40:04 UTC (rev 33590) +++ haiku/trunk/src/apps/debugger/gui/team_window/ThreadListView.cpp 2009-10-15 04:40:33 UTC (rev 33591) @@ -6,8 +6,6 @@ #include "ThreadListView.h" -#include <stdio.h> - #include <new> #include <Looper.h> @@ -15,6 +13,7 @@ #include <AutoLocker.h> #include <ObjectList.h> +#include <ToolTip.h> #include "table/TableColumns.h" @@ -27,22 +26,23 @@ // #pragma mark - ThreadsTableModel -class ThreadListView::ThreadsTableModel : public TableModel { +class ThreadListView::ThreadsTableModel : public TableModel, + public TableToolTipProvider { public: ThreadsTableModel(Team* team) : fTeam(team) { - Update(); + Update(-1); } ~ThreadsTableModel() { fTeam = NULL; - Update(); + Update(-1); } - bool Update() + bool Update(thread_id threadID) { if (fTeam == NULL) { for (int32 i = 0; Thread* thread = fThreads.ItemAt(i); i++) @@ -61,6 +61,8 @@ // remove no longer existing threads while (Thread* oldThread = fThreads.ItemAt(index)) { if (oldThread == newThread) { + if (threadID >= 0 && oldThread->ID() == threadID) + NotifyRowsChanged(index, 1); index++; newThread = it.Next(); } else { @@ -90,7 +92,7 @@ virtual int32 CountColumns() const { - return 2; + return 3; } virtual int32 CountRows() const @@ -109,6 +111,38 @@ value.SetTo(thread->ID()); return true; case 1: + { + switch (thread->State()) { + case THREAD_STATE_RUNNING: + value.SetTo("Running", B_VARIANT_DONT_COPY_DATA); + return true; + case THREAD_STATE_STOPPED: + break; + case THREAD_STATE_UNKNOWN: + default: + value.SetTo("?", B_VARIANT_DONT_COPY_DATA); + return true; + } + + // thread is stopped -- get the reason + switch (thread->StoppedReason()) { + case THREAD_STOPPED_DEBUGGER_CALL: + value.SetTo("Call", B_VARIANT_DONT_COPY_DATA); + return true; + case THREAD_STOPPED_EXCEPTION: + value.SetTo("Exception", B_VARIANT_DONT_COPY_DATA); + return true; + case THREAD_STOPPED_BREAKPOINT: + case THREAD_STOPPED_WATCHPOINT: + case THREAD_STOPPED_SINGLE_STEP: + case THREAD_STOPPED_DEBUGGED: + case THREAD_STOPPED_UNKNOWN: + default: + value.SetTo("Debugged", B_VARIANT_DONT_COPY_DATA); + return true; + } + } + case 2: value.SetTo(thread->Name(), B_VARIANT_DONT_COPY_DATA); return true; default: @@ -116,6 +150,57 @@ } } + virtual bool GetToolTipForTableCell(int32 rowIndex, int32 columnIndex, + BToolTip** _tip) + { + Thread* thread = fThreads.ItemAt(rowIndex); + if (thread == NULL) + return false; + + BString text; + text << "Thread: \"" << thread->Name() << "\" (" << thread->ID() + << ")\n"; + + switch (thread->State()) { + case THREAD_STATE_RUNNING: + text << "Running"; + break; + case THREAD_STATE_STOPPED: + { + switch (thread->StoppedReason()) { + case THREAD_STOPPED_DEBUGGER_CALL: + text << "Called debugger(): " + << thread->StoppedReasonInfo(); + break; + case THREAD_STOPPED_EXCEPTION: + text << "Caused exception: " + << thread->StoppedReasonInfo(); + break; + case THREAD_STOPPED_BREAKPOINT: + case THREAD_STOPPED_WATCHPOINT: + case THREAD_STOPPED_SINGLE_STEP: + case THREAD_STOPPED_DEBUGGED: + case THREAD_STOPPED_UNKNOWN: + default: + text << "Stopped for debugging"; + break; + } + break; + } + case THREAD_STATE_UNKNOWN: + default: + text << "Current State Unknown"; + break; + } + + BTextToolTip* tip = new(std::nothrow) BTextToolTip(text); + if (tip == NULL) + return false; + + *_tip = tip; + return true; + } + Thread* ThreadAt(int32 index) const { return fThreads.ItemAt(index); @@ -206,9 +291,14 @@ { switch (message->what) { case MSG_SYNC_THREAD_LIST: - if (fThreadsTableModel != NULL) - fThreadsTableModel->Update(); + { + thread_id threadID; + if (message->FindInt32("thread", &threadID) != B_OK) + threadID = -1; + + fThreadsTableModel->Update(threadID); break; + } default: BGroupView::MessageReceived(message); break; @@ -231,16 +321,24 @@ void +ThreadListView::ThreadStateChanged(const Team::ThreadEvent& event) +{ + BMessage message(MSG_SYNC_THREAD_LIST); + message.AddInt32("thread", event.GetThread()->ID()); + + Looper()->PostMessage(&message, this); +} + + +void ThreadListView::TableSelectionChanged(Table* table) { if (fListener == NULL) return; Thread* thread = NULL; - if (fThreadsTableModel != NULL) { - TableSelectionModel* selectionModel = table->SelectionModel(); - thread = fThreadsTableModel->ThreadAt(selectionModel->RowAt(0)); - } + TableSelectionModel* selectionModel = table->SelectionModel(); + thread = fThreadsTableModel->ThreadAt(selectionModel->RowAt(0)); fListener->ThreadSelectionChanged(thread); } @@ -253,17 +351,19 @@ AddChild(fThreadsTable->ToView()); // columns - fThreadsTable->AddColumn(new Int32TableColumn(0, "ID", 40, 20, 1000, + fThreadsTable->AddColumn(new Int32TableColumn(0, "ID", 60, 20, 1000, B_TRUNCATE_MIDDLE, B_ALIGN_RIGHT)); - fThreadsTable->AddColumn(new StringTableColumn(1, "Name", 80, 40, 1000, + fThreadsTable->AddColumn(new StringTableColumn(1, "State", 80, 40, 1000, B_TRUNCATE_END, B_ALIGN_LEFT)); + fThreadsTable->AddColumn(new StringTableColumn(2, "Name", 200, 40, 1000, + B_TRUNCATE_END, B_ALIGN_LEFT)); fThreadsTable->SetSelectionMode(B_SINGLE_SELECTION_LIST); fThreadsTable->AddTableListener(this); - fThreadsTableModel = new(std::nothrow) ThreadsTableModel(fTeam); + fThreadsTableModel = new ThreadsTableModel(fTeam); fThreadsTable->SetTableModel(fThreadsTableModel); - fThreadsTable->ResizeAllColumnsToPreferred(); + fThreadsTable->SetToolTipProvider(fThreadsTableModel); fTeam->AddListener(this); } Modified: haiku/trunk/src/apps/debugger/gui/team_window/ThreadListView.h =================================================================== --- haiku/trunk/src/apps/debugger/gui/team_window/ThreadListView.h 2009-10-15 04:40:04 UTC (rev 33590) +++ haiku/trunk/src/apps/debugger/gui/team_window/ThreadListView.h 2009-10-15 04:40:33 UTC (rev 33591) @@ -40,6 +40,8 @@ // Team::Listener virtual void ThreadAdded(const Team::ThreadEvent& event); virtual void ThreadRemoved(const Team::ThreadEvent& event); + virtual void ThreadStateChanged( + const Team::ThreadEvent& event); // TableListener virtual void TableSelectionChanged(Table* table); Modified: haiku/trunk/src/apps/debugger/model/Thread.cpp =================================================================== --- haiku/trunk/src/apps/debugger/model/Thread.cpp 2009-10-15 04:40:04 UTC (rev 33590) +++ haiku/trunk/src/apps/debugger/model/Thread.cpp 2009-10-15 04:40:33 UTC (rev 33591) @@ -5,6 +5,8 @@ #include "Thread.h" +#include <stdio.h> + #include "CpuState.h" #include "StackTrace.h" #include "Team.h" @@ -15,6 +17,7 @@ fTeam(team), fID(threadID), fState(THREAD_STATE_UNKNOWN), + fStoppedReason(THREAD_STOPPED_UNKNOWN), fCpuState(NULL), fStackTrace(NULL) { @@ -52,12 +55,14 @@ void -Thread::SetState(uint32 state) +Thread::SetState(uint32 state, uint32 reason, const BString& info) { if (state == fState) return; fState = state; + fStoppedReason = reason; + fStoppedReasonInfo = info; // unset CPU state and stack trace, if the thread isn't stopped if (fState != THREAD_STATE_STOPPED) { Modified: haiku/trunk/src/apps/debugger/model/Thread.h =================================================================== --- haiku/trunk/src/apps/debugger/model/Thread.h 2009-10-15 04:40:04 UTC (rev 33590) +++ haiku/trunk/src/apps/debugger/model/Thread.h 2009-10-15 04:40:33 UTC (rev 33591) @@ -17,13 +17,25 @@ class Team; +// general thread state enum { THREAD_STATE_UNKNOWN, THREAD_STATE_RUNNING, THREAD_STATE_STOPPED }; +// reason why stopped +enum { + THREAD_STOPPED_UNKNOWN, + THREAD_STOPPED_DEBUGGED, + THREAD_STOPPED_DEBUGGER_CALL, + THREAD_STOPPED_BREAKPOINT, + THREAD_STOPPED_WATCHPOINT, + THREAD_STOPPED_SINGLE_STEP, + THREAD_STOPPED_EXCEPTION +}; + class Thread : public Referenceable, public DoublyLinkedListLinkImpl<Thread> { public: Thread(Team* team, thread_id threadID); @@ -40,8 +52,15 @@ void SetName(const BString& name); uint32 State() const { return fState; } - void SetState(uint32 state); + void SetState(uint32 state, + uint32 reason = THREAD_STOPPED_UNKNOWN, + const BString& info = BString()); + uint32 StoppedReason() const + { return fStoppedReason; } + const BString& StoppedReasonInfo() const + { return fStoppedReasonInfo; } + CpuState* GetCpuState() const { return fCpuState; } void SetCpuState(CpuState* state); @@ -53,6 +72,8 @@ thread_id fID; BString fName; uint32 fState; + uint32 fStoppedReason; + BString fStoppedReasonInfo; CpuState* fCpuState; StackTrace* fStackTrace; };