* Although it takes a bit of memory, the Model also stores an array with

pointers to all events now. This allows for backward iteration.
* Model::ThreadWaitObjectGroup: Added a few convenience getters.
* Added functions thread_state_name() and wait_object_type_name() to translate
  a ThreadState respectively a wait object type into a readable string.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34588 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-12-09 15:26:42 +00:00
parent f3156fffd0
commit 6d5e661da4
4 changed files with 228 additions and 15 deletions
+92 -1
View File
@@ -13,6 +13,50 @@
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include <thread_defs.h>
static const char* const kThreadStateNames[] = {
"running",
"still running",
"preempted",
"ready",
"waiting",
"unknown"
};
const char*
thread_state_name(ThreadState state)
{
return kThreadStateNames[state];
}
const char*
wait_object_type_name(uint32 type)
{
switch (type) {
case THREAD_BLOCK_TYPE_SEMAPHORE:
return "semaphore";
case THREAD_BLOCK_TYPE_CONDITION_VARIABLE:
return "condition";
case THREAD_BLOCK_TYPE_MUTEX:
return "mutex";
case THREAD_BLOCK_TYPE_RW_LOCK:
return "rw lock";
case THREAD_BLOCK_TYPE_OTHER:
return "other";
case THREAD_BLOCK_TYPE_SNOOZE:
return "snooze";
case THREAD_BLOCK_TYPE_SIGNAL:
return "signal";
default:
return "unknown";
}
}
// #pragma mark - CPU // #pragma mark - CPU
@@ -457,11 +501,14 @@ Model::CompactSchedulingState::Delete()
// #pragma mark - Model // #pragma mark - Model
Model::Model(const char* dataSourceName, void* eventData, size_t eventDataSize) Model::Model(const char* dataSourceName, void* eventData, size_t eventDataSize,
system_profiler_event_header** events, size_t eventCount)
: :
fDataSourceName(dataSourceName), fDataSourceName(dataSourceName),
fEventData(eventData), fEventData(eventData),
fEvents(events),
fEventDataSize(eventDataSize), fEventDataSize(eventDataSize),
fEventCount(eventCount),
fCPUCount(1), fCPUCount(1),
fBaseTime(0), fBaseTime(0),
fLastEventTime(0), fLastEventTime(0),
@@ -486,6 +533,50 @@ Model::~Model()
} }
size_t
Model::ClosestEventIndex(nanotime_t eventTime) const
{
// The events themselves are unmodified and use an absolute time.
eventTime += fBaseTime;
// Binary search the event. Since not all events have a timestamp, we have
// to do a bit of iteration, too.
size_t lower = 0;
size_t upper = CountEvents();
while (lower < upper) {
size_t mid = (lower + upper) / 2;
while (mid < upper) {
system_profiler_event_header* header = fEvents[mid];
switch (header->event) {
case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE:
case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE:
break;
default:
mid++;
continue;
}
break;
}
if (mid == upper) {
lower = mid;
break;
}
system_profiler_thread_scheduling_event* event
= (system_profiler_thread_scheduling_event*)(fEvents[mid] + 1);
if (event->time < eventTime)
lower = mid + 1;
else
upper = mid;
}
return lower;
}
void void
Model::LoadingFinished() Model::LoadingFinished()
{ {
+55 -2
View File
@@ -28,6 +28,9 @@ enum ThreadState {
UNKNOWN UNKNOWN
}; };
const char* thread_state_name(ThreadState state);
const char* wait_object_type_name(uint32 type);
class Model : public Referenceable { class Model : public Referenceable {
public: public:
@@ -50,12 +53,20 @@ public:
public: public:
Model(const char* dataSourceName, Model(const char* dataSourceName,
void* eventData, size_t eventDataSize); void* eventData, size_t eventDataSize,
system_profiler_event_header** events,
size_t eventCount);
~Model(); ~Model();
inline const char* DataSourceName() const; inline const char* DataSourceName() const;
inline void* EventData() const; inline void* EventData() const;
inline size_t EventDataSize() const; inline size_t EventDataSize() const;
inline system_profiler_event_header** Events() const;
inline size_t CountEvents() const;
size_t ClosestEventIndex(nanotime_t eventTime) const;
// finds the greatest event with event
// time >= eventTime; may return
// CountEvents()
void LoadingFinished(); void LoadingFinished();
@@ -119,13 +130,16 @@ private:
typedef BObjectList<CompactSchedulingState> SchedulingStateList; typedef BObjectList<CompactSchedulingState> SchedulingStateList;
private: private:
static int _CompareEventTimeSchedulingState(const nanotime_t* time, static int _CompareEventTimeSchedulingState(
const nanotime_t* time,
const CompactSchedulingState* state); const CompactSchedulingState* state);
private: private:
BString fDataSourceName; BString fDataSourceName;
void* fEventData; void* fEventData;
system_profiler_event_header** fEvents;
size_t fEventDataSize; size_t fEventDataSize;
size_t fEventCount;
int32 fCPUCount; int32 fCPUCount;
nanotime_t fBaseTime; nanotime_t fBaseTime;
nanotime_t fLastEventTime; nanotime_t fLastEventTime;
@@ -262,6 +276,10 @@ public:
ThreadWaitObject* threadWaitObject); ThreadWaitObject* threadWaitObject);
~ThreadWaitObjectGroup(); ~ThreadWaitObjectGroup();
inline uint32 Type() const;
inline addr_t Object() const;
inline const char* Name() const;
inline ThreadWaitObject* MostRecentThreadWaitObject() const; inline ThreadWaitObject* MostRecentThreadWaitObject() const;
inline WaitObject* MostRecentWaitObject() const; inline WaitObject* MostRecentWaitObject() const;
@@ -529,6 +547,20 @@ Model::EventDataSize() const
} }
system_profiler_event_header**
Model::Events() const
{
return fEvents;
}
size_t
Model::CountEvents() const
{
return fEventCount;
}
nanotime_t nanotime_t
Model::BaseTime() const Model::BaseTime() const
{ {
@@ -769,6 +801,27 @@ Model::ThreadWaitObject::TotalWaitTime() const
// #pragma mark - ThreadWaitObjectGroup // #pragma mark - ThreadWaitObjectGroup
uint32
Model::ThreadWaitObjectGroup::Type() const
{
return MostRecentThreadWaitObject()->Type();
}
addr_t
Model::ThreadWaitObjectGroup::Object() const
{
return MostRecentThreadWaitObject()->Object();
}
const char*
Model::ThreadWaitObjectGroup::Name() const
{
return MostRecentThreadWaitObject()->Name();
}
Model::ThreadWaitObject* Model::ThreadWaitObject*
Model::ThreadWaitObjectGroup::MostRecentThreadWaitObject() const Model::ThreadWaitObjectGroup::MostRecentThreadWaitObject() const
{ {
@@ -160,6 +160,16 @@ ModelLoader::_Load()
status_t error = _ReadDebugEvents(&eventData, &eventDataSize); status_t error = _ReadDebugEvents(&eventData, &eventDataSize);
if (error != B_OK) if (error != B_OK)
return error; return error;
MemoryDeleter eventDataDeleter(eventData);
// create a debug event array
system_profiler_event_header** events;
size_t eventCount;
error = _CreateDebugEventArray(eventData, eventDataSize, events,
eventCount);
if (error != B_OK)
return error;
ArrayDeleter<system_profiler_event_header*> eventsDeleter(events);
// get the data source name // get the data source name
BString dataSourceName; BString dataSourceName;
@@ -167,19 +177,15 @@ ModelLoader::_Load()
// create a model // create a model
fModel = new(std::nothrow) Model(dataSourceName.String(), eventData, fModel = new(std::nothrow) Model(dataSourceName.String(), eventData,
eventDataSize); eventDataSize, events, eventCount);
if (fModel == NULL) { if (fModel == NULL)
free(eventData);
return B_NO_MEMORY; return B_NO_MEMORY;
} eventDataDeleter.Detach();
eventsDeleter.Detach();
// create a debug input stream // create a debug input stream
BDebugEventInputStream* input = new(std::nothrow) BDebugEventInputStream; BDebugEventInputStream input;
if (input == NULL) error = input.SetTo(eventData, eventDataSize, false);
return B_NO_MEMORY;
ObjectDeleter<BDebugEventInputStream> inputDeleter(input);
error = input->SetTo(eventData, eventDataSize, false);
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -201,7 +207,7 @@ ModelLoader::_Load()
uint32 cpu; uint32 cpu;
const void* buffer; const void* buffer;
off_t offset; off_t offset;
ssize_t bufferSize = input->ReadNextEvent(&event, &cpu, &buffer, ssize_t bufferSize = input.ReadNextEvent(&event, &cpu, &buffer,
&offset); &offset);
if (bufferSize < 0) if (bufferSize < 0)
return bufferSize; return bufferSize;
@@ -320,6 +326,65 @@ ModelLoader::_ReadDebugEvents(void** _eventData, size_t* _size)
} }
status_t
ModelLoader::_CreateDebugEventArray(void* eventData, size_t eventDataSize,
system_profiler_event_header**& _events, size_t& _eventCount)
{
// count the events
BDebugEventInputStream input;
status_t error = input.SetTo(eventData, eventDataSize, false);
if (error != B_OK)
return error;
size_t eventCount = 0;
while (true) {
// get next event
uint32 event;
uint32 cpu;
const void* buffer;
ssize_t bufferSize = input.ReadNextEvent(&event, &cpu, &buffer, NULL);
if (bufferSize < 0)
return bufferSize;
if (buffer == NULL)
break;
eventCount++;
}
// create the array
system_profiler_event_header** events = new(std::nothrow)
system_profiler_event_header*[eventCount];
if (events == NULL)
return B_NO_MEMORY;
// populate the array
error = input.SetTo(eventData, eventDataSize, false);
if (error != B_OK) {
delete[] events;
return error;
}
size_t eventIndex = 0;
while (true) {
// get next event
uint32 event;
uint32 cpu;
const void* buffer;
off_t offset;
input.ReadNextEvent(&event, &cpu, &buffer, &offset);
if (buffer == NULL)
break;
events[eventIndex++]
= (system_profiler_event_header*)((uint8*)eventData + offset);
}
_events = events;
_eventCount = eventCount;
return B_OK;
}
status_t status_t
ModelLoader::_ProcessEvent(uint32 event, uint32 cpu, const void* buffer, ModelLoader::_ProcessEvent(uint32 event, uint32 cpu, const void* buffer,
size_t size) size_t size)
@@ -46,6 +46,10 @@ private:
status_t _Load(); status_t _Load();
status_t _ReadDebugEvents(void** _eventData, status_t _ReadDebugEvents(void** _eventData,
size_t* _size); size_t* _size);
status_t _CreateDebugEventArray(void* eventData,
size_t eventDataSize,
system_profiler_event_header**& _events,
size_t& _eventCount);
status_t _ProcessEvent(uint32 event, uint32 cpu, status_t _ProcessEvent(uint32 event, uint32 cpu,
const void* buffer, size_t size); const void* buffer, size_t size);