13dc9bfd1SIngo Weinhold/*
23dc9bfd1SIngo Weinhold * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
33dc9bfd1SIngo Weinhold * Distributed under the terms of the MIT License.
43dc9bfd1SIngo Weinhold */
53dc9bfd1SIngo Weinhold
64e890d34SAxel Dörfler
74f1804a1SIngo Weinhold#include "Model.h"
83dc9bfd1SIngo Weinhold
908e34e27SIngo Weinhold#include <new>
103dc9bfd1SIngo Weinhold
1108e34e27SIngo Weinhold#include <stdio.h>
1208e34e27SIngo Weinhold#include <stdlib.h>
1308e34e27SIngo Weinhold
1408e34e27SIngo Weinhold#include <AutoDeleter.h>
1508e34e27SIngo Weinhold
166d5e661dSIngo Weinhold#include <thread_defs.h>
176d5e661dSIngo Weinhold
186d5e661dSIngo Weinhold
196d5e661dSIngo Weinhold
206d5e661dSIngo Weinholdstatic const char* const kThreadStateNames[] = {
216d5e661dSIngo Weinhold	"running",
226d5e661dSIngo Weinhold	"still running",
236d5e661dSIngo Weinhold	"preempted",
246d5e661dSIngo Weinhold	"ready",
256d5e661dSIngo Weinhold	"waiting",
266d5e661dSIngo Weinhold	"unknown"
276d5e661dSIngo Weinhold};
286d5e661dSIngo Weinhold
296d5e661dSIngo Weinhold
306d5e661dSIngo Weinholdconst char*
316d5e661dSIngo Weinholdthread_state_name(ThreadState state)
326d5e661dSIngo Weinhold{
336d5e661dSIngo Weinhold	return kThreadStateNames[state];
346d5e661dSIngo Weinhold}
356d5e661dSIngo Weinhold
366d5e661dSIngo Weinhold
376d5e661dSIngo Weinholdconst char*
386d5e661dSIngo Weinholdwait_object_type_name(uint32 type)
396d5e661dSIngo Weinhold{
406d5e661dSIngo Weinhold	switch (type) {
416d5e661dSIngo Weinhold		case THREAD_BLOCK_TYPE_SEMAPHORE:
426d5e661dSIngo Weinhold			return "semaphore";
436d5e661dSIngo Weinhold		case THREAD_BLOCK_TYPE_CONDITION_VARIABLE:
446d5e661dSIngo Weinhold			return "condition";
456d5e661dSIngo Weinhold		case THREAD_BLOCK_TYPE_MUTEX:
466d5e661dSIngo Weinhold			return "mutex";
476d5e661dSIngo Weinhold		case THREAD_BLOCK_TYPE_RW_LOCK:
486d5e661dSIngo Weinhold			return "rw lock";
492c588b03SAugustin Cavalier		case THREAD_BLOCK_TYPE_USER:
502c588b03SAugustin Cavalier			return "user";
516d5e661dSIngo Weinhold		case THREAD_BLOCK_TYPE_OTHER:
526d5e661dSIngo Weinhold			return "other";
536d5e661dSIngo Weinhold		case THREAD_BLOCK_TYPE_SNOOZE:
546d5e661dSIngo Weinhold			return "snooze";
556d5e661dSIngo Weinhold		case THREAD_BLOCK_TYPE_SIGNAL:
566d5e661dSIngo Weinhold			return "signal";
576d5e661dSIngo Weinhold		default:
586d5e661dSIngo Weinhold			return "unknown";
596d5e661dSIngo Weinhold	}
606d5e661dSIngo Weinhold}
616d5e661dSIngo Weinhold
6208e34e27SIngo Weinhold
63bea40bcdSIngo Weinhold// #pragma mark - CPU
64bea40bcdSIngo Weinhold
65bea40bcdSIngo Weinhold
66bea40bcdSIngo WeinholdModel::CPU::CPU()
67bea40bcdSIngo Weinhold	:
68bea40bcdSIngo Weinhold	fIdleTime(0)
69bea40bcdSIngo Weinhold{
70bea40bcdSIngo Weinhold}
71bea40bcdSIngo Weinhold
72bea40bcdSIngo Weinhold
73bea40bcdSIngo Weinholdvoid
74bea40bcdSIngo WeinholdModel::CPU::SetIdleTime(nanotime_t time)
75bea40bcdSIngo Weinhold{
76bea40bcdSIngo Weinhold	fIdleTime = time;
77bea40bcdSIngo Weinhold}
78bea40bcdSIngo Weinhold
79bea40bcdSIngo Weinhold
80c2354448SIngo Weinhold// #pragma mark - IORequest
81c2354448SIngo Weinhold
82c2354448SIngo Weinhold
83f0a592fdSIngo WeinholdModel::IORequest::IORequest(
84f0a592fdSIngo Weinhold	system_profiler_io_request_scheduled* scheduledEvent,
85f0a592fdSIngo Weinhold	system_profiler_io_request_finished* finishedEvent, size_t operationCount)
86f0a592fdSIngo Weinhold	:
87f0a592fdSIngo Weinhold	scheduledEvent(scheduledEvent),
88f0a592fdSIngo Weinhold	finishedEvent(finishedEvent),
89f0a592fdSIngo Weinhold	operationCount(operationCount)
90f0a592fdSIngo Weinhold{
91f0a592fdSIngo Weinhold}
92f0a592fdSIngo Weinhold
93f0a592fdSIngo Weinhold
94f0a592fdSIngo WeinholdModel::IORequest::~IORequest()
95f0a592fdSIngo Weinhold{
96f0a592fdSIngo Weinhold}
97f0a592fdSIngo Weinhold
98f0a592fdSIngo Weinhold
99c2354448SIngo Weinhold/*static*/ Model::IORequest*
100c2354448SIngo WeinholdModel::IORequest::Create(system_profiler_io_request_scheduled* scheduledEvent,
101c2354448SIngo Weinhold	system_profiler_io_request_finished* finishedEvent, size_t operationCount)
102c2354448SIngo Weinhold{
103c2354448SIngo Weinhold	void* memory = malloc(
104c2354448SIngo Weinhold		sizeof(IORequest) + operationCount * sizeof(IOOperation));
105c2354448SIngo Weinhold	if (memory == NULL)
106c2354448SIngo Weinhold		return NULL;
107c2354448SIngo Weinhold
108c2354448SIngo Weinhold	return new(memory) IORequest(scheduledEvent, finishedEvent, operationCount);
109c2354448SIngo Weinhold}
110c2354448SIngo Weinhold
111c2354448SIngo Weinhold
112c2354448SIngo Weinholdvoid
113c2354448SIngo WeinholdModel::IORequest::Delete()
114c2354448SIngo Weinhold{
115c2354448SIngo Weinhold	free(this);
116c2354448SIngo Weinhold}
117c2354448SIngo Weinhold
118c2354448SIngo Weinhold
119934a8d01SIngo Weinhold// #pragma mark - IOScheduler
120934a8d01SIngo Weinhold
121934a8d01SIngo Weinhold
122934a8d01SIngo WeinholdModel::IOScheduler::IOScheduler(system_profiler_io_scheduler_added* event,
123934a8d01SIngo Weinhold	int32 index)
124934a8d01SIngo Weinhold	:
125934a8d01SIngo Weinhold	fAddedEvent(event),
126934a8d01SIngo Weinhold	fIndex(index)
127934a8d01SIngo Weinhold{
128934a8d01SIngo Weinhold}
129934a8d01SIngo Weinhold
130934a8d01SIngo Weinhold
1311e336ebaSIngo Weinhold// #pragma mark - WaitObject
1321e336ebaSIngo Weinhold
1331e336ebaSIngo Weinhold
1341e336ebaSIngo WeinholdModel::WaitObject::WaitObject(const system_profiler_wait_object_info* event)
1351e336ebaSIngo Weinhold	:
1364e890d34SAxel Dörfler	fEvent(event),
1374e890d34SAxel Dörfler	fWaits(0),
1384e890d34SAxel Dörfler	fTotalWaitTime(0)
1391e336ebaSIngo Weinhold{
1401e336ebaSIngo Weinhold}
1411e336ebaSIngo Weinhold
1421e336ebaSIngo Weinhold
1431e336ebaSIngo WeinholdModel::WaitObject::~WaitObject()
1441e336ebaSIngo Weinhold{
1451e336ebaSIngo Weinhold}
1461e336ebaSIngo Weinhold
1471e336ebaSIngo Weinhold
1484e890d34SAxel Dörflervoid
149d8d4b902SIngo WeinholdModel::WaitObject::AddWait(nanotime_t waitTime)
1504e890d34SAxel Dörfler{
1514e890d34SAxel Dörfler	fWaits++;
1524e890d34SAxel Dörfler	fTotalWaitTime += waitTime;
1534e890d34SAxel Dörfler}
1544e890d34SAxel Dörfler
1554e890d34SAxel Dörfler
1561e336ebaSIngo Weinhold// #pragma mark - WaitObjectGroup
1571e336ebaSIngo Weinhold
1581e336ebaSIngo Weinhold
1591e336ebaSIngo WeinholdModel::WaitObjectGroup::WaitObjectGroup(WaitObject* waitObject)
1604e890d34SAxel Dörfler	:
1614e890d34SAxel Dörfler	fWaits(-1),
1624e890d34SAxel Dörfler	fTotalWaitTime(-1)
1631e336ebaSIngo Weinhold{
1644e890d34SAxel Dörfler	fWaitObjects.AddItem(waitObject);
1651e336ebaSIngo Weinhold}
1661e336ebaSIngo Weinhold
1671e336ebaSIngo Weinhold
1681e336ebaSIngo WeinholdModel::WaitObjectGroup::~WaitObjectGroup()
1691e336ebaSIngo Weinhold{
1701e336ebaSIngo Weinhold}
1711e336ebaSIngo Weinhold
1721e336ebaSIngo Weinhold
1734e890d34SAxel Dörflerint64
1744e890d34SAxel DörflerModel::WaitObjectGroup::Waits()
1754e890d34SAxel Dörfler{
1764e890d34SAxel Dörfler	if (fWaits < 0)
1774e890d34SAxel Dörfler		_ComputeWaits();
1784e890d34SAxel Dörfler
1794e890d34SAxel Dörfler	return fWaits;
1804e890d34SAxel Dörfler}
1814e890d34SAxel Dörfler
1824e890d34SAxel Dörfler
183d8d4b902SIngo Weinholdnanotime_t
1844e890d34SAxel DörflerModel::WaitObjectGroup::TotalWaitTime()
1854e890d34SAxel Dörfler{
1864e890d34SAxel Dörfler	if (fTotalWaitTime < 0)
1874e890d34SAxel Dörfler		_ComputeWaits();
1884e890d34SAxel Dörfler
1894e890d34SAxel Dörfler	return fTotalWaitTime;
1904e890d34SAxel Dörfler}
1914e890d34SAxel Dörfler
1924e890d34SAxel Dörfler
1934e890d34SAxel Dörflervoid
1944e890d34SAxel DörflerModel::WaitObjectGroup::_ComputeWaits()
1954e890d34SAxel Dörfler{
1964e890d34SAxel Dörfler	fWaits = 0;
1974e890d34SAxel Dörfler	fTotalWaitTime = 0;
1984e890d34SAxel Dörfler
1994e890d34SAxel Dörfler	for (int32 i = fWaitObjects.CountItems(); i-- > 0;) {
2004e890d34SAxel Dörfler		WaitObject* waitObject = fWaitObjects.ItemAt(i);
2014e890d34SAxel Dörfler
2024e890d34SAxel Dörfler		fWaits += waitObject->Waits();
2034e890d34SAxel Dörfler		fTotalWaitTime += waitObject->TotalWaitTime();
2044e890d34SAxel Dörfler	}
2054e890d34SAxel Dörfler}
2064e890d34SAxel Dörfler
2074e890d34SAxel Dörfler
2081e336ebaSIngo Weinhold// #pragma mark - ThreadWaitObject
2091e336ebaSIngo Weinhold
2101e336ebaSIngo Weinhold
2111e336ebaSIngo WeinholdModel::ThreadWaitObject::ThreadWaitObject(WaitObject* waitObject)
2121e336ebaSIngo Weinhold	:
2131e336ebaSIngo Weinhold	fWaitObject(waitObject),
2141e336ebaSIngo Weinhold	fWaits(0),
2151e336ebaSIngo Weinhold	fTotalWaitTime(0)
2161e336ebaSIngo Weinhold{
2171e336ebaSIngo Weinhold}
2181e336ebaSIngo Weinhold
2191e336ebaSIngo Weinhold
2201e336ebaSIngo WeinholdModel::ThreadWaitObject::~ThreadWaitObject()
2211e336ebaSIngo Weinhold{
2221e336ebaSIngo Weinhold}
2231e336ebaSIngo Weinhold
2241e336ebaSIngo Weinhold
2251e336ebaSIngo Weinholdvoid
226d8d4b902SIngo WeinholdModel::ThreadWaitObject::AddWait(nanotime_t waitTime)
2271e336ebaSIngo Weinhold{
2281e336ebaSIngo Weinhold	fWaits++;
2291e336ebaSIngo Weinhold	fTotalWaitTime += waitTime;
2304e890d34SAxel Dörfler
2314e890d34SAxel Dörfler	fWaitObject->AddWait(waitTime);
2321e336ebaSIngo Weinhold}
2331e336ebaSIngo Weinhold
2341e336ebaSIngo Weinhold
2351e336ebaSIngo Weinhold// #pragma mark - ThreadWaitObjectGroup
2361e336ebaSIngo Weinhold
2371e336ebaSIngo Weinhold
2381e336ebaSIngo WeinholdModel::ThreadWaitObjectGroup::ThreadWaitObjectGroup(
2391e336ebaSIngo Weinhold	ThreadWaitObject* threadWaitObject)
2401e336ebaSIngo Weinhold{
2411e336ebaSIngo Weinhold	fWaitObjects.Add(threadWaitObject);
2421e336ebaSIngo Weinhold}
2431e336ebaSIngo Weinhold
2441e336ebaSIngo Weinhold
2451e336ebaSIngo WeinholdModel::ThreadWaitObjectGroup::~ThreadWaitObjectGroup()
2461e336ebaSIngo Weinhold{
2471e336ebaSIngo Weinhold}
2481e336ebaSIngo Weinhold
2491e336ebaSIngo Weinhold
250055d771cSIngo Weinholdbool
251055d771cSIngo WeinholdModel::ThreadWaitObjectGroup::GetThreadWaitObjects(
252055d771cSIngo Weinhold	BObjectList<ThreadWaitObject>& objects)
253055d771cSIngo Weinhold{
254055d771cSIngo Weinhold	ThreadWaitObjectList::Iterator it = fWaitObjects.GetIterator();
255055d771cSIngo Weinhold	while (ThreadWaitObject* object = it.Next()) {
256055d771cSIngo Weinhold		if (!objects.AddItem(object))
257055d771cSIngo Weinhold			return false;
258055d771cSIngo Weinhold	}
259055d771cSIngo Weinhold
260055d771cSIngo Weinhold	return true;
261055d771cSIngo Weinhold}
262055d771cSIngo Weinhold
263055d771cSIngo Weinhold
26408e34e27SIngo Weinhold// #pragma mark - Team
26508e34e27SIngo Weinhold
26608e34e27SIngo Weinhold
267d8d4b902SIngo WeinholdModel::Team::Team(const system_profiler_team_added* event, nanotime_t time)
26808e34e27SIngo Weinhold	:
26908e34e27SIngo Weinhold	fCreationEvent(event),
27008e34e27SIngo Weinhold	fCreationTime(time),
27108e34e27SIngo Weinhold	fDeletionTime(-1),
27208e34e27SIngo Weinhold	fThreads(10)
27308e34e27SIngo Weinhold{
27408e34e27SIngo Weinhold}
27508e34e27SIngo Weinhold
27608e34e27SIngo Weinhold
27708e34e27SIngo WeinholdModel::Team::~Team()
27808e34e27SIngo Weinhold{
27908e34e27SIngo Weinhold}
28008e34e27SIngo Weinhold
28108e34e27SIngo Weinhold
28208e34e27SIngo Weinholdbool
28308e34e27SIngo WeinholdModel::Team::AddThread(Thread* thread)
28408e34e27SIngo Weinhold{
28508e34e27SIngo Weinhold	return fThreads.BinaryInsert(thread, &Thread::CompareByCreationTimeID);
28608e34e27SIngo Weinhold}
28708e34e27SIngo Weinhold
28808e34e27SIngo Weinhold
28908e34e27SIngo Weinhold// #pragma mark - Thread
29008e34e27SIngo Weinhold
29108e34e27SIngo Weinhold
29208e34e27SIngo WeinholdModel::Thread::Thread(Team* team, const system_profiler_thread_added* event,
293d8d4b902SIngo Weinhold	nanotime_t time)
29408e34e27SIngo Weinhold	:
295a63809d3SIngo Weinhold	fEvents(NULL),
296a63809d3SIngo Weinhold	fEventCount(0),
297c2354448SIngo Weinhold	fIORequests(NULL),
298c2354448SIngo Weinhold	fIORequestCount(0),
29908e34e27SIngo Weinhold	fTeam(team),
30008e34e27SIngo Weinhold	fCreationEvent(event),
30108e34e27SIngo Weinhold	fCreationTime(time),
3021e336ebaSIngo Weinhold	fDeletionTime(-1),
3031e336ebaSIngo Weinhold	fRuns(0),
3041e336ebaSIngo Weinhold	fTotalRunTime(0),
3051e336ebaSIngo Weinhold	fMinRunTime(-1),
3061e336ebaSIngo Weinhold	fMaxRunTime(-1),
3071e336ebaSIngo Weinhold	fLatencies(0),
3081e336ebaSIngo Weinhold	fTotalLatency(0),
3091e336ebaSIngo Weinhold	fMinLatency(-1),
3101e336ebaSIngo Weinhold	fMaxLatency(-1),
3111e336ebaSIngo Weinhold	fReruns(0),
3121e336ebaSIngo Weinhold	fTotalRerunTime(0),
3131e336ebaSIngo Weinhold	fMinRerunTime(-1),
3141e336ebaSIngo Weinhold	fMaxRerunTime(-1),
315d1331844SIngo Weinhold	fWaits(0),
316d1331844SIngo Weinhold	fTotalWaitTime(0),
3171e336ebaSIngo Weinhold	fUnspecifiedWaitTime(0),
318c2354448SIngo Weinhold	fIOCount(0),
319c2354448SIngo Weinhold	fIOTime(0),
3201e336ebaSIngo Weinhold	fPreemptions(0),
321d4d63490SIngo Weinhold	fIndex(-1),
3221e336ebaSIngo Weinhold	fWaitObjectGroups(20, true)
32308e34e27SIngo Weinhold{
32408e34e27SIngo Weinhold}
32508e34e27SIngo Weinhold
32608e34e27SIngo Weinhold
32708e34e27SIngo WeinholdModel::Thread::~Thread()
32808e34e27SIngo Weinhold{
329c2354448SIngo Weinhold	if (fIORequests != NULL) {
330c2354448SIngo Weinhold		for (size_t i = 0; i < fIORequestCount; i++)
331c2354448SIngo Weinhold			fIORequests[i]->Delete();
332c2354448SIngo Weinhold
333c2354448SIngo Weinhold		delete[] fIORequests;
334c2354448SIngo Weinhold	}
335c2354448SIngo Weinhold
336a63809d3SIngo Weinhold	delete[] fEvents;
337a63809d3SIngo Weinhold}
338a63809d3SIngo Weinhold
339a63809d3SIngo Weinhold
340a63809d3SIngo Weinholdvoid
341a63809d3SIngo WeinholdModel::Thread::SetEvents(system_profiler_event_header** events,
342a63809d3SIngo Weinhold	size_t eventCount)
343a63809d3SIngo Weinhold{
344a63809d3SIngo Weinhold	fEvents = events;
345a63809d3SIngo Weinhold	fEventCount = eventCount;
34608e34e27SIngo Weinhold}
34708e34e27SIngo Weinhold
34808e34e27SIngo Weinhold
349c2354448SIngo Weinholdvoid
350c2354448SIngo WeinholdModel::Thread::SetIORequests(IORequest** requests, size_t requestCount)
351c2354448SIngo Weinhold{
352c2354448SIngo Weinhold	fIORequests = requests;
353c2354448SIngo Weinhold	fIORequestCount = requestCount;
354c2354448SIngo Weinhold}
355c2354448SIngo Weinhold
356c2354448SIngo Weinhold
357f0a592fdSIngo Weinholdsize_t
358f0a592fdSIngo WeinholdModel::Thread::ClosestRequestStartIndex(nanotime_t minRequestStartTime) const
359f0a592fdSIngo Weinhold{
360f0a592fdSIngo Weinhold	size_t lower = 0;
361f0a592fdSIngo Weinhold	size_t upper = fIORequestCount;
362f0a592fdSIngo Weinhold	while (lower < upper) {
363f0a592fdSIngo Weinhold		size_t mid = (lower + upper) / 2;
364f0a592fdSIngo Weinhold		IORequest* request = fIORequests[mid];
365f0a592fdSIngo Weinhold
366f0a592fdSIngo Weinhold		if (request->ScheduledTime() < minRequestStartTime)
367f0a592fdSIngo Weinhold			lower = mid + 1;
368f0a592fdSIngo Weinhold		else
369f0a592fdSIngo Weinhold			upper = mid;
370f0a592fdSIngo Weinhold	}
371f0a592fdSIngo Weinhold
372f0a592fdSIngo Weinhold	return lower;
373f0a592fdSIngo Weinhold}
374f0a592fdSIngo Weinhold
375f0a592fdSIngo Weinhold
3761e336ebaSIngo WeinholdModel::ThreadWaitObjectGroup*
3771e336ebaSIngo WeinholdModel::Thread::ThreadWaitObjectGroupFor(uint32 type, addr_t object) const
3781e336ebaSIngo Weinhold{
3791e336ebaSIngo Weinhold	type_and_object key;
3801e336ebaSIngo Weinhold	key.type = type;
3811e336ebaSIngo Weinhold	key.object = object;
3821e336ebaSIngo Weinhold
3831e336ebaSIngo Weinhold	return fWaitObjectGroups.BinarySearchByKey(key,
3841e336ebaSIngo Weinhold		&ThreadWaitObjectGroup::CompareWithTypeObject);
3851e336ebaSIngo Weinhold}
3861e336ebaSIngo Weinhold
3871e336ebaSIngo Weinhold
3881e336ebaSIngo Weinholdvoid
389d8d4b902SIngo WeinholdModel::Thread::AddRun(nanotime_t runTime)
3901e336ebaSIngo Weinhold{
3911e336ebaSIngo Weinhold	fRuns++;
3921e336ebaSIngo Weinhold	fTotalRunTime += runTime;
3931e336ebaSIngo Weinhold
3941e336ebaSIngo Weinhold	if (fMinRunTime < 0 || runTime < fMinRunTime)
3951e336ebaSIngo Weinhold		fMinRunTime = runTime;
3961e336ebaSIngo Weinhold	if (runTime > fMaxRunTime)
3971e336ebaSIngo Weinhold		fMaxRunTime = runTime;
3981e336ebaSIngo Weinhold}
3991e336ebaSIngo Weinhold
4001e336ebaSIngo Weinhold
4011e336ebaSIngo Weinholdvoid
402d8d4b902SIngo WeinholdModel::Thread::AddRerun(nanotime_t runTime)
4031e336ebaSIngo Weinhold{
4041e336ebaSIngo Weinhold	fReruns++;
4051e336ebaSIngo Weinhold	fTotalRerunTime += runTime;
4061e336ebaSIngo Weinhold
4071e336ebaSIngo Weinhold	if (fMinRerunTime < 0 || runTime < fMinRerunTime)
4081e336ebaSIngo Weinhold		fMinRerunTime = runTime;
4091e336ebaSIngo Weinhold	if (runTime > fMaxRerunTime)
4101e336ebaSIngo Weinhold		fMaxRerunTime = runTime;
4111e336ebaSIngo Weinhold}
4121e336ebaSIngo Weinhold
4131e336ebaSIngo Weinhold
4141e336ebaSIngo Weinholdvoid
415d8d4b902SIngo WeinholdModel::Thread::AddLatency(nanotime_t latency)
4161e336ebaSIngo Weinhold{
4171e336ebaSIngo Weinhold	fLatencies++;
4181e336ebaSIngo Weinhold	fTotalLatency += latency;
4191e336ebaSIngo Weinhold
4201e336ebaSIngo Weinhold	if (fMinLatency < 0 || latency < fMinLatency)
4211e336ebaSIngo Weinhold		fMinLatency = latency;
4221e336ebaSIngo Weinhold	if (latency > fMaxLatency)
4231e336ebaSIngo Weinhold		fMaxLatency = latency;
4241e336ebaSIngo Weinhold}
4251e336ebaSIngo Weinhold
4261e336ebaSIngo Weinhold
4271e336ebaSIngo Weinholdvoid
428d8d4b902SIngo WeinholdModel::Thread::AddPreemption(nanotime_t runTime)
4291e336ebaSIngo Weinhold{
4301e336ebaSIngo Weinhold	fPreemptions++;
4311e336ebaSIngo Weinhold}
4321e336ebaSIngo Weinhold
4331e336ebaSIngo Weinhold
434d1331844SIngo Weinholdvoid
435d8d4b902SIngo WeinholdModel::Thread::AddWait(nanotime_t waitTime)
436d1331844SIngo Weinhold{
437d1331844SIngo Weinhold	fWaits++;
438d1331844SIngo Weinhold	fTotalWaitTime += waitTime;
439d1331844SIngo Weinhold}
440d1331844SIngo Weinhold
441d1331844SIngo Weinhold
4421e336ebaSIngo Weinholdvoid
443d8d4b902SIngo WeinholdModel::Thread::AddUnspecifiedWait(nanotime_t waitTime)
4441e336ebaSIngo Weinhold{
4451e336ebaSIngo Weinhold	fUnspecifiedWaitTime += waitTime;
4461e336ebaSIngo Weinhold}
4471e336ebaSIngo Weinhold
4481e336ebaSIngo Weinhold
4491e336ebaSIngo WeinholdModel::ThreadWaitObject*
4501e336ebaSIngo WeinholdModel::Thread::AddThreadWaitObject(WaitObject* waitObject,
4511e336ebaSIngo Weinhold	ThreadWaitObjectGroup** _threadWaitObjectGroup)
4521e336ebaSIngo Weinhold{
4531e336ebaSIngo Weinhold	// create a thread wait object
4541e336ebaSIngo Weinhold	ThreadWaitObject* threadWaitObject
4551e336ebaSIngo Weinhold		= new(std::nothrow) ThreadWaitObject(waitObject);
4561e336ebaSIngo Weinhold	if (threadWaitObject == NULL)
4571e336ebaSIngo Weinhold		return NULL;
4581e336ebaSIngo Weinhold
4591e336ebaSIngo Weinhold	// find the thread wait object group
4601e336ebaSIngo Weinhold	ThreadWaitObjectGroup* threadWaitObjectGroup
4611e336ebaSIngo Weinhold		= ThreadWaitObjectGroupFor(waitObject->Type(), waitObject->Object());
4621e336ebaSIngo Weinhold	if (threadWaitObjectGroup == NULL) {
4631e336ebaSIngo Weinhold		// doesn't exist yet -- create
4641e336ebaSIngo Weinhold		threadWaitObjectGroup = new(std::nothrow) ThreadWaitObjectGroup(
4651e336ebaSIngo Weinhold			threadWaitObject);
4661e336ebaSIngo Weinhold		if (threadWaitObjectGroup == NULL) {
4671e336ebaSIngo Weinhold			delete threadWaitObject;
4681e336ebaSIngo Weinhold			return NULL;
4691e336ebaSIngo Weinhold		}
4701e336ebaSIngo Weinhold
4711e336ebaSIngo Weinhold		// add to the list
4721e336ebaSIngo Weinhold		if (!fWaitObjectGroups.BinaryInsert(threadWaitObjectGroup,
4731e336ebaSIngo Weinhold				&ThreadWaitObjectGroup::CompareByTypeObject)) {
4741e336ebaSIngo Weinhold			delete threadWaitObjectGroup;
4751e336ebaSIngo Weinhold			return NULL;
4761e336ebaSIngo Weinhold		}
4771e336ebaSIngo Weinhold	} else {
4781e336ebaSIngo Weinhold		// exists -- just add the object
4791e336ebaSIngo Weinhold		threadWaitObjectGroup->AddWaitObject(threadWaitObject);
4801e336ebaSIngo Weinhold	}
4811e336ebaSIngo Weinhold
4821e336ebaSIngo Weinhold	if (_threadWaitObjectGroup != NULL)
4831e336ebaSIngo Weinhold		*_threadWaitObjectGroup = threadWaitObjectGroup;
4841e336ebaSIngo Weinhold
4851e336ebaSIngo Weinhold	return threadWaitObject;
4861e336ebaSIngo Weinhold}
4871e336ebaSIngo Weinhold
4881e336ebaSIngo Weinhold
489c2354448SIngo Weinholdvoid
490c2354448SIngo WeinholdModel::Thread::SetIOs(int64 count, nanotime_t time)
491c2354448SIngo Weinhold{
492c2354448SIngo Weinhold	fIOCount = count;
493c2354448SIngo Weinhold	fIOTime = time;
494c2354448SIngo Weinhold}
495c2354448SIngo Weinhold
496c2354448SIngo Weinhold
497d4d63490SIngo Weinhold// #pragma mark - SchedulingState
498d4d63490SIngo Weinhold
499d4d63490SIngo Weinhold
500d4d63490SIngo WeinholdModel::SchedulingState::~SchedulingState()
501d4d63490SIngo Weinhold{
502d4d63490SIngo Weinhold	Clear();
503d4d63490SIngo Weinhold}
504d4d63490SIngo Weinhold
505d4d63490SIngo Weinhold
506d4d63490SIngo Weinholdstatus_t
507d4d63490SIngo WeinholdModel::SchedulingState::Init()
508d4d63490SIngo Weinhold{
509d4d63490SIngo Weinhold	status_t error = fThreadStates.Init();
510d4d63490SIngo Weinhold	if (error != B_OK)
511d4d63490SIngo Weinhold		return error;
512d4d63490SIngo Weinhold
513d4d63490SIngo Weinhold	return B_OK;
514d4d63490SIngo Weinhold}
515d4d63490SIngo Weinhold
516d4d63490SIngo Weinhold
517d4d63490SIngo Weinholdstatus_t
518d4d63490SIngo WeinholdModel::SchedulingState::Init(const CompactSchedulingState* state)
519d4d63490SIngo Weinhold{
520d4d63490SIngo Weinhold	status_t error = Init();
521d4d63490SIngo Weinhold	if (error != B_OK)
522d4d63490SIngo Weinhold		return error;
523d4d63490SIngo Weinhold
524d4d63490SIngo Weinhold	if (state == NULL)
525d4d63490SIngo Weinhold		return B_OK;
526d4d63490SIngo Weinhold
527d4d63490SIngo Weinhold	fLastEventTime = state->LastEventTime();
528d4d63490SIngo Weinhold	for (int32 i = 0; const CompactThreadSchedulingState* compactThreadState
529d4d63490SIngo Weinhold			= state->ThreadStateAt(i); i++) {
530d4d63490SIngo Weinhold		ThreadSchedulingState* threadState
531d4d63490SIngo Weinhold			= new(std::nothrow) ThreadSchedulingState(*compactThreadState);
532d4d63490SIngo Weinhold		if (threadState == NULL)
533d4d63490SIngo Weinhold			return B_NO_MEMORY;
534d4d63490SIngo Weinhold
535d4d63490SIngo Weinhold		fThreadStates.Insert(threadState);
536d4d63490SIngo Weinhold	}
537d4d63490SIngo Weinhold
538d4d63490SIngo Weinhold	return B_OK;
539d4d63490SIngo Weinhold}
540d4d63490SIngo Weinhold
541d4d63490SIngo Weinhold
542d4d63490SIngo Weinholdvoid
543d4d63490SIngo WeinholdModel::SchedulingState::Clear()
544d4d63490SIngo Weinhold{
545d4d63490SIngo Weinhold	ThreadSchedulingState* state = fThreadStates.Clear(true);
546d4d63490SIngo Weinhold	while (state != NULL) {
547d4d63490SIngo Weinhold		ThreadSchedulingState* next = state->next;
548a63809d3SIngo Weinhold		DeleteThread(state);
549d4d63490SIngo Weinhold		state = next;
550d4d63490SIngo Weinhold	}
551d4d63490SIngo Weinhold
552d4d63490SIngo Weinhold	fLastEventTime = -1;
553d4d63490SIngo Weinhold}
554d4d63490SIngo Weinhold
555a63809d3SIngo Weinholdvoid
556a63809d3SIngo WeinholdModel::SchedulingState::DeleteThread(ThreadSchedulingState* thread)
557a63809d3SIngo Weinhold{
558a63809d3SIngo Weinhold	delete thread;
559a63809d3SIngo Weinhold}
560a63809d3SIngo Weinhold
561d4d63490SIngo Weinhold
562d4d63490SIngo Weinhold// #pragma mark - CompactSchedulingState
563d4d63490SIngo Weinhold
564d4d63490SIngo Weinhold
565d4d63490SIngo Weinhold/*static*/ Model::CompactSchedulingState*
566d4d63490SIngo WeinholdModel::CompactSchedulingState::Create(const SchedulingState& state,
567d4d63490SIngo Weinhold	off_t eventOffset)
568d4d63490SIngo Weinhold{
569d8d4b902SIngo Weinhold	nanotime_t lastEventTime = state.LastEventTime();
570d4d63490SIngo Weinhold
571d4d63490SIngo Weinhold	// count the active threads
572d4d63490SIngo Weinhold	int32 threadCount = 0;
573d4d63490SIngo Weinhold	for (ThreadSchedulingStateTable::Iterator it
574d4d63490SIngo Weinhold				= state.ThreadStates().GetIterator();
575d4d63490SIngo Weinhold			ThreadSchedulingState* threadState = it.Next();) {
576d4d63490SIngo Weinhold		Thread* thread = threadState->thread;
577d4d63490SIngo Weinhold		if (thread->CreationTime() <= lastEventTime
578d4d63490SIngo Weinhold			&& (thread->DeletionTime() == -1
579d4d63490SIngo Weinhold				|| thread->DeletionTime() >= lastEventTime)) {
580d4d63490SIngo Weinhold			threadCount++;
581d4d63490SIngo Weinhold		}
582d4d63490SIngo Weinhold	}
583d4d63490SIngo Weinhold
584d4d63490SIngo Weinhold	CompactSchedulingState* compactState = (CompactSchedulingState*)malloc(
585d4d63490SIngo Weinhold		sizeof(CompactSchedulingState)
586d4d63490SIngo Weinhold			+ threadCount * sizeof(CompactThreadSchedulingState));
587d4d63490SIngo Weinhold	if (compactState == NULL)
588d4d63490SIngo Weinhold		return NULL;
589d4d63490SIngo Weinhold
590d4d63490SIngo Weinhold	// copy the state info
591d4d63490SIngo Weinhold	compactState->fEventOffset = eventOffset;
592d4d63490SIngo Weinhold	compactState->fThreadCount = threadCount;
593d4d63490SIngo Weinhold	compactState->fLastEventTime = lastEventTime;
594d4d63490SIngo Weinhold
595d4d63490SIngo Weinhold	int32 threadIndex = 0;
596d4d63490SIngo Weinhold	for (ThreadSchedulingStateTable::Iterator it
597d4d63490SIngo Weinhold				= state.ThreadStates().GetIterator();
598d4d63490SIngo Weinhold			ThreadSchedulingState* threadState = it.Next();) {
599d4d63490SIngo Weinhold		Thread* thread = threadState->thread;
600d4d63490SIngo Weinhold		if (thread->CreationTime() <= lastEventTime
601d4d63490SIngo Weinhold			&& (thread->DeletionTime() == -1
602d4d63490SIngo Weinhold				|| thread->DeletionTime() >= lastEventTime)) {
603d4d63490SIngo Weinhold			compactState->fThreadStates[threadIndex++] = *threadState;
604d4d63490SIngo Weinhold		}
605d4d63490SIngo Weinhold	}
606d4d63490SIngo Weinhold
607d4d63490SIngo Weinhold	return compactState;
608d4d63490SIngo Weinhold}
609d4d63490SIngo Weinhold
610d4d63490SIngo Weinhold
611d4d63490SIngo Weinholdvoid
612d4d63490SIngo WeinholdModel::CompactSchedulingState::Delete()
613d4d63490SIngo Weinhold{
614d4d63490SIngo Weinhold	free(this);
615d4d63490SIngo Weinhold}
616d4d63490SIngo Weinhold
617d4d63490SIngo Weinhold
61808e34e27SIngo Weinhold// #pragma mark - Model
61908e34e27SIngo Weinhold
62008e34e27SIngo Weinhold
6216d5e661dSIngo WeinholdModel::Model(const char* dataSourceName, void* eventData, size_t eventDataSize,
6226d5e661dSIngo Weinhold	system_profiler_event_header** events, size_t eventCount)
62308e34e27SIngo Weinhold	:
62431391fedSIngo Weinhold	fDataSourceName(dataSourceName),
62508e34e27SIngo Weinhold	fEventData(eventData),
6266d5e661dSIngo Weinhold	fEvents(events),
62708e34e27SIngo Weinhold	fEventDataSize(eventDataSize),
6286d5e661dSIngo Weinhold	fEventCount(eventCount),
629bea40bcdSIngo Weinhold	fCPUCount(1),
63031391fedSIngo Weinhold	fBaseTime(0),
63131391fedSIngo Weinhold	fLastEventTime(0),
632bea40bcdSIngo Weinhold	fIdleTime(0),
633bea40bcdSIngo Weinhold	fCPUs(20, true),
63408e34e27SIngo Weinhold	fTeams(20, true),
6351e336ebaSIngo Weinhold	fThreads(20, true),
636d4d63490SIngo Weinhold	fWaitObjectGroups(20, true),
637934a8d01SIngo Weinhold	fIOSchedulers(10, true),
638d4d63490SIngo Weinhold	fSchedulingStates(100)
6393dc9bfd1SIngo Weinhold{
6403dc9bfd1SIngo Weinhold}
6413dc9bfd1SIngo Weinhold
6423dc9bfd1SIngo Weinhold
6434f1804a1SIngo WeinholdModel::~Model()
6443dc9bfd1SIngo Weinhold{
645d4d63490SIngo Weinhold	for (int32 i = 0; CompactSchedulingState* state
646d4d63490SIngo Weinhold		= fSchedulingStates.ItemAt(i); i++) {
647d4d63490SIngo Weinhold		state->Delete();
648d4d63490SIngo Weinhold	}
649d4d63490SIngo Weinhold
650a63809d3SIngo Weinhold	delete[] fEvents;
651a63809d3SIngo Weinhold
65208e34e27SIngo Weinhold	free(fEventData);
653e3bd3d83SIngo Weinhold
654e3bd3d83SIngo Weinhold	for (int32 i = 0; void* data = fAssociatedData.ItemAt(i); i++)
655e3bd3d83SIngo Weinhold		free(data);
65608e34e27SIngo Weinhold}
65708e34e27SIngo Weinhold
65808e34e27SIngo Weinhold
6596d5e661dSIngo Weinholdsize_t
6606d5e661dSIngo WeinholdModel::ClosestEventIndex(nanotime_t eventTime) const
6616d5e661dSIngo Weinhold{
6626d5e661dSIngo Weinhold	// The events themselves are unmodified and use an absolute time.
6636d5e661dSIngo Weinhold	eventTime += fBaseTime;
6646d5e661dSIngo Weinhold
6656d5e661dSIngo Weinhold	// Binary search the event. Since not all events have a timestamp, we have
6666d5e661dSIngo Weinhold	// to do a bit of iteration, too.
6676d5e661dSIngo Weinhold	size_t lower = 0;
6686d5e661dSIngo Weinhold	size_t upper = CountEvents();
6696d5e661dSIngo Weinhold	while (lower < upper) {
6706d5e661dSIngo Weinhold		size_t mid = (lower + upper) / 2;
6716d5e661dSIngo Weinhold		while (mid < upper) {
6726d5e661dSIngo Weinhold			system_profiler_event_header* header = fEvents[mid];
6736d5e661dSIngo Weinhold			switch (header->event) {
6746d5e661dSIngo Weinhold				case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
6756d5e661dSIngo Weinhold				case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE:
6766d5e661dSIngo Weinhold				case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE:
6776d5e661dSIngo Weinhold					break;
6786d5e661dSIngo Weinhold				default:
6796d5e661dSIngo Weinhold					mid++;
6806d5e661dSIngo Weinhold					continue;
6816d5e661dSIngo Weinhold			}
6826d5e661dSIngo Weinhold
6836d5e661dSIngo Weinhold			break;
6846d5e661dSIngo Weinhold		}
6856d5e661dSIngo Weinhold
6866d5e661dSIngo Weinhold		if (mid == upper) {
6876d5e661dSIngo Weinhold			lower = mid;
6886d5e661dSIngo Weinhold			break;
6896d5e661dSIngo Weinhold		}
6906d5e661dSIngo Weinhold
6916d5e661dSIngo Weinhold		system_profiler_thread_scheduling_event* event
6926d5e661dSIngo Weinhold			= (system_profiler_thread_scheduling_event*)(fEvents[mid] + 1);
6936d5e661dSIngo Weinhold		if (event->time < eventTime)
6946d5e661dSIngo Weinhold			lower = mid + 1;
6956d5e661dSIngo Weinhold		else
6966d5e661dSIngo Weinhold			upper = mid;
6976d5e661dSIngo Weinhold	}
6986d5e661dSIngo Weinhold
6996d5e661dSIngo Weinhold	return lower;
7006d5e661dSIngo Weinhold}
7016d5e661dSIngo Weinhold
7026d5e661dSIngo Weinhold
703e3bd3d83SIngo Weinholdbool
704e3bd3d83SIngo WeinholdModel::AddAssociatedData(void* data)
705e3bd3d83SIngo Weinhold{
706e3bd3d83SIngo Weinhold	return fAssociatedData.AddItem(data);
707e3bd3d83SIngo Weinhold}
708e3bd3d83SIngo Weinhold
709e3bd3d83SIngo Weinhold
710e3bd3d83SIngo Weinholdvoid
711e3bd3d83SIngo WeinholdModel::RemoveAssociatedData(void* data)
712e3bd3d83SIngo Weinhold{
713e3bd3d83SIngo Weinhold	fAssociatedData.RemoveItem(data);
714e3bd3d83SIngo Weinhold}
715e3bd3d83SIngo Weinhold
716e3bd3d83SIngo Weinhold
717d4d63490SIngo Weinholdvoid
718d4d63490SIngo WeinholdModel::LoadingFinished()
719d4d63490SIngo Weinhold{
720bea40bcdSIngo Weinhold	// set the thread indices
721d4d63490SIngo Weinhold	for (int32 i = 0; Thread* thread = fThreads.ItemAt(i); i++)
722d4d63490SIngo Weinhold		thread->SetIndex(i);
723bea40bcdSIngo Weinhold
724bea40bcdSIngo Weinhold	// compute the total idle time
725bea40bcdSIngo Weinhold	fIdleTime = 0;
726bea40bcdSIngo Weinhold	for (int32 i = 0; CPU* cpu = CPUAt(i); i++)
727bea40bcdSIngo Weinhold		fIdleTime += cpu->IdleTime();
728d4d63490SIngo Weinhold}
729d4d63490SIngo Weinhold
730d4d63490SIngo Weinhold
73131391fedSIngo Weinholdvoid
732d8d4b902SIngo WeinholdModel::SetBaseTime(nanotime_t time)
73331391fedSIngo Weinhold{
73431391fedSIngo Weinhold	fBaseTime = time;
735d4d63490SIngo Weinhold}
73631391fedSIngo Weinhold
73731391fedSIngo Weinhold
73831391fedSIngo Weinholdvoid
739d8d4b902SIngo WeinholdModel::SetLastEventTime(nanotime_t time)
74031391fedSIngo Weinhold{
74131391fedSIngo Weinhold	fLastEventTime = time;
74231391fedSIngo Weinhold}
74331391fedSIngo Weinhold
74431391fedSIngo Weinhold
745bea40bcdSIngo Weinholdbool
746bea40bcdSIngo WeinholdModel::SetCPUCount(int32 count)
747bea40bcdSIngo Weinhold{
748bea40bcdSIngo Weinhold	fCPUCount = count;
749bea40bcdSIngo Weinhold
750bea40bcdSIngo Weinhold	fCPUs.MakeEmpty();
751bea40bcdSIngo Weinhold
752bea40bcdSIngo Weinhold	for (int32 i = 0; i < fCPUCount; i++) {
753bea40bcdSIngo Weinhold		CPU* cpu = new(std::nothrow) CPU;
754bea40bcdSIngo Weinhold		if (cpu == NULL || !fCPUs.AddItem(cpu)) {
755bea40bcdSIngo Weinhold			delete cpu;
756bea40bcdSIngo Weinhold			return false;
757bea40bcdSIngo Weinhold		}
758bea40bcdSIngo Weinhold	}
759bea40bcdSIngo Weinhold
760bea40bcdSIngo Weinhold	return true;
761bea40bcdSIngo Weinhold}
762bea40bcdSIngo Weinhold
763bea40bcdSIngo Weinhold
76408e34e27SIngo Weinholdint32
76508e34e27SIngo WeinholdModel::CountTeams() const
76608e34e27SIngo Weinhold{
76708e34e27SIngo Weinhold		return fTeams.CountItems();
76808e34e27SIngo Weinhold}
76908e34e27SIngo Weinhold
77008e34e27SIngo Weinhold
77108e34e27SIngo WeinholdModel::Team*
77208e34e27SIngo WeinholdModel::TeamAt(int32 index) const
77308e34e27SIngo Weinhold{
77408e34e27SIngo Weinhold	return fTeams.ItemAt(index);
77508e34e27SIngo Weinhold}
77608e34e27SIngo Weinhold
77708e34e27SIngo Weinhold
77808e34e27SIngo WeinholdModel::Team*
77908e34e27SIngo WeinholdModel::TeamByID(team_id id) const
78008e34e27SIngo Weinhold{
78108e34e27SIngo Weinhold	return fTeams.BinarySearchByKey(id, &Team::CompareWithID);
78208e34e27SIngo Weinhold}
78308e34e27SIngo Weinhold
78408e34e27SIngo Weinhold
78508e34e27SIngo WeinholdModel::Team*
786d8d4b902SIngo WeinholdModel::AddTeam(const system_profiler_team_added* event, nanotime_t time)
78708e34e27SIngo Weinhold{
78808e34e27SIngo Weinhold	Team* team = TeamByID(event->team);
78908e34e27SIngo Weinhold	if (team != NULL) {
790883b3e1dSMichael Lotz		fprintf(stderr, "Duplicate team: %" B_PRId32 "\n", event->team);
79108e34e27SIngo Weinhold		// TODO: User feedback!
79208e34e27SIngo Weinhold		return team;
79308e34e27SIngo Weinhold	}
79408e34e27SIngo Weinhold
79508e34e27SIngo Weinhold	team = new(std::nothrow) Team(event, time);
79608e34e27SIngo Weinhold	if (team == NULL)
79708e34e27SIngo Weinhold		return NULL;
79808e34e27SIngo Weinhold
79908e34e27SIngo Weinhold	if (!fTeams.BinaryInsert(team, &Team::CompareByID)) {
80008e34e27SIngo Weinhold		delete team;
80108e34e27SIngo Weinhold		return NULL;
80208e34e27SIngo Weinhold	}
80308e34e27SIngo Weinhold
80408e34e27SIngo Weinhold	return team;
80508e34e27SIngo Weinhold}
80608e34e27SIngo Weinhold
80708e34e27SIngo Weinhold
80808e34e27SIngo Weinholdint32
80908e34e27SIngo WeinholdModel::CountThreads() const
81008e34e27SIngo Weinhold{
81108e34e27SIngo Weinhold	return fThreads.CountItems();
81208e34e27SIngo Weinhold}
81308e34e27SIngo Weinhold
81408e34e27SIngo Weinhold
81508e34e27SIngo WeinholdModel::Thread*
81608e34e27SIngo WeinholdModel::ThreadAt(int32 index) const
81708e34e27SIngo Weinhold{
81808e34e27SIngo Weinhold	return fThreads.ItemAt(index);
81908e34e27SIngo Weinhold}
82008e34e27SIngo Weinhold
82108e34e27SIngo Weinhold
82208e34e27SIngo WeinholdModel::Thread*
82308e34e27SIngo WeinholdModel::ThreadByID(thread_id id) const
82408e34e27SIngo Weinhold{
82508e34e27SIngo Weinhold	return fThreads.BinarySearchByKey(id, &Thread::CompareWithID);
82608e34e27SIngo Weinhold}
82708e34e27SIngo Weinhold
82808e34e27SIngo Weinhold
82908e34e27SIngo WeinholdModel::Thread*
830d8d4b902SIngo WeinholdModel::AddThread(const system_profiler_thread_added* event, nanotime_t time)
83108e34e27SIngo Weinhold{
83208e34e27SIngo Weinhold	// check whether we do already know the thread
83308e34e27SIngo Weinhold	Thread* thread = ThreadByID(event->thread);
83408e34e27SIngo Weinhold	if (thread != NULL) {
835883b3e1dSMichael Lotz		fprintf(stderr, "Duplicate thread: %" B_PRId32 "\n", event->thread);
83608e34e27SIngo Weinhold		// TODO: User feedback!
83708e34e27SIngo Weinhold		return thread;
83808e34e27SIngo Weinhold	}
83908e34e27SIngo Weinhold
84008e34e27SIngo Weinhold	// get its team
84108e34e27SIngo Weinhold	Team* team = TeamByID(event->team);
84208e34e27SIngo Weinhold	if (team == NULL) {
843883b3e1dSMichael Lotz		fprintf(stderr, "No team for thread: %" B_PRId32 "\n", event->thread);
84408e34e27SIngo Weinhold		return NULL;
84508e34e27SIngo Weinhold	}
84608e34e27SIngo Weinhold
84708e34e27SIngo Weinhold	// create the thread and add it
84808e34e27SIngo Weinhold	thread = new(std::nothrow) Thread(team, event, time);
84908e34e27SIngo Weinhold	if (thread == NULL)
85008e34e27SIngo Weinhold		return NULL;
85108e34e27SIngo Weinhold	ObjectDeleter<Thread> threadDeleter(thread);
85208e34e27SIngo Weinhold
85308e34e27SIngo Weinhold	if (!fThreads.BinaryInsert(thread, &Thread::CompareByID))
85408e34e27SIngo Weinhold		return NULL;
85508e34e27SIngo Weinhold
85608e34e27SIngo Weinhold	if (!team->AddThread(thread)) {
85708e34e27SIngo Weinhold		fThreads.RemoveItem(thread);
85808e34e27SIngo Weinhold		return NULL;
85908e34e27SIngo Weinhold	}
86008e34e27SIngo Weinhold
86108e34e27SIngo Weinhold	threadDeleter.Detach();
86208e34e27SIngo Weinhold	return thread;
8633dc9bfd1SIngo Weinhold}
8641e336ebaSIngo Weinhold
8651e336ebaSIngo Weinhold
8661e336ebaSIngo WeinholdModel::WaitObject*
8671e336ebaSIngo WeinholdModel::AddWaitObject(const system_profiler_wait_object_info* event,
8681e336ebaSIngo Weinhold	WaitObjectGroup** _waitObjectGroup)
8691e336ebaSIngo Weinhold{
8701e336ebaSIngo Weinhold	// create a wait object
8711e336ebaSIngo Weinhold	WaitObject* waitObject = new(std::nothrow) WaitObject(event);
8721e336ebaSIngo Weinhold	if (waitObject == NULL)
8731e336ebaSIngo Weinhold		return NULL;
8741e336ebaSIngo Weinhold
8751e336ebaSIngo Weinhold	// find the wait object group
8761e336ebaSIngo Weinhold	WaitObjectGroup* waitObjectGroup
8771e336ebaSIngo Weinhold		= WaitObjectGroupFor(waitObject->Type(), waitObject->Object());
8781e336ebaSIngo Weinhold	if (waitObjectGroup == NULL) {
8791e336ebaSIngo Weinhold		// doesn't exist yet -- create
8801e336ebaSIngo Weinhold		waitObjectGroup = new(std::nothrow) WaitObjectGroup(waitObject);
8811e336ebaSIngo Weinhold		if (waitObjectGroup == NULL) {
8821e336ebaSIngo Weinhold			delete waitObject;
8831e336ebaSIngo Weinhold			return NULL;
8841e336ebaSIngo Weinhold		}
8851e336ebaSIngo Weinhold
8861e336ebaSIngo Weinhold		// add to the list
8871e336ebaSIngo Weinhold		if (!fWaitObjectGroups.BinaryInsert(waitObjectGroup,
8881e336ebaSIngo Weinhold				&WaitObjectGroup::CompareByTypeObject)) {
8891e336ebaSIngo Weinhold			delete waitObjectGroup;
8901e336ebaSIngo Weinhold			return NULL;
8911e336ebaSIngo Weinhold		}
8921e336ebaSIngo Weinhold	} else {
8931e336ebaSIngo Weinhold		// exists -- just add the object
8941e336ebaSIngo Weinhold		waitObjectGroup->AddWaitObject(waitObject);
8951e336ebaSIngo Weinhold	}
8961e336ebaSIngo Weinhold
8971e336ebaSIngo Weinhold	if (_waitObjectGroup != NULL)
8981e336ebaSIngo Weinhold		*_waitObjectGroup = waitObjectGroup;
8991e336ebaSIngo Weinhold
9001e336ebaSIngo Weinhold	return waitObject;
9011e336ebaSIngo Weinhold}
9021e336ebaSIngo Weinhold
9031e336ebaSIngo Weinhold
9044e890d34SAxel Dörflerint32
9054e890d34SAxel DörflerModel::CountWaitObjectGroups() const
9064e890d34SAxel Dörfler{
9074e890d34SAxel Dörfler	return fWaitObjectGroups.CountItems();
9084e890d34SAxel Dörfler}
9094e890d34SAxel Dörfler
9104e890d34SAxel Dörfler
9114e890d34SAxel DörflerModel::WaitObjectGroup*
9124e890d34SAxel DörflerModel::WaitObjectGroupAt(int32 index) const
9134e890d34SAxel Dörfler{
9144e890d34SAxel Dörfler	return fWaitObjectGroups.ItemAt(index);
9154e890d34SAxel Dörfler}
9164e890d34SAxel Dörfler
9174e890d34SAxel Dörfler
9181e336ebaSIngo WeinholdModel::WaitObjectGroup*
9191e336ebaSIngo WeinholdModel::WaitObjectGroupFor(uint32 type, addr_t object) const
9201e336ebaSIngo Weinhold{
9211e336ebaSIngo Weinhold	type_and_object key;
9221e336ebaSIngo Weinhold	key.type = type;
9231e336ebaSIngo Weinhold	key.object = object;
9241e336ebaSIngo Weinhold
9251e336ebaSIngo Weinhold	return fWaitObjectGroups.BinarySearchByKey(key,
9261e336ebaSIngo Weinhold		&WaitObjectGroup::CompareWithTypeObject);
9271e336ebaSIngo Weinhold}
9281e336ebaSIngo Weinhold
9291e336ebaSIngo Weinhold
9301e336ebaSIngo WeinholdModel::ThreadWaitObject*
9311e336ebaSIngo WeinholdModel::AddThreadWaitObject(thread_id threadID, WaitObject* waitObject,
9321e336ebaSIngo Weinhold	ThreadWaitObjectGroup** _threadWaitObjectGroup)
9331e336ebaSIngo Weinhold{
9341e336ebaSIngo Weinhold	Thread* thread = ThreadByID(threadID);
9351e336ebaSIngo Weinhold	if (thread == NULL)
9361e336ebaSIngo Weinhold		return NULL;
9371e336ebaSIngo Weinhold
9381e336ebaSIngo Weinhold	return thread->AddThreadWaitObject(waitObject, _threadWaitObjectGroup);
9391e336ebaSIngo Weinhold}
9401e336ebaSIngo Weinhold
9411e336ebaSIngo Weinhold
9421e336ebaSIngo WeinholdModel::ThreadWaitObjectGroup*
9431e336ebaSIngo WeinholdModel::ThreadWaitObjectGroupFor(thread_id threadID, uint32 type, addr_t object) const
9441e336ebaSIngo Weinhold{
9451e336ebaSIngo Weinhold	Thread* thread = ThreadByID(threadID);
9461e336ebaSIngo Weinhold	if (thread == NULL)
9471e336ebaSIngo Weinhold		return NULL;
9481e336ebaSIngo Weinhold
9491e336ebaSIngo Weinhold	return thread->ThreadWaitObjectGroupFor(type, object);
9501e336ebaSIngo Weinhold}
951d4d63490SIngo Weinhold
952d4d63490SIngo Weinhold
953934a8d01SIngo Weinholdint32
954934a8d01SIngo WeinholdModel::CountIOSchedulers() const
955934a8d01SIngo Weinhold{
956934a8d01SIngo Weinhold	return fIOSchedulers.CountItems();
957934a8d01SIngo Weinhold}
958934a8d01SIngo Weinhold
959934a8d01SIngo Weinhold
960934a8d01SIngo WeinholdModel::IOScheduler*
961934a8d01SIngo WeinholdModel::IOSchedulerAt(int32 index) const
962934a8d01SIngo Weinhold{
963934a8d01SIngo Weinhold	return fIOSchedulers.ItemAt(index);
964934a8d01SIngo Weinhold}
965934a8d01SIngo Weinhold
966934a8d01SIngo Weinhold
967934a8d01SIngo WeinholdModel::IOScheduler*
968934a8d01SIngo WeinholdModel::IOSchedulerByID(int32 id) const
969934a8d01SIngo Weinhold{
970934a8d01SIngo Weinhold	for (int32 i = 0; IOScheduler* scheduler = fIOSchedulers.ItemAt(i); i++) {
971