* 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. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33591 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -93,14 +93,16 @@ ThreadHandler::SetBreakpointAndRun(target_addr_t address)
|
||||
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 @@ ThreadHandler::HandleBreakpointHit(BreakpointHitEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ ThreadHandler::HandleSingleStep(SingleStepEvent* event)
|
||||
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 @@ ThreadHandler::HandleThreadAction(uint32 action)
|
||||
|
||||
// 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 @@ ThreadHandler::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info)
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,10 +64,14 @@ private:
|
||||
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);
|
||||
|
||||
@@ -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 @@ enum {
|
||||
// #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 @@ public:
|
||||
// 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 @@ public:
|
||||
|
||||
virtual int32 CountColumns() const
|
||||
{
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
virtual int32 CountRows() const
|
||||
@@ -109,6 +111,38 @@ public:
|
||||
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 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ ThreadListView::MessageReceived(BMessage* message)
|
||||
{
|
||||
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;
|
||||
@@ -230,6 +320,16 @@ ThreadListView::ThreadRemoved(const Team::ThreadEvent& event)
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -237,10 +337,8 @@ ThreadListView::TableSelectionChanged(Table* table)
|
||||
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 @@ ThreadListView::_Init()
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ private:
|
||||
// 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);
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "CpuState.h"
|
||||
#include "StackTrace.h"
|
||||
#include "Team.h"
|
||||
@@ -15,6 +17,7 @@ Thread::Thread(Team* team, thread_id threadID)
|
||||
fTeam(team),
|
||||
fID(threadID),
|
||||
fState(THREAD_STATE_UNKNOWN),
|
||||
fStoppedReason(THREAD_STOPPED_UNKNOWN),
|
||||
fCpuState(NULL),
|
||||
fStackTrace(NULL)
|
||||
{
|
||||
@@ -52,12 +55,14 @@ Thread::SetName(const BString& name)
|
||||
|
||||
|
||||
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) {
|
||||
|
||||
@@ -17,12 +17,24 @@ class StackTrace;
|
||||
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:
|
||||
@@ -40,7 +52,14 @@ public:
|
||||
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 @@ private:
|
||||
thread_id fID;
|
||||
BString fName;
|
||||
uint32 fState;
|
||||
uint32 fStoppedReason;
|
||||
BString fStoppedReasonInfo;
|
||||
CpuState* fCpuState;
|
||||
StackTrace* fStackTrace;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user