* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ThreadModelLoader.h"
#include <stdio.h>
#include <new>
#include <AutoLocker.h>
#include <DebugEventStream.h>
#include "ThreadModel.h"
static int
compare_by_type_and_name(const Model::ThreadWaitObject* a,
const Model::ThreadWaitObject* b)
{
if (a->Type() != b->Type())
return a->Type() < b->Type() ? -1 : 1;
return strcmp(a->Name(), b->Name());
}
ThreadModelLoader::ThreadModelLoader(Model* model, Model::Thread* thread,
const BMessenger& target, void* targetCookie)
:
AbstractModelLoader(target, targetCookie),
fModel(model),
fThread(thread),
fThreadModel(NULL)
{
}
ThreadModelLoader::~ThreadModelLoader()
{
delete fThreadModel;
}
ThreadModel*
ThreadModelLoader::DetachModel()
{
AutoLocker<BLocker> locker(fLock);
if (fThreadModel == NULL || fLoading)
return NULL;
ThreadModel* model = fThreadModel;
fThreadModel = NULL;
return model;
}
status_t
ThreadModelLoader::PrepareForLoading()
{
return B_OK;
}
status_t
ThreadModelLoader::Load()
{
try {
return _Load();
} catch(...) {
return B_ERROR;
}
}
void
ThreadModelLoader::FinishLoading(bool success)
{
if (!success) {
delete fThreadModel;
fThreadModel = NULL;
}
}
status_t
ThreadModelLoader::_Load()
{
fThreadModel = new(std::nothrow) ThreadModel(fModel, fThread);
if (fThreadModel == NULL)
return B_NO_MEMORY;
BObjectList<Model::ThreadWaitObject> waitObjects;
int32 groupCount = fThread->CountThreadWaitObjectGroups();
for (int32 i = 0; i < groupCount; i++) {
Model::ThreadWaitObjectGroup* group
= fThread->ThreadWaitObjectGroupAt(i);
if (!group->GetThreadWaitObjects(waitObjects))
return B_NO_MEMORY;
}
waitObjects.SortItems(&compare_by_type_and_name);
int32 waitObjectCount = waitObjects.CountItems();
printf("%" B_PRId32 " wait objects\n", waitObjectCount);
for (int32 i = 0; i < waitObjectCount;) {
printf("new wait object group at %" B_PRId32 "\n", i);
Model::ThreadWaitObject* firstObject = waitObjects.ItemAt(i);
int32 k = i + 1;
for (; k < waitObjectCount; k++) {
if (compare_by_type_and_name(firstObject, waitObjects.ItemAt(k))
!= 0) {
break;
}
}
if (fThreadModel->AddWaitObjectGroup(waitObjects, i, k) == NULL)
return B_NO_MEMORY;
i = k;
}
thread_id threadID = fThread->ID();
bool done = false;
uint32 count = 0;
system_profiler_event_header** events = fModel->Events();
size_t eventCount = fModel->CountEvents();
for (size_t i = 0; i < eventCount; i++) {
system_profiler_event_header* header = events[i];
void* buffer = header + 1;
bool keepEvent = false;
switch (header->event) {
case B_SYSTEM_PROFILER_THREAD_REMOVED:
{
system_profiler_thread_removed* event
= (system_profiler_thread_removed*)buffer;
if (event->thread == threadID)
done = true;
break;
}
case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
{
system_profiler_thread_scheduled* event
= (system_profiler_thread_scheduled*)buffer;
keepEvent = event->thread == threadID
|| event->previous_thread == threadID ;
break;
}
case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE:
{
thread_enqueued_in_run_queue* event
= (thread_enqueued_in_run_queue*)buffer;
keepEvent = event->thread == threadID;
break;
}
case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE:
{
thread_removed_from_run_queue* event
= (thread_removed_from_run_queue*)buffer;
keepEvent = event->thread == threadID;
break;
}
default:
break;
}
if (keepEvent)
fThreadModel->AddSchedulingEvent(header);
if (++count % 32 == 0) {
AutoLocker<BLocker> locker(fLock);
if (fAborted)
return B_ERROR;
}
}
return B_OK;
}