xref: /haiku/src/apps/debuganalyzer/model_loader/ModelLoader.cpp (revision c199c568dec06759c5e47d3d246299a1aba45f3d)
137ea7254SIngo Weinhold /*
237ea7254SIngo Weinhold  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
337ea7254SIngo Weinhold  * Distributed under the terms of the MIT License.
437ea7254SIngo Weinhold  */
537ea7254SIngo Weinhold 
6d4d63490SIngo Weinhold 
737ea7254SIngo Weinhold #include "ModelLoader.h"
837ea7254SIngo Weinhold 
937ea7254SIngo Weinhold #include <stdio.h>
1037ea7254SIngo Weinhold #include <string.h>
1137ea7254SIngo Weinhold 
12c2354448SIngo Weinhold #include <algorithm>
1337ea7254SIngo Weinhold #include <new>
1437ea7254SIngo Weinhold 
1537ea7254SIngo Weinhold #include <AutoDeleter.h>
1637ea7254SIngo Weinhold #include <AutoLocker.h>
1737ea7254SIngo Weinhold #include <DebugEventStream.h>
1837ea7254SIngo Weinhold 
1937ea7254SIngo Weinhold #include <system_profiler_defs.h>
2037ea7254SIngo Weinhold #include <thread_defs.h>
2137ea7254SIngo Weinhold 
2237ea7254SIngo Weinhold #include "DataSource.h"
2337ea7254SIngo Weinhold #include "MessageCodes.h"
2437ea7254SIngo Weinhold #include "Model.h"
2537ea7254SIngo Weinhold 
2637ea7254SIngo Weinhold 
27d4d63490SIngo Weinhold // add a scheduling state snapshot every x events
28d4d63490SIngo Weinhold static const uint32 kSchedulingSnapshotInterval = 1024;
29d4d63490SIngo Weinhold 
30bea40bcdSIngo Weinhold static const uint32 kMaxCPUCount = 1024;
31bea40bcdSIngo Weinhold 
32d4d63490SIngo Weinhold 
3337ea7254SIngo Weinhold struct SimpleWaitObjectInfo : system_profiler_wait_object_info {
SimpleWaitObjectInfoSimpleWaitObjectInfo3437ea7254SIngo Weinhold 	SimpleWaitObjectInfo(uint32 type)
3537ea7254SIngo Weinhold 	{
3637ea7254SIngo Weinhold 		this->type = type;
3737ea7254SIngo Weinhold 		object = 0;
3837ea7254SIngo Weinhold 		referenced_object = 0;
3937ea7254SIngo Weinhold 		name[0] = '\0';
4037ea7254SIngo Weinhold 	}
4137ea7254SIngo Weinhold };
4237ea7254SIngo Weinhold 
4337ea7254SIngo Weinhold 
4437ea7254SIngo Weinhold static const SimpleWaitObjectInfo kSnoozeWaitObjectInfo(
4537ea7254SIngo Weinhold 	THREAD_BLOCK_TYPE_SNOOZE);
4637ea7254SIngo Weinhold static const SimpleWaitObjectInfo kSignalWaitObjectInfo(
4737ea7254SIngo Weinhold 	THREAD_BLOCK_TYPE_SIGNAL);
4837ea7254SIngo Weinhold 
4937ea7254SIngo Weinhold 
50a63809d3SIngo Weinhold // #pragma mark - CPUInfo
51a63809d3SIngo Weinhold 
52a63809d3SIngo Weinhold 
53bea40bcdSIngo Weinhold struct ModelLoader::CPUInfo {
54bea40bcdSIngo Weinhold 	nanotime_t	idleTime;
55bea40bcdSIngo Weinhold 
CPUInfoModelLoader::CPUInfo56bea40bcdSIngo Weinhold 	CPUInfo()
57bea40bcdSIngo Weinhold 		:
58bea40bcdSIngo Weinhold 		idleTime(0)
59bea40bcdSIngo Weinhold 	{
60bea40bcdSIngo Weinhold 	}
61bea40bcdSIngo Weinhold };
62bea40bcdSIngo Weinhold 
63bea40bcdSIngo Weinhold 
64c2354448SIngo Weinhold // #pragma mark - IOOperation
65c2354448SIngo Weinhold 
66c2354448SIngo Weinhold 
67c2354448SIngo Weinhold struct ModelLoader::IOOperation : DoublyLinkedListLinkImpl<IOOperation> {
68c2354448SIngo Weinhold 	io_operation_started*	startedEvent;
69c2354448SIngo Weinhold 	io_operation_finished*	finishedEvent;
70c2354448SIngo Weinhold 
IOOperationModelLoader::IOOperation71c2354448SIngo Weinhold 	IOOperation(io_operation_started* startedEvent)
72c2354448SIngo Weinhold 		:
73c2354448SIngo Weinhold 		startedEvent(startedEvent),
74c2354448SIngo Weinhold 		finishedEvent(NULL)
75c2354448SIngo Weinhold 	{
76c2354448SIngo Weinhold 	}
77c2354448SIngo Weinhold };
78c2354448SIngo Weinhold 
79c2354448SIngo Weinhold 
80c2354448SIngo Weinhold // #pragma mark - IORequest
81c2354448SIngo Weinhold 
82c2354448SIngo Weinhold 
83c2354448SIngo Weinhold struct ModelLoader::IORequest : DoublyLinkedListLinkImpl<IORequest> {
84c2354448SIngo Weinhold 	io_request_scheduled*	scheduledEvent;
85c2354448SIngo Weinhold 	io_request_finished*	finishedEvent;
86c2354448SIngo Weinhold 	IOOperationList			operations;
87c2354448SIngo Weinhold 	size_t					operationCount;
88c2354448SIngo Weinhold 	IORequest*				hashNext;
89c2354448SIngo Weinhold 
IORequestModelLoader::IORequest90c2354448SIngo Weinhold 	IORequest(io_request_scheduled* scheduledEvent)
91c2354448SIngo Weinhold 		:
92c2354448SIngo Weinhold 		scheduledEvent(scheduledEvent),
93c2354448SIngo Weinhold 		finishedEvent(NULL),
94c2354448SIngo Weinhold 		operationCount(0)
95c2354448SIngo Weinhold 	{
96c2354448SIngo Weinhold 	}
97c2354448SIngo Weinhold 
~IORequestModelLoader::IORequest98c2354448SIngo Weinhold 	~IORequest()
99c2354448SIngo Weinhold 	{
100c2354448SIngo Weinhold 		while (IOOperation* operation = operations.RemoveHead())
101c2354448SIngo Weinhold 			delete operation;
102c2354448SIngo Weinhold 	}
103c2354448SIngo Weinhold 
AddOperationModelLoader::IORequest104c2354448SIngo Weinhold 	void AddOperation(IOOperation* operation)
105c2354448SIngo Weinhold 	{
106c2354448SIngo Weinhold 		operations.Add(operation);
107c2354448SIngo Weinhold 		operationCount++;
108c2354448SIngo Weinhold 	}
109c2354448SIngo Weinhold 
FindOperationModelLoader::IORequest110c2354448SIngo Weinhold 	IOOperation* FindOperation(void* address) const
111c2354448SIngo Weinhold 	{
112c2354448SIngo Weinhold 		for (IOOperationList::ConstReverseIterator it
113c2354448SIngo Weinhold 				= operations.GetReverseIterator();
114c2354448SIngo Weinhold 			IOOperation* operation = it.Next();) {
115c2354448SIngo Weinhold 			if (operation->startedEvent->operation == address)
116c2354448SIngo Weinhold 				return operation;
117c2354448SIngo Weinhold 		}
118c2354448SIngo Weinhold 
119c2354448SIngo Weinhold 		return NULL;
120c2354448SIngo Weinhold 	}
121c2354448SIngo Weinhold 
CreateModelRequestModelLoader::IORequest122c2354448SIngo Weinhold 	Model::IORequest* CreateModelRequest() const
123c2354448SIngo Weinhold 	{
124c2354448SIngo Weinhold 		size_t operationCount = operations.Count();
125c2354448SIngo Weinhold 
126c2354448SIngo Weinhold 		Model::IORequest* modelRequest = Model::IORequest::Create(
127c2354448SIngo Weinhold 			scheduledEvent, finishedEvent, operationCount);
128c2354448SIngo Weinhold 		if (modelRequest == NULL)
129c2354448SIngo Weinhold 			return NULL;
130c2354448SIngo Weinhold 
131c2354448SIngo Weinhold 		size_t index = 0;
132c2354448SIngo Weinhold 		for (IOOperationList::ConstIterator it = operations.GetIterator();
133c2354448SIngo Weinhold 				IOOperation* operation = it.Next();) {
134c2354448SIngo Weinhold 			Model::IOOperation& modelOperation
135c2354448SIngo Weinhold 				= modelRequest->operations[index++];
136c2354448SIngo Weinhold 			modelOperation.startedEvent = operation->startedEvent;
137c2354448SIngo Weinhold 			modelOperation.finishedEvent = operation->finishedEvent;
138c2354448SIngo Weinhold 		}
139c2354448SIngo Weinhold 
140c2354448SIngo Weinhold 		return modelRequest;
141c2354448SIngo Weinhold 	}
142c2354448SIngo Weinhold };
143c2354448SIngo Weinhold 
144c2354448SIngo Weinhold 
145c2354448SIngo Weinhold // #pragma mark - IORequestHashDefinition
146c2354448SIngo Weinhold 
147c2354448SIngo Weinhold 
148c2354448SIngo Weinhold struct ModelLoader::IORequestHashDefinition {
149c2354448SIngo Weinhold 	typedef void*		KeyType;
150c2354448SIngo Weinhold 	typedef	IORequest	ValueType;
151c2354448SIngo Weinhold 
HashKeyModelLoader::IORequestHashDefinition152c2354448SIngo Weinhold 	size_t HashKey(KeyType key) const
153c2354448SIngo Weinhold 		{ return (size_t)key; }
154c2354448SIngo Weinhold 
HashModelLoader::IORequestHashDefinition155c2354448SIngo Weinhold 	size_t Hash(const IORequest* value) const
156c2354448SIngo Weinhold 		{ return HashKey(value->scheduledEvent->request); }
157c2354448SIngo Weinhold 
CompareModelLoader::IORequestHashDefinition158c2354448SIngo Weinhold 	bool Compare(KeyType key, const IORequest* value) const
159c2354448SIngo Weinhold 		{ return key == value->scheduledEvent->request; }
160c2354448SIngo Weinhold 
GetLinkModelLoader::IORequestHashDefinition161c2354448SIngo Weinhold 	IORequest*& GetLink(IORequest* value) const
162c2354448SIngo Weinhold 		{ return value->hashNext; }
163c2354448SIngo Weinhold };
164c2354448SIngo Weinhold 
165c2354448SIngo Weinhold 
166a63809d3SIngo Weinhold // #pragma mark - ExtendedThreadSchedulingState
167a63809d3SIngo Weinhold 
168a63809d3SIngo Weinhold 
169a63809d3SIngo Weinhold struct ModelLoader::ExtendedThreadSchedulingState
170a63809d3SIngo Weinhold 		: Model::ThreadSchedulingState {
171a63809d3SIngo Weinhold 
ExtendedThreadSchedulingStateModelLoader::ExtendedThreadSchedulingState172a63809d3SIngo Weinhold 	ExtendedThreadSchedulingState(Model::Thread* thread)
173a63809d3SIngo Weinhold 		:
174a63809d3SIngo Weinhold 		Model::ThreadSchedulingState(thread),
175a63809d3SIngo Weinhold 		fEvents(NULL),
176a63809d3SIngo Weinhold 		fEventIndex(0),
177a63809d3SIngo Weinhold 		fEventCount(0)
178a63809d3SIngo Weinhold 	{
179a63809d3SIngo Weinhold 	}
180a63809d3SIngo Weinhold 
~ExtendedThreadSchedulingStateModelLoader::ExtendedThreadSchedulingState181a63809d3SIngo Weinhold 	~ExtendedThreadSchedulingState()
182a63809d3SIngo Weinhold 	{
183a63809d3SIngo Weinhold 		delete[] fEvents;
184c2354448SIngo Weinhold 
185c2354448SIngo Weinhold 		while (IORequest* request = fIORequests.RemoveHead())
186c2354448SIngo Weinhold 			delete request;
187c2354448SIngo Weinhold 		while (IORequest* request = fPendingIORequests.RemoveHead())
188c2354448SIngo Weinhold 			delete request;
189a63809d3SIngo Weinhold 	}
190a63809d3SIngo Weinhold 
EventsModelLoader::ExtendedThreadSchedulingState191a63809d3SIngo Weinhold 	system_profiler_event_header** Events() const
192a63809d3SIngo Weinhold 	{
193a63809d3SIngo Weinhold 		return fEvents;
194a63809d3SIngo Weinhold 	}
195a63809d3SIngo Weinhold 
CountEventsModelLoader::ExtendedThreadSchedulingState196a63809d3SIngo Weinhold 	size_t CountEvents() const
197a63809d3SIngo Weinhold 	{
198a63809d3SIngo Weinhold 		return fEventCount;
199a63809d3SIngo Weinhold 	}
200a63809d3SIngo Weinhold 
DetachEventsModelLoader::ExtendedThreadSchedulingState201a63809d3SIngo Weinhold 	system_profiler_event_header** DetachEvents()
202a63809d3SIngo Weinhold 	{
203a63809d3SIngo Weinhold 		system_profiler_event_header** events = fEvents;
204a63809d3SIngo Weinhold 		fEvents = NULL;
205a63809d3SIngo Weinhold 		return events;
206a63809d3SIngo Weinhold 	}
207a63809d3SIngo Weinhold 
IncrementEventCountModelLoader::ExtendedThreadSchedulingState208a63809d3SIngo Weinhold 	void IncrementEventCount()
209a63809d3SIngo Weinhold 	{
210a63809d3SIngo Weinhold 		fEventCount++;
211a63809d3SIngo Weinhold 	}
212a63809d3SIngo Weinhold 
AddEventModelLoader::ExtendedThreadSchedulingState213a63809d3SIngo Weinhold 	void AddEvent(system_profiler_event_header* event)
214a63809d3SIngo Weinhold 	{
215a63809d3SIngo Weinhold 		fEvents[fEventIndex++] = event;
216a63809d3SIngo Weinhold 	}
217a63809d3SIngo Weinhold 
AllocateEventArrayModelLoader::ExtendedThreadSchedulingState218a63809d3SIngo Weinhold 	bool AllocateEventArray()
219a63809d3SIngo Weinhold 	{
220a63809d3SIngo Weinhold 		if (fEventCount == 0)
221a63809d3SIngo Weinhold 			return true;
222a63809d3SIngo Weinhold 
223a63809d3SIngo Weinhold 		fEvents = new(std::nothrow) system_profiler_event_header*[fEventCount];
224a63809d3SIngo Weinhold 		if (fEvents == NULL)
225a63809d3SIngo Weinhold 			return false;
226a63809d3SIngo Weinhold 
227a63809d3SIngo Weinhold 		return true;
228a63809d3SIngo Weinhold 	}
229a63809d3SIngo Weinhold 
AddIORequestModelLoader::ExtendedThreadSchedulingState230c2354448SIngo Weinhold 	void AddIORequest(IORequest* request)
231c2354448SIngo Weinhold 	{
232c2354448SIngo Weinhold 		fPendingIORequests.Add(request);
233c2354448SIngo Weinhold 	}
234c2354448SIngo Weinhold 
IORequestFinishedModelLoader::ExtendedThreadSchedulingState235c2354448SIngo Weinhold 	void IORequestFinished(IORequest* request)
236c2354448SIngo Weinhold 	{
237c2354448SIngo Weinhold 		fPendingIORequests.Remove(request);
238c2354448SIngo Weinhold 		fIORequests.Add(request);
239c2354448SIngo Weinhold 	}
240c2354448SIngo Weinhold 
PrepareThreadIORequestsModelLoader::ExtendedThreadSchedulingState241c2354448SIngo Weinhold 	bool PrepareThreadIORequests(Model::IORequest**& _requests,
242c2354448SIngo Weinhold 		size_t& _requestCount)
243c2354448SIngo Weinhold 	{
244c2354448SIngo Weinhold 		fIORequests.MoveFrom(&fPendingIORequests);
245c2354448SIngo Weinhold 		size_t requestCount = fIORequests.Count();
246c2354448SIngo Weinhold 
247c2354448SIngo Weinhold 		if (requestCount == 0) {
248c2354448SIngo Weinhold 			_requests = NULL;
249c2354448SIngo Weinhold 			_requestCount = 0;
250c2354448SIngo Weinhold 			return true;
251c2354448SIngo Weinhold 		}
252c2354448SIngo Weinhold 
253c2354448SIngo Weinhold 		Model::IORequest** requests
254c2354448SIngo Weinhold 			= new(std::nothrow) Model::IORequest*[requestCount];
255c2354448SIngo Weinhold 		if (requests == NULL)
256c2354448SIngo Weinhold 			return false;
257c2354448SIngo Weinhold 
258c2354448SIngo Weinhold 		size_t index = 0;
259c2354448SIngo Weinhold 		while (IORequest* request = fIORequests.RemoveHead()) {
260c2354448SIngo Weinhold 			ObjectDeleter<IORequest> requestDeleter(request);
261c2354448SIngo Weinhold 
262c2354448SIngo Weinhold 			Model::IORequest* modelRequest = request->CreateModelRequest();
263c2354448SIngo Weinhold 			if (modelRequest == NULL) {
264c2354448SIngo Weinhold 				for (size_t i = 0; i < index; i++)
265c2354448SIngo Weinhold 					requests[i]->Delete();
266*c199c568SAugustin Cavalier 				delete[] requests;
267c2354448SIngo Weinhold 				return false;
268c2354448SIngo Weinhold 			}
269c2354448SIngo Weinhold 
270c2354448SIngo Weinhold 			requests[index++] = modelRequest;
271c2354448SIngo Weinhold 		}
272c2354448SIngo Weinhold 
273c2354448SIngo Weinhold 		_requests = requests;
274c2354448SIngo Weinhold 		_requestCount = requestCount;
275c2354448SIngo Weinhold 		return true;
276c2354448SIngo Weinhold 	}
277c2354448SIngo Weinhold 
278a63809d3SIngo Weinhold private:
279a63809d3SIngo Weinhold 	system_profiler_event_header**	fEvents;
280a63809d3SIngo Weinhold 	size_t							fEventIndex;
281a63809d3SIngo Weinhold 	size_t							fEventCount;
282c2354448SIngo Weinhold 	IORequestList					fIORequests;
283c2354448SIngo Weinhold 	IORequestList					fPendingIORequests;
284a63809d3SIngo Weinhold };
285a63809d3SIngo Weinhold 
286a63809d3SIngo Weinhold 
287a63809d3SIngo Weinhold // #pragma mark - ExtendedSchedulingState
288a63809d3SIngo Weinhold 
289a63809d3SIngo Weinhold 
290a63809d3SIngo Weinhold struct ModelLoader::ExtendedSchedulingState : Model::SchedulingState {
LookupThreadModelLoader::ExtendedSchedulingState291a63809d3SIngo Weinhold 	inline ExtendedThreadSchedulingState* LookupThread(thread_id threadID) const
292a63809d3SIngo Weinhold 	{
293a63809d3SIngo Weinhold 		Model::ThreadSchedulingState* thread
294a63809d3SIngo Weinhold 			= Model::SchedulingState::LookupThread(threadID);
295a63809d3SIngo Weinhold 		return thread != NULL
296a63809d3SIngo Weinhold 			? static_cast<ExtendedThreadSchedulingState*>(thread) : NULL;
297a63809d3SIngo Weinhold 	}
298a63809d3SIngo Weinhold 
299a63809d3SIngo Weinhold 
300a63809d3SIngo Weinhold protected:
DeleteThreadModelLoader::ExtendedSchedulingState301a63809d3SIngo Weinhold 	virtual void DeleteThread(Model::ThreadSchedulingState* thread)
302a63809d3SIngo Weinhold 	{
303a63809d3SIngo Weinhold 		delete static_cast<ExtendedThreadSchedulingState*>(thread);
304a63809d3SIngo Weinhold 	}
305a63809d3SIngo Weinhold };
306a63809d3SIngo Weinhold 
307a63809d3SIngo Weinhold 
308a63809d3SIngo Weinhold // #pragma mark - ModelLoader
30937ea7254SIngo Weinhold 
31037ea7254SIngo Weinhold 
31137ea7254SIngo Weinhold inline void
_UpdateLastEventTime(nanotime_t time)312d8d4b902SIngo Weinhold ModelLoader::_UpdateLastEventTime(nanotime_t time)
31337ea7254SIngo Weinhold {
31431391fedSIngo Weinhold 	if (fBaseTime < 0) {
31537ea7254SIngo Weinhold 		fBaseTime = time;
31631391fedSIngo Weinhold 		fModel->SetBaseTime(time);
31731391fedSIngo Weinhold 	}
31837ea7254SIngo Weinhold 
319a63809d3SIngo Weinhold 	fState->SetLastEventTime(time - fBaseTime);
32037ea7254SIngo Weinhold }
32137ea7254SIngo Weinhold 
32237ea7254SIngo Weinhold 
ModelLoader(DataSource * dataSource,const BMessenger & target,void * targetCookie)32337ea7254SIngo Weinhold ModelLoader::ModelLoader(DataSource* dataSource,
32437ea7254SIngo Weinhold 	const BMessenger& target, void* targetCookie)
32537ea7254SIngo Weinhold 	:
32664d5660eSIngo Weinhold 	AbstractModelLoader(target, targetCookie),
32737ea7254SIngo Weinhold 	fModel(NULL),
328bea40bcdSIngo Weinhold 	fDataSource(dataSource),
329c2354448SIngo Weinhold 	fCPUInfos(NULL),
330c2354448SIngo Weinhold 	fState(NULL),
331c2354448SIngo Weinhold 	fIORequests(NULL)
33237ea7254SIngo Weinhold {
33337ea7254SIngo Weinhold }
33437ea7254SIngo Weinhold 
33537ea7254SIngo Weinhold 
~ModelLoader()33637ea7254SIngo Weinhold ModelLoader::~ModelLoader()
33737ea7254SIngo Weinhold {
338bea40bcdSIngo Weinhold 	delete[] fCPUInfos;
33937ea7254SIngo Weinhold 	delete fDataSource;
34037ea7254SIngo Weinhold 	delete fModel;
341c2354448SIngo Weinhold 	delete fState;
342c2354448SIngo Weinhold 	delete fIORequests;
34337ea7254SIngo Weinhold }
34437ea7254SIngo Weinhold 
34537ea7254SIngo Weinhold 
34637ea7254SIngo Weinhold Model*
DetachModel()34737ea7254SIngo Weinhold ModelLoader::DetachModel()
34837ea7254SIngo Weinhold {
34937ea7254SIngo Weinhold 	AutoLocker<BLocker> locker(fLock);
35037ea7254SIngo Weinhold 
35137ea7254SIngo Weinhold 	if (fModel == NULL || fLoading)
35237ea7254SIngo Weinhold 		return NULL;
35337ea7254SIngo Weinhold 
35437ea7254SIngo Weinhold 	Model* model = fModel;
35537ea7254SIngo Weinhold 	fModel = NULL;
35637ea7254SIngo Weinhold 
35737ea7254SIngo Weinhold 	return model;
35837ea7254SIngo Weinhold }
35937ea7254SIngo Weinhold 
36037ea7254SIngo Weinhold 
36164d5660eSIngo Weinhold status_t
PrepareForLoading()36264d5660eSIngo Weinhold ModelLoader::PrepareForLoading()
36337ea7254SIngo Weinhold {
36464d5660eSIngo Weinhold 	if (fModel != NULL || fDataSource == NULL)
36564d5660eSIngo Weinhold 		return B_BAD_VALUE;
36664d5660eSIngo Weinhold 
367a63809d3SIngo Weinhold 	// create and init the state
368a63809d3SIngo Weinhold 	fState = new(std::nothrow) ExtendedSchedulingState;
369a63809d3SIngo Weinhold 	if (fState == NULL)
370a63809d3SIngo Weinhold 		return B_NO_MEMORY;
371a63809d3SIngo Weinhold 
372a63809d3SIngo Weinhold 	status_t error = fState->Init();
37364d5660eSIngo Weinhold 	if (error != B_OK)
37464d5660eSIngo Weinhold 		return error;
37564d5660eSIngo Weinhold 
376c2354448SIngo Weinhold 	// create CPU info array
377bea40bcdSIngo Weinhold 	fCPUInfos = new(std::nothrow) CPUInfo[kMaxCPUCount];
378bea40bcdSIngo Weinhold 	if (fCPUInfos == NULL)
379bea40bcdSIngo Weinhold 		return B_NO_MEMORY;
380bea40bcdSIngo Weinhold 
381c2354448SIngo Weinhold 	// create IORequest hash table
382c2354448SIngo Weinhold 	fIORequests = new(std::nothrow) IORequestTable;
383c2354448SIngo Weinhold 	if (fIORequests == NULL || fIORequests->Init() != B_OK)
384c2354448SIngo Weinhold 		return B_NO_MEMORY;
385c2354448SIngo Weinhold 
38664d5660eSIngo Weinhold 	return B_OK;
38737ea7254SIngo Weinhold }
38837ea7254SIngo Weinhold 
38937ea7254SIngo Weinhold 
39037ea7254SIngo Weinhold status_t
Load()39164d5660eSIngo Weinhold ModelLoader::Load()
39237ea7254SIngo Weinhold {
39337ea7254SIngo Weinhold 	try {
39464d5660eSIngo Weinhold 		return _Load();
39537ea7254SIngo Weinhold 	} catch(...) {
39664d5660eSIngo Weinhold 		return B_ERROR;
39764d5660eSIngo Weinhold 	}
39837ea7254SIngo Weinhold }
39937ea7254SIngo Weinhold 
40037ea7254SIngo Weinhold 
40164d5660eSIngo Weinhold void
FinishLoading(bool success)40264d5660eSIngo Weinhold ModelLoader::FinishLoading(bool success)
40364d5660eSIngo Weinhold {
404a63809d3SIngo Weinhold 	delete fState;
405a63809d3SIngo Weinhold 	fState = NULL;
40637ea7254SIngo Weinhold 
40764d5660eSIngo Weinhold 	if (!success) {
40837ea7254SIngo Weinhold 		delete fModel;
40937ea7254SIngo Weinhold 		fModel = NULL;
41037ea7254SIngo Weinhold 	}
411bea40bcdSIngo Weinhold 
412bea40bcdSIngo Weinhold 	delete[] fCPUInfos;
413bea40bcdSIngo Weinhold 	fCPUInfos = NULL;
414c2354448SIngo Weinhold 
415c2354448SIngo Weinhold 	delete fIORequests;
416c2354448SIngo Weinhold 	fIORequests = NULL;
417c2354448SIngo Weinhold }
41837ea7254SIngo Weinhold 
41937ea7254SIngo Weinhold 
42037ea7254SIngo Weinhold status_t
_Load()42137ea7254SIngo Weinhold ModelLoader::_Load()
42237ea7254SIngo Weinhold {
42337ea7254SIngo Weinhold 	// read the complete data into memory
42437ea7254SIngo Weinhold 	void* eventData;
42537ea7254SIngo Weinhold 	size_t eventDataSize;
42637ea7254SIngo Weinhold 	status_t error = _ReadDebugEvents(&eventData, &eventDataSize);
42737ea7254SIngo Weinhold 	if (error != B_OK)
42837ea7254SIngo Weinhold 		return error;
4296d5e661dSIngo Weinhold 	MemoryDeleter eventDataDeleter(eventData);
4306d5e661dSIngo Weinhold 
4316d5e661dSIngo Weinhold 	// create a debug event array
4326d5e661dSIngo Weinhold 	system_profiler_event_header** events;
4336d5e661dSIngo Weinhold 	size_t eventCount;
4346d5e661dSIngo Weinhold 	error = _CreateDebugEventArray(eventData, eventDataSize, events,
4356d5e661dSIngo Weinhold 		eventCount);
4366d5e661dSIngo Weinhold 	if (error != B_OK)
4376d5e661dSIngo Weinhold 		return error;
4386d5e661dSIngo Weinhold 	ArrayDeleter<system_profiler_event_header*> eventsDeleter(events);
43937ea7254SIngo Weinhold 
44031391fedSIngo Weinhold 	// get the data source name
44131391fedSIngo Weinhold 	BString dataSourceName;
44231391fedSIngo Weinhold 	fDataSource->GetName(dataSourceName);
44331391fedSIngo Weinhold 
44437ea7254SIngo Weinhold 	// create a model
44531391fedSIngo Weinhold 	fModel = new(std::nothrow) Model(dataSourceName.String(), eventData,
4466d5e661dSIngo Weinhold 		eventDataSize, events, eventCount);
4476d5e661dSIngo Weinhold 	if (fModel == NULL)
44837ea7254SIngo Weinhold 		return B_NO_MEMORY;
4496d5e661dSIngo Weinhold 	eventDataDeleter.Detach();
4506d5e661dSIngo Weinhold 	eventsDeleter.Detach();
45137ea7254SIngo Weinhold 
45237ea7254SIngo Weinhold 	// create a debug input stream
4536d5e661dSIngo Weinhold 	BDebugEventInputStream input;
4546d5e661dSIngo Weinhold 	error = input.SetTo(eventData, eventDataSize, false);
45537ea7254SIngo Weinhold 	if (error != B_OK)
45637ea7254SIngo Weinhold 		return error;
45737ea7254SIngo Weinhold 
45837ea7254SIngo Weinhold 	// add the snooze and signal wait objects to the model
45937ea7254SIngo Weinhold 	if (fModel->AddWaitObject(&kSnoozeWaitObjectInfo, NULL) == NULL
46037ea7254SIngo Weinhold 		|| fModel->AddWaitObject(&kSignalWaitObjectInfo, NULL) == NULL) {
46137ea7254SIngo Weinhold 		return B_NO_MEMORY;
46237ea7254SIngo Weinhold 	}
46337ea7254SIngo Weinhold 
46437ea7254SIngo Weinhold 	// process the events
465bea40bcdSIngo Weinhold 	fMaxCPUIndex = 0;
466a63809d3SIngo Weinhold 	fState->Clear();
46737ea7254SIngo Weinhold 	fBaseTime = -1;
468d4d63490SIngo Weinhold 	uint64 count = 0;
46937ea7254SIngo Weinhold 
47037ea7254SIngo Weinhold 	while (true) {
47137ea7254SIngo Weinhold 		// get next event
47237ea7254SIngo Weinhold 		uint32 event;
47337ea7254SIngo Weinhold 		uint32 cpu;
47437ea7254SIngo Weinhold 		const void* buffer;
475d4d63490SIngo Weinhold 		off_t offset;
4766d5e661dSIngo Weinhold 		ssize_t bufferSize = input.ReadNextEvent(&event, &cpu, &buffer,
477d4d63490SIngo Weinhold 			&offset);
47837ea7254SIngo Weinhold 		if (bufferSize < 0)
47937ea7254SIngo Weinhold 			return bufferSize;
48037ea7254SIngo Weinhold 		if (buffer == NULL)
48131391fedSIngo Weinhold 			break;
48237ea7254SIngo Weinhold 
48337ea7254SIngo Weinhold 		// process the event
48437ea7254SIngo Weinhold 		status_t error = _ProcessEvent(event, cpu, buffer, bufferSize);
48537ea7254SIngo Weinhold 		if (error != B_OK)
48637ea7254SIngo Weinhold 			return error;
48737ea7254SIngo Weinhold 
488bea40bcdSIngo Weinhold 		if (cpu > fMaxCPUIndex) {
489bea40bcdSIngo Weinhold 			if (cpu + 1 > kMaxCPUCount)
490bea40bcdSIngo Weinhold 				return B_BAD_DATA;
491bea40bcdSIngo Weinhold 			fMaxCPUIndex = cpu;
492bea40bcdSIngo Weinhold 		}
493bea40bcdSIngo Weinhold 
49437ea7254SIngo Weinhold 		// periodically check whether we're supposed to abort
49537ea7254SIngo Weinhold 		if (++count % 32 == 0) {
49637ea7254SIngo Weinhold 			AutoLocker<BLocker> locker(fLock);
49737ea7254SIngo Weinhold 			if (fAborted)
49837ea7254SIngo Weinhold 				return B_ERROR;
49937ea7254SIngo Weinhold 		}
500d4d63490SIngo Weinhold 
501d4d63490SIngo Weinhold 		// periodically add scheduling snapshots
502d4d63490SIngo Weinhold 		if (count % kSchedulingSnapshotInterval == 0)
503a63809d3SIngo Weinhold 			fModel->AddSchedulingStateSnapshot(*fState, offset);
50437ea7254SIngo Weinhold 	}
50531391fedSIngo Weinhold 
506bea40bcdSIngo Weinhold 	if (!fModel->SetCPUCount(fMaxCPUIndex + 1))
507bea40bcdSIngo Weinhold 		return B_NO_MEMORY;
508bea40bcdSIngo Weinhold 
509bea40bcdSIngo Weinhold 	for (uint32 i = 0; i <= fMaxCPUIndex; i++)
510bea40bcdSIngo Weinhold 		fModel->CPUAt(i)->SetIdleTime(fCPUInfos[i].idleTime);
511bea40bcdSIngo Weinhold 
512a63809d3SIngo Weinhold 	fModel->SetLastEventTime(fState->LastEventTime());
513a63809d3SIngo Weinhold 
514c2354448SIngo Weinhold 	if (!_SetThreadEvents() || !_SetThreadIORequests())
515a63809d3SIngo Weinhold 		return B_NO_MEMORY;
516a63809d3SIngo Weinhold 
517d4d63490SIngo Weinhold 	fModel->LoadingFinished();
51831391fedSIngo Weinhold 
51931391fedSIngo Weinhold 	return B_OK;
52037ea7254SIngo Weinhold }
52137ea7254SIngo Weinhold 
52237ea7254SIngo Weinhold 
52337ea7254SIngo Weinhold status_t
_ReadDebugEvents(void ** _eventData,size_t * _size)52437ea7254SIngo Weinhold ModelLoader::_ReadDebugEvents(void** _eventData, size_t* _size)
52537ea7254SIngo Weinhold {
52637ea7254SIngo Weinhold 	// get a BDataIO from the data source
52737ea7254SIngo Weinhold 	BDataIO* io;
52837ea7254SIngo Weinhold 	status_t error = fDataSource->CreateDataIO(&io);
52937ea7254SIngo Weinhold 	if (error != B_OK)
53037ea7254SIngo Weinhold 		return error;
53137ea7254SIngo Weinhold 	ObjectDeleter<BDataIO> dataIOtDeleter(io);
53237ea7254SIngo Weinhold 
53337ea7254SIngo Weinhold 	// First we need to find out how large a buffer to allocate.
53437ea7254SIngo Weinhold 	size_t size;
53537ea7254SIngo Weinhold 
53637ea7254SIngo Weinhold 	if (BPositionIO* positionIO = dynamic_cast<BPositionIO*>(io)) {
53737ea7254SIngo Weinhold 		// it's a BPositionIO -- this makes things easier, since we know how
53837ea7254SIngo Weinhold 		// many bytes to read
53937ea7254SIngo Weinhold 		off_t currentPos = positionIO->Position();
54037ea7254SIngo Weinhold 		if (currentPos < 0)
54137ea7254SIngo Weinhold 			return currentPos;
54237ea7254SIngo Weinhold 
54337ea7254SIngo Weinhold 		off_t fileSize;
54437ea7254SIngo Weinhold 		error = positionIO->GetSize(&fileSize);
54537ea7254SIngo Weinhold 		if (error != B_OK)
54637ea7254SIngo Weinhold 			return error;
54737ea7254SIngo Weinhold 
54837ea7254SIngo Weinhold 		size = fileSize - currentPos;
54937ea7254SIngo Weinhold 	} else {
55037ea7254SIngo Weinhold 		// no BPositionIO -- we need to determine the total size by iteratively
55137ea7254SIngo Weinhold 		// reading the whole data one time
55237ea7254SIngo Weinhold 
55337ea7254SIngo Weinhold 		// allocate a dummy buffer for reading
55437ea7254SIngo Weinhold 		const size_t kBufferSize = 1024 * 1024;
55537ea7254SIngo Weinhold 		void* buffer = malloc(kBufferSize);
55637ea7254SIngo Weinhold 		if (buffer == NULL)
55737ea7254SIngo Weinhold 			return B_NO_MEMORY;
55837ea7254SIngo Weinhold 		MemoryDeleter bufferDeleter(buffer);
55937ea7254SIngo Weinhold 
56037ea7254SIngo Weinhold 		size = 0;
56137ea7254SIngo Weinhold 		while (true) {
56237ea7254SIngo Weinhold 			ssize_t bytesRead = io->Read(buffer, kBufferSize);
56337ea7254SIngo Weinhold 			if (bytesRead < 0)
56437ea7254SIngo Weinhold 				return bytesRead;
56537ea7254SIngo Weinhold 			if (bytesRead == 0)
56637ea7254SIngo Weinhold 				break;
56737ea7254SIngo Weinhold 
56837ea7254SIngo Weinhold 			size += bytesRead;
56937ea7254SIngo Weinhold 		}
57037ea7254SIngo Weinhold 
57137ea7254SIngo Weinhold 		// we've got the size -- recreate the BDataIO
57237ea7254SIngo Weinhold 		dataIOtDeleter.Delete();
57337ea7254SIngo Weinhold 		error = fDataSource->CreateDataIO(&io);
57437ea7254SIngo Weinhold 		if (error != B_OK)
57537ea7254SIngo Weinhold 			return error;
57637ea7254SIngo Weinhold 		dataIOtDeleter.SetTo(io);
57737ea7254SIngo Weinhold 	}
57837ea7254SIngo Weinhold 
57937ea7254SIngo Weinhold 	// allocate the data buffer
58037ea7254SIngo Weinhold 	void* data = malloc(size);
58137ea7254SIngo Weinhold 	if (data == NULL)
58237ea7254SIngo Weinhold 		return B_NO_MEMORY;
58337ea7254SIngo Weinhold 	MemoryDeleter dataDeleter(data);
58437ea7254SIngo Weinhold 
58537ea7254SIngo Weinhold 	// read the data
58637ea7254SIngo Weinhold 	ssize_t bytesRead = io->Read(data, size);
58737ea7254SIngo Weinhold 	if (bytesRead < 0)
58837ea7254SIngo Weinhold 		return bytesRead;
58937ea7254SIngo Weinhold 	if ((size_t)bytesRead != size)
59037ea7254SIngo Weinhold 		return B_FILE_ERROR;
59137ea7254SIngo Weinhold 
59237ea7254SIngo Weinhold 	dataDeleter.Detach();
59337ea7254SIngo Weinhold 	*_eventData = data;
59437ea7254SIngo Weinhold 	*_size = size;
59537ea7254SIngo Weinhold 	return B_OK;
59637ea7254SIngo Weinhold }
59737ea7254SIngo Weinhold 
59837ea7254SIngo Weinhold 
59937ea7254SIngo Weinhold status_t
_CreateDebugEventArray(void * eventData,size_t eventDataSize,system_profiler_event_header ** & _events,size_t & _eventCount)6006d5e661dSIngo Weinhold ModelLoader::_CreateDebugEventArray(void* eventData, size_t eventDataSize,
6016d5e661dSIngo Weinhold 	system_profiler_event_header**& _events, size_t& _eventCount)
6026d5e661dSIngo Weinhold {
6036d5e661dSIngo Weinhold 	// count the events
6046d5e661dSIngo Weinhold 	BDebugEventInputStream input;
6056d5e661dSIngo Weinhold 	status_t error = input.SetTo(eventData, eventDataSize, false);
6066d5e661dSIngo Weinhold 	if (error != B_OK)
6076d5e661dSIngo Weinhold 		return error;
6086d5e661dSIngo Weinhold 
6096d5e661dSIngo Weinhold 	size_t eventCount = 0;
6106d5e661dSIngo Weinhold 	while (true) {
6116d5e661dSIngo Weinhold 		// get next event
6126d5e661dSIngo Weinhold 		uint32 event;
6136d5e661dSIngo Weinhold 		uint32 cpu;
6146d5e661dSIngo Weinhold 		const void* buffer;
6156d5e661dSIngo Weinhold 		ssize_t bufferSize = input.ReadNextEvent(&event, &cpu, &buffer, NULL);
6166d5e661dSIngo Weinhold 		if (bufferSize < 0)
6176d5e661dSIngo Weinhold 			return bufferSize;
6186d5e661dSIngo Weinhold 		if (buffer == NULL)
6196d5e661dSIngo Weinhold 			break;
6206d5e661dSIngo Weinhold 
6216d5e661dSIngo Weinhold 		eventCount++;
6226d5e661dSIngo Weinhold 	}
6236d5e661dSIngo Weinhold 
6246d5e661dSIngo Weinhold 	// create the array
6256d5e661dSIngo Weinhold 	system_profiler_event_header** events = new(std::nothrow)
6266d5e661dSIngo Weinhold 		system_profiler_event_header*[eventCount];
6276d5e661dSIngo Weinhold 	if (events == NULL)
6286d5e661dSIngo Weinhold 		return B_NO_MEMORY;
6296d5e661dSIngo Weinhold 
6306d5e661dSIngo Weinhold 	// populate the array
6316d5e661dSIngo Weinhold 	error = input.SetTo(eventData, eventDataSize, false);
6326d5e661dSIngo Weinhold 	if (error != B_OK) {
6336d5e661dSIngo Weinhold 		delete[] events;
6346d5e661dSIngo Weinhold 		return error;
6356d5e661dSIngo Weinhold 	}
6366d5e661dSIngo Weinhold 
6376d5e661dSIngo Weinhold 	size_t eventIndex = 0;
6386d5e661dSIngo Weinhold 	while (true) {
6396d5e661dSIngo Weinhold 		// get next event
6406d5e661dSIngo Weinhold 		uint32 event;
6416d5e661dSIngo Weinhold 		uint32 cpu;
6426d5e661dSIngo Weinhold 		const void* buffer;
6436d5e661dSIngo Weinhold 		off_t offset;
6446d5e661dSIngo Weinhold 		input.ReadNextEvent(&event, &cpu, &buffer, &offset);
6456d5e661dSIngo Weinhold 		if (buffer == NULL)
6466d5e661dSIngo Weinhold 			break;
6476d5e661dSIngo Weinhold 
6486d5e661dSIngo Weinhold 		events[eventIndex++]
6496d5e661dSIngo Weinhold 			= (system_profiler_event_header*)((uint8*)eventData + offset);
6506d5e661dSIngo Weinhold 	}
6516d5e661dSIngo Weinhold 
6526d5e661dSIngo Weinhold 	_events = events;
6536d5e661dSIngo Weinhold 	_eventCount = eventCount;
6546d5e661dSIngo Weinhold 	return B_OK;
6556d5e661dSIngo Weinhold }
6566d5e661dSIngo Weinhold 
6576d5e661dSIngo Weinhold 
6586d5e661dSIngo Weinhold status_t
_ProcessEvent(uint32 event,uint32 cpu,const void * buffer,size_t size)65937ea7254SIngo Weinhold ModelLoader::_ProcessEvent(uint32 event, uint32 cpu, const void* buffer,
66037ea7254SIngo Weinhold 	size_t size)
66137ea7254SIngo Weinhold {
66237ea7254SIngo Weinhold 	switch (event) {
66337ea7254SIngo Weinhold 		case B_SYSTEM_PROFILER_TEAM_ADDED:
66437ea7254SIngo Weinhold 			_HandleTeamAdded((system_profiler_team_added*)buffer);
66537ea7254SIngo Weinhold 			break;
66637ea7254SIngo Weinhold 
66737ea7254SIngo Weinhold 		case B_SYSTEM_PROFILER_TEAM_REMOVED:
66837ea7254SIngo Weinhold 			_HandleTeamRemoved((system_profiler_team_removed*)buffer);
66937ea7254SIngo Weinhold 			break;
67037ea7254SIngo Weinhold 
67137ea7254SIngo Weinhold 		case B_SYSTEM_PROFILER_TEAM_EXEC:
67237ea7254SIngo Weinhold 			_HandleTeamExec((system_profiler_team_exec*)buffer);
67337ea7254SIngo Weinhold 			break;
67437ea7254SIngo Weinhold 
67537ea7254SIngo Weinhold 		case B_SYSTEM_PROFILER_THREAD_ADDED:
67637ea7254SIngo Weinhold 			_HandleThreadAdded((system_profiler_thread_added*)buffer);
67737ea7254SIngo Weinhold 			break;
67837ea7254SIngo Weinhold 
67937ea7254SIngo Weinhold 		case B_SYSTEM_PROFILER_THREAD_REMOVED:
68037ea7254SIngo Weinhold 			_HandleThreadRemoved((system_profiler_thread_removed*)buffer);
68137ea7254SIngo Weinhold 			break;
68237ea7254SIngo Weinhold 
68337ea7254SIngo Weinhold 		case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
684bea40bcdSIngo Weinhold 			_HandleThreadScheduled(cpu,
685bea40bcdSIngo Weinhold 				(system_profiler_thread_scheduled*)buffer);
68637ea7254SIngo Weinhold 			break;
68737ea7254SIngo Weinhold 
68837ea7254SIngo Weinhold 		case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE:
68937ea7254SIngo Weinhold 			_HandleThreadEnqueuedInRunQueue(
69037ea7254SIngo Weinhold 				(thread_enqueued_in_run_queue*)buffer);
69137ea7254SIngo Weinhold 			break;
69237ea7254SIngo Weinhold 
69337ea7254SIngo Weinhold 		case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE:
694bea40bcdSIngo Weinhold 			_HandleThreadRemovedFromRunQueue(cpu,
69537ea7254SIngo Weinhold 				(thread_removed_from_run_queue*)buffer);
69637ea7254SIngo Weinhold 			break;
69737ea7254SIngo Weinhold 
69837ea7254SIngo Weinhold 		case B_SYSTEM_PROFILER_WAIT_OBJECT_INFO:
69937ea7254SIngo Weinhold 			_HandleWaitObjectInfo((system_profiler_wait_object_info*)buffer);
70037ea7254SIngo Weinhold 			break;
70137ea7254SIngo Weinhold 
70283f19b67SIngo Weinhold 		case B_SYSTEM_PROFILER_IO_SCHEDULER_ADDED:
703934a8d01SIngo Weinhold 			_HandleIOSchedulerAdded(
704934a8d01SIngo Weinhold 				(system_profiler_io_scheduler_added*)buffer);
705934a8d01SIngo Weinhold 			break;
706934a8d01SIngo Weinhold 
70783f19b67SIngo Weinhold 		case B_SYSTEM_PROFILER_IO_SCHEDULER_REMOVED:
708934a8d01SIngo Weinhold 			// not so interesting
709c2354448SIngo Weinhold 			break;
710c2354448SIngo Weinhold 
71183f19b67SIngo Weinhold 		case B_SYSTEM_PROFILER_IO_REQUEST_SCHEDULED:
712c2354448SIngo Weinhold 			_HandleIORequestScheduled((io_request_scheduled*)buffer);
713c2354448SIngo Weinhold 			break;
71483f19b67SIngo Weinhold 		case B_SYSTEM_PROFILER_IO_REQUEST_FINISHED:
715c2354448SIngo Weinhold 			_HandleIORequestFinished((io_request_finished*)buffer);
716c2354448SIngo Weinhold 			break;
71783f19b67SIngo Weinhold 		case B_SYSTEM_PROFILER_IO_OPERATION_STARTED:
718c2354448SIngo Weinhold 			_HandleIOOperationStarted((io_operation_started*)buffer);
719c2354448SIngo Weinhold 			break;
72083f19b67SIngo Weinhold 		case B_SYSTEM_PROFILER_IO_OPERATION_FINISHED:
721c2354448SIngo Weinhold 			_HandleIOOperationFinished((io_operation_finished*)buffer);
72283f19b67SIngo Weinhold 			break;
72383f19b67SIngo Weinhold 
72437ea7254SIngo Weinhold 		default:
725883b3e1dSMichael Lotz 			printf("unsupported event type %" B_PRIu32 ", size: %" B_PRIuSIZE
726883b3e1dSMichael Lotz 				"\n", event, size);
72737ea7254SIngo Weinhold 			return B_BAD_DATA;
72837ea7254SIngo Weinhold 	}
72937ea7254SIngo Weinhold 
73037ea7254SIngo Weinhold 	return B_OK;
73137ea7254SIngo Weinhold }
73237ea7254SIngo Weinhold 
73337ea7254SIngo Weinhold 
734a63809d3SIngo Weinhold bool
_SetThreadEvents()735a63809d3SIngo Weinhold ModelLoader::_SetThreadEvents()
736a63809d3SIngo Weinhold {
737a63809d3SIngo Weinhold 	// allocate the threads' events arrays
738a63809d3SIngo Weinhold 	for (int32 i = 0; Model::Thread* thread = fModel->ThreadAt(i); i++) {
739a63809d3SIngo Weinhold 		ExtendedThreadSchedulingState* state
740a63809d3SIngo Weinhold 			= fState->LookupThread(thread->ID());
741a63809d3SIngo Weinhold 		if (!state->AllocateEventArray())
742a63809d3SIngo Weinhold 			return false;
743a63809d3SIngo Weinhold 	}
744a63809d3SIngo Weinhold 
745a63809d3SIngo Weinhold 	// fill the threads' event arrays
746a63809d3SIngo Weinhold 	system_profiler_event_header** events = fModel->Events();
747a63809d3SIngo Weinhold 	size_t eventCount = fModel->CountEvents();
748a63809d3SIngo Weinhold 	for (size_t i = 0; i < eventCount; i++) {
749a63809d3SIngo Weinhold 		system_profiler_event_header* header = events[i];
750a63809d3SIngo Weinhold 		void* buffer = header + 1;
751a63809d3SIngo Weinhold 
752a63809d3SIngo Weinhold 		switch (header->event) {
753a63809d3SIngo Weinhold 			case B_SYSTEM_PROFILER_THREAD_ADDED:
754a63809d3SIngo Weinhold 			{
755a63809d3SIngo Weinhold 				system_profiler_thread_added* event
756a63809d3SIngo Weinhold 					= (system_profiler_thread_added*)buffer;
757a63809d3SIngo Weinhold 				fState->LookupThread(event->thread)->AddEvent(header);
758a63809d3SIngo Weinhold 				break;
759a63809d3SIngo Weinhold 			}
760a63809d3SIngo Weinhold 
761a63809d3SIngo Weinhold 			case B_SYSTEM_PROFILER_THREAD_REMOVED:
762a63809d3SIngo Weinhold 			{
763a63809d3SIngo Weinhold 				system_profiler_thread_removed* event
764a63809d3SIngo Weinhold 					= (system_profiler_thread_removed*)buffer;
765a63809d3SIngo Weinhold 				fState->LookupThread(event->thread)->AddEvent(header);
766a63809d3SIngo Weinhold 				break;
767a63809d3SIngo Weinhold 			}
768a63809d3SIngo Weinhold 
769a63809d3SIngo Weinhold 			case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
770a63809d3SIngo Weinhold 			{
771a63809d3SIngo Weinhold 				system_profiler_thread_scheduled* event
772a63809d3SIngo Weinhold 					= (system_profiler_thread_scheduled*)buffer;
773a63809d3SIngo Weinhold 				fState->LookupThread(event->thread)->AddEvent(header);
774a63809d3SIngo Weinhold 
775a63809d3SIngo Weinhold 				if (event->thread != event->previous_thread) {
776a63809d3SIngo Weinhold 					fState->LookupThread(event->previous_thread)
777a63809d3SIngo Weinhold 						->AddEvent(header);
778a63809d3SIngo Weinhold 				}
779a63809d3SIngo Weinhold 				break;
780a63809d3SIngo Weinhold 			}
781a63809d3SIngo Weinhold 
782a63809d3SIngo Weinhold 			case B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE:
783a63809d3SIngo Weinhold 			{
784a63809d3SIngo Weinhold 				thread_enqueued_in_run_queue* event
785a63809d3SIngo Weinhold 					= (thread_enqueued_in_run_queue*)buffer;
786a63809d3SIngo Weinhold 				fState->LookupThread(event->thread)->AddEvent(header);
787a63809d3SIngo Weinhold 				break;
788a63809d3SIngo Weinhold 			}
789a63809d3SIngo Weinhold 
790a63809d3SIngo Weinhold 			case B_SYSTEM_PROFILER_THREAD_REMOVED_FROM_RUN_QUEUE:
791a63809d3SIngo Weinhold 			{
792a63809d3SIngo Weinhold 				thread_removed_from_run_queue* event
793a63809d3SIngo Weinhold 					= (thread_removed_from_run_queue*)buffer;
794a63809d3SIngo Weinhold 				fState->LookupThread(event->thread)->AddEvent(header);
795a63809d3SIngo Weinhold 				break;
796a63809d3SIngo Weinhold 			}
797a63809d3SIngo Weinhold 
798a63809d3SIngo Weinhold 			default:
799a63809d3SIngo Weinhold 				break;
800a63809d3SIngo Weinhold 		}
801a63809d3SIngo Weinhold 	}
802a63809d3SIngo Weinhold 
803a63809d3SIngo Weinhold 	// transfer the events arrays from the scheduling states to the thread
804a63809d3SIngo Weinhold 	// objects
805a63809d3SIngo Weinhold 	for (int32 i = 0; Model::Thread* thread = fModel->ThreadAt(i); i++) {
806a63809d3SIngo Weinhold 		ExtendedThreadSchedulingState* state
807a63809d3SIngo Weinhold 			= fState->LookupThread(thread->ID());
808a63809d3SIngo Weinhold 		thread->SetEvents(state->Events(), state->CountEvents());
809a63809d3SIngo Weinhold 		state->DetachEvents();
810a63809d3SIngo Weinhold 	}
811a63809d3SIngo Weinhold 
812a63809d3SIngo Weinhold 	return true;
813a63809d3SIngo Weinhold }
814a63809d3SIngo Weinhold 
815a63809d3SIngo Weinhold 
816c2354448SIngo Weinhold bool
_SetThreadIORequests()817c2354448SIngo Weinhold ModelLoader::_SetThreadIORequests()
818c2354448SIngo Weinhold {
819c2354448SIngo Weinhold 	for (int32 i = 0; Model::Thread* thread = fModel->ThreadAt(i); i++) {
820c2354448SIngo Weinhold 		ExtendedThreadSchedulingState* state
821c2354448SIngo Weinhold 			= fState->LookupThread(thread->ID());
822c2354448SIngo Weinhold 		Model::IORequest** requests;
823c2354448SIngo Weinhold 		size_t requestCount;
824c2354448SIngo Weinhold 		if (!state->PrepareThreadIORequests(requests, requestCount))
825c2354448SIngo Weinhold 			return false;
826c2354448SIngo Weinhold 		if (requestCount > 0)
827c2354448SIngo Weinhold 			_SetThreadIORequests(thread, requests, requestCount);
828c2354448SIngo Weinhold 	}
829c2354448SIngo Weinhold 
830c2354448SIngo Weinhold 	return true;
831c2354448SIngo Weinhold }
832c2354448SIngo Weinhold 
833c2354448SIngo Weinhold 
834c2354448SIngo Weinhold void
_SetThreadIORequests(Model::Thread * thread,Model::IORequest ** requests,size_t requestCount)835c2354448SIngo Weinhold ModelLoader::_SetThreadIORequests(Model::Thread* thread,
836c2354448SIngo Weinhold 	Model::IORequest** requests, size_t requestCount)
837c2354448SIngo Weinhold {
838c2354448SIngo Weinhold 	// compute some totals
839c2354448SIngo Weinhold 	int64 ioCount = 0;
840c2354448SIngo Weinhold 	nanotime_t ioTime = 0;
841c2354448SIngo Weinhold 
842c2354448SIngo Weinhold 	// sort requests by scheduler and start time
843c2354448SIngo Weinhold 	std::sort(requests, requests + requestCount,
844c2354448SIngo Weinhold 		Model::IORequest::SchedulerTimeLess);
845c2354448SIngo Weinhold 
846c2354448SIngo Weinhold 	nanotime_t endTime = fBaseTime + fModel->LastEventTime();
847c2354448SIngo Weinhold 
848c2354448SIngo Weinhold 	// compute the summed up I/O times
849c2354448SIngo Weinhold 	nanotime_t ioStart = requests[0]->scheduledEvent->time;
850c2354448SIngo Weinhold 	nanotime_t previousEnd = requests[0]->finishedEvent != NULL
851c2354448SIngo Weinhold 		? requests[0]->finishedEvent->time : endTime;
852c2354448SIngo Weinhold 	int32 scheduler = requests[0]->scheduledEvent->scheduler;
853c2354448SIngo Weinhold 
854c2354448SIngo Weinhold 	for (size_t i = 1; i < requestCount; i++) {
855c2354448SIngo Weinhold 		system_profiler_io_request_scheduled* scheduledEvent
856c2354448SIngo Weinhold 			= requests[i]->scheduledEvent;
857c2354448SIngo Weinhold 		if (scheduledEvent->scheduler != scheduler
858c2354448SIngo Weinhold 			|| scheduledEvent->time >= previousEnd) {
859c2354448SIngo Weinhold 			ioCount++;
860c2354448SIngo Weinhold 			ioTime += previousEnd - ioStart;
861c2354448SIngo Weinhold 			ioStart = scheduledEvent->time;
862c2354448SIngo Weinhold 		}
863c2354448SIngo Weinhold 
864c2354448SIngo Weinhold 		previousEnd = requests[i]->finishedEvent != NULL
865c2354448SIngo Weinhold 			? requests[i]->finishedEvent->time : endTime;
866c2354448SIngo Weinhold 	}
867c2354448SIngo Weinhold 
868c2354448SIngo Weinhold 	ioCount++;
869c2354448SIngo Weinhold 	ioTime += previousEnd - ioStart;
870c2354448SIngo Weinhold 
871934a8d01SIngo Weinhold 	// sort requests by start time
872934a8d01SIngo Weinhold 	std::sort(requests, requests + requestCount, Model::IORequest::TimeLess);
873934a8d01SIngo Weinhold 
874c2354448SIngo Weinhold 	// set the computed values
875c2354448SIngo Weinhold 	thread->SetIORequests(requests, requestCount);
876c2354448SIngo Weinhold 	thread->SetIOs(ioCount, ioTime);
877c2354448SIngo Weinhold }
878c2354448SIngo Weinhold 
879c2354448SIngo Weinhold 
88037ea7254SIngo Weinhold void
_HandleTeamAdded(system_profiler_team_added * event)88137ea7254SIngo Weinhold ModelLoader::_HandleTeamAdded(system_profiler_team_added* event)
88237ea7254SIngo Weinhold {
883a63809d3SIngo Weinhold 	if (fModel->AddTeam(event, fState->LastEventTime()) == NULL)
88437ea7254SIngo Weinhold 		throw std::bad_alloc();
88537ea7254SIngo Weinhold }
88637ea7254SIngo Weinhold 
88737ea7254SIngo Weinhold 
88837ea7254SIngo Weinhold void
_HandleTeamRemoved(system_profiler_team_removed * event)88937ea7254SIngo Weinhold ModelLoader::_HandleTeamRemoved(system_profiler_team_removed* event)
89037ea7254SIngo Weinhold {
89137ea7254SIngo Weinhold 	if (Model::Team* team = fModel->TeamByID(event->team))
892a63809d3SIngo Weinhold 		team->SetDeletionTime(fState->LastEventTime());
893883b3e1dSMichael Lotz 	else {
894883b3e1dSMichael Lotz 		printf("Warning: Removed event for unknown team: %" B_PRId32 "\n",
895883b3e1dSMichael Lotz 			event->team);
896883b3e1dSMichael Lotz 	}
89737ea7254SIngo Weinhold }
89837ea7254SIngo Weinhold 
89937ea7254SIngo Weinhold 
90037ea7254SIngo Weinhold void
_HandleTeamExec(system_profiler_team_exec * event)90137ea7254SIngo Weinhold ModelLoader::_HandleTeamExec(system_profiler_team_exec* event)
90237ea7254SIngo Weinhold {
90337ea7254SIngo Weinhold 	// TODO:...
90437ea7254SIngo Weinhold }
90537ea7254SIngo Weinhold 
90637ea7254SIngo Weinhold 
90737ea7254SIngo Weinhold void
_HandleThreadAdded(system_profiler_thread_added * event)90837ea7254SIngo Weinhold ModelLoader::_HandleThreadAdded(system_profiler_thread_added* event)
90937ea7254SIngo Weinhold {
9105b78a987SIngo Weinhold 	_AddThread(event)->IncrementEventCount();
91137ea7254SIngo Weinhold }
91237ea7254SIngo Weinhold 
91337ea7254SIngo Weinhold 
91437ea7254SIngo Weinhold void
_HandleThreadRemoved(system_profiler_thread_removed * event)91537ea7254SIngo Weinhold ModelLoader::_HandleThreadRemoved(system_profiler_thread_removed* event)
91637ea7254SIngo Weinhold {
917a63809d3SIngo Weinhold 	ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
9185b78a987SIngo Weinhold 	if (thread == NULL) {
919883b3e1dSMichael Lotz 		printf("Warning: Removed event for unknown thread: %" B_PRId32 "\n",
9205b78a987SIngo Weinhold 			event->thread);
9215b78a987SIngo Weinhold 		thread = _AddUnknownThread(event->thread);
9225b78a987SIngo Weinhold 	}
9235b78a987SIngo Weinhold 
924a63809d3SIngo Weinhold 	thread->thread->SetDeletionTime(fState->LastEventTime());
925a63809d3SIngo Weinhold 	thread->IncrementEventCount();
92637ea7254SIngo Weinhold }
92737ea7254SIngo Weinhold 
92837ea7254SIngo Weinhold 
92937ea7254SIngo Weinhold void
_HandleThreadScheduled(uint32 cpu,system_profiler_thread_scheduled * event)930bea40bcdSIngo Weinhold ModelLoader::_HandleThreadScheduled(uint32 cpu,
931bea40bcdSIngo Weinhold 	system_profiler_thread_scheduled* event)
93237ea7254SIngo Weinhold {
93337ea7254SIngo Weinhold 	_UpdateLastEventTime(event->time);
93437ea7254SIngo Weinhold 
935a63809d3SIngo Weinhold 	ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
93637ea7254SIngo Weinhold 	if (thread == NULL) {
937883b3e1dSMichael Lotz 		printf("Warning: Schedule event for unknown thread: %" B_PRId32 "\n",
9385b78a987SIngo Weinhold 			event->thread);
9395b78a987SIngo Weinhold 		thread = _AddUnknownThread(event->thread);
94037ea7254SIngo Weinhold 		return;
94137ea7254SIngo Weinhold 	}
94237ea7254SIngo Weinhold 
943a63809d3SIngo Weinhold 	nanotime_t diffTime = fState->LastEventTime() - thread->lastTime;
94437ea7254SIngo Weinhold 
94537ea7254SIngo Weinhold 	if (thread->state == READY) {
94637ea7254SIngo Weinhold 		// thread scheduled after having been woken up
94737ea7254SIngo Weinhold 		thread->thread->AddLatency(diffTime);
94837ea7254SIngo Weinhold 	} else if (thread->state == PREEMPTED) {
94937ea7254SIngo Weinhold 		// thread scheduled after having been preempted before
95037ea7254SIngo Weinhold 		thread->thread->AddRerun(diffTime);
95137ea7254SIngo Weinhold 	}
95237ea7254SIngo Weinhold 
95337ea7254SIngo Weinhold 	if (thread->state == STILL_RUNNING) {
95437ea7254SIngo Weinhold 		// Thread was running and continues to run.
95537ea7254SIngo Weinhold 		thread->state = RUNNING;
95637ea7254SIngo Weinhold 	}
95737ea7254SIngo Weinhold 
95837ea7254SIngo Weinhold 	if (thread->state != RUNNING) {
959a63809d3SIngo Weinhold 		thread->lastTime = fState->LastEventTime();
96037ea7254SIngo Weinhold 		thread->state = RUNNING;
96137ea7254SIngo Weinhold 	}
96237ea7254SIngo Weinhold 
963a63809d3SIngo Weinhold 	thread->IncrementEventCount();
964a63809d3SIngo Weinhold 
96537ea7254SIngo Weinhold 	// unscheduled thread
96637ea7254SIngo Weinhold 
96737ea7254SIngo Weinhold 	if (event->thread == event->previous_thread)
96837ea7254SIngo Weinhold 		return;
96937ea7254SIngo Weinhold 
970a63809d3SIngo Weinhold 	thread = fState->LookupThread(event->previous_thread);
97137ea7254SIngo Weinhold 	if (thread == NULL) {
972883b3e1dSMichael Lotz 		printf("Warning: Schedule event for unknown previous thread: %" B_PRId32
973883b3e1dSMichael Lotz 			"\n", event->previous_thread);
9745b78a987SIngo Weinhold 		thread = _AddUnknownThread(event->previous_thread);
97537ea7254SIngo Weinhold 	}
97637ea7254SIngo Weinhold 
977a63809d3SIngo Weinhold 	diffTime = fState->LastEventTime() - thread->lastTime;
97837ea7254SIngo Weinhold 
97937ea7254SIngo Weinhold 	if (thread->state == STILL_RUNNING) {
98037ea7254SIngo Weinhold 		// thread preempted
98137ea7254SIngo Weinhold 		thread->thread->AddPreemption(diffTime);
98237ea7254SIngo Weinhold 		thread->thread->AddRun(diffTime);
983bea40bcdSIngo Weinhold 		if (thread->priority == 0)
984bea40bcdSIngo Weinhold 			_AddIdleTime(cpu, diffTime);
98537ea7254SIngo Weinhold 
986a63809d3SIngo Weinhold 		thread->lastTime = fState->LastEventTime();
98737ea7254SIngo Weinhold 		thread->state = PREEMPTED;
98837ea7254SIngo Weinhold 	} else if (thread->state == RUNNING) {
98937ea7254SIngo Weinhold 		// thread starts waiting (it hadn't been added to the run
99037ea7254SIngo Weinhold 		// queue before being unscheduled)
99137ea7254SIngo Weinhold 		thread->thread->AddRun(diffTime);
992bea40bcdSIngo Weinhold 		if (thread->priority == 0)
993bea40bcdSIngo Weinhold 			_AddIdleTime(cpu, diffTime);
99437ea7254SIngo Weinhold 
99537ea7254SIngo Weinhold 		if (event->previous_thread_state == B_THREAD_WAITING) {
99637ea7254SIngo Weinhold 			addr_t waitObject = event->previous_thread_wait_object;
99737ea7254SIngo Weinhold 			switch (event->previous_thread_wait_object_type) {
99837ea7254SIngo Weinhold 				case THREAD_BLOCK_TYPE_SNOOZE:
99937ea7254SIngo Weinhold 				case THREAD_BLOCK_TYPE_SIGNAL:
100037ea7254SIngo Weinhold 					waitObject = 0;
100137ea7254SIngo Weinhold 					break;
100237ea7254SIngo Weinhold 				case THREAD_BLOCK_TYPE_SEMAPHORE:
100337ea7254SIngo Weinhold 				case THREAD_BLOCK_TYPE_CONDITION_VARIABLE:
100437ea7254SIngo Weinhold 				case THREAD_BLOCK_TYPE_MUTEX:
100537ea7254SIngo Weinhold 				case THREAD_BLOCK_TYPE_RW_LOCK:
100637ea7254SIngo Weinhold 				case THREAD_BLOCK_TYPE_OTHER:
1007557f0446SAugustin Cavalier 				case THREAD_BLOCK_TYPE_OTHER_OBJECT:
100837ea7254SIngo Weinhold 				default:
100937ea7254SIngo Weinhold 					break;
101037ea7254SIngo Weinhold 			}
101137ea7254SIngo Weinhold 
101237ea7254SIngo Weinhold 			_AddThreadWaitObject(thread,
101337ea7254SIngo Weinhold 				event->previous_thread_wait_object_type, waitObject);
101437ea7254SIngo Weinhold 		}
101537ea7254SIngo Weinhold 
1016a63809d3SIngo Weinhold 		thread->lastTime = fState->LastEventTime();
101737ea7254SIngo Weinhold 		thread->state = WAITING;
101837ea7254SIngo Weinhold 	} else if (thread->state == UNKNOWN) {
101937ea7254SIngo Weinhold 		uint32 threadState = event->previous_thread_state;
102037ea7254SIngo Weinhold 		if (threadState == B_THREAD_WAITING
102137ea7254SIngo Weinhold 			|| threadState == B_THREAD_SUSPENDED) {
1022a63809d3SIngo Weinhold 			thread->lastTime = fState->LastEventTime();
102337ea7254SIngo Weinhold 			thread->state = WAITING;
102437ea7254SIngo Weinhold 		} else if (threadState == B_THREAD_READY) {
1025a63809d3SIngo Weinhold 			thread->lastTime = fState->LastEventTime();
102637ea7254SIngo Weinhold 			thread->state = PREEMPTED;
102737ea7254SIngo Weinhold 		}
102837ea7254SIngo Weinhold 	}
1029a63809d3SIngo Weinhold 
1030a63809d3SIngo Weinhold 	thread->IncrementEventCount();
103137ea7254SIngo Weinhold }
103237ea7254SIngo Weinhold 
103337ea7254SIngo Weinhold 
103437ea7254SIngo Weinhold void
_HandleThreadEnqueuedInRunQueue(thread_enqueued_in_run_queue * event)103537ea7254SIngo Weinhold ModelLoader::_HandleThreadEnqueuedInRunQueue(
103637ea7254SIngo Weinhold 	thread_enqueued_in_run_queue* event)
103737ea7254SIngo Weinhold {
103837ea7254SIngo Weinhold 	_UpdateLastEventTime(event->time);
103937ea7254SIngo Weinhold 
1040a63809d3SIngo Weinhold 	ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
104137ea7254SIngo Weinhold 	if (thread == NULL) {
1042883b3e1dSMichael Lotz 		printf("Warning: Enqueued in run queue event for unknown thread: %"
1043883b3e1dSMichael Lotz 			B_PRId32 "\n", event->thread);
10445b78a987SIngo Weinhold 		thread = _AddUnknownThread(event->thread);
104537ea7254SIngo Weinhold 	}
104637ea7254SIngo Weinhold 
104737ea7254SIngo Weinhold 	if (thread->state == RUNNING || thread->state == STILL_RUNNING) {
104837ea7254SIngo Weinhold 		// Thread was running and is reentered into the run queue. This
104937ea7254SIngo Weinhold 		// is done by the scheduler, if the thread remains ready.
105037ea7254SIngo Weinhold 		thread->state = STILL_RUNNING;
105137ea7254SIngo Weinhold 	} else {
105237ea7254SIngo Weinhold 		// Thread was waiting and is ready now.
1053a63809d3SIngo Weinhold 		nanotime_t diffTime = fState->LastEventTime() - thread->lastTime;
105437ea7254SIngo Weinhold 		if (thread->waitObject != NULL) {
105537ea7254SIngo Weinhold 			thread->waitObject->AddWait(diffTime);
105637ea7254SIngo Weinhold 			thread->waitObject = NULL;
105737ea7254SIngo Weinhold 			thread->thread->AddWait(diffTime);
105837ea7254SIngo Weinhold 		} else if (thread->state != UNKNOWN)
105937ea7254SIngo Weinhold 			thread->thread->AddUnspecifiedWait(diffTime);
106037ea7254SIngo Weinhold 
1061a63809d3SIngo Weinhold 		thread->lastTime = fState->LastEventTime();
106237ea7254SIngo Weinhold 		thread->state = READY;
106337ea7254SIngo Weinhold 	}
1064bea40bcdSIngo Weinhold 
1065bea40bcdSIngo Weinhold 	thread->priority = event->priority;
1066a63809d3SIngo Weinhold 
1067a63809d3SIngo Weinhold 	thread->IncrementEventCount();
106837ea7254SIngo Weinhold }
106937ea7254SIngo Weinhold 
107037ea7254SIngo Weinhold 
107137ea7254SIngo Weinhold void
_HandleThreadRemovedFromRunQueue(uint32 cpu,thread_removed_from_run_queue * event)1072bea40bcdSIngo Weinhold ModelLoader::_HandleThreadRemovedFromRunQueue(uint32 cpu,
107337ea7254SIngo Weinhold 	thread_removed_from_run_queue* event)
107437ea7254SIngo Weinhold {
107537ea7254SIngo Weinhold 	_UpdateLastEventTime(event->time);
107637ea7254SIngo Weinhold 
1077a63809d3SIngo Weinhold 	ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
107837ea7254SIngo Weinhold 	if (thread == NULL) {
10795b78a987SIngo Weinhold 		printf("Warning: Removed from run queue event for unknown thread: "
1080883b3e1dSMichael Lotz 			"%" B_PRId32 "\n", event->thread);
10815b78a987SIngo Weinhold 		thread = _AddUnknownThread(event->thread);
108237ea7254SIngo Weinhold 	}
108337ea7254SIngo Weinhold 
108437ea7254SIngo Weinhold 	// This really only happens when the thread priority is changed
108537ea7254SIngo Weinhold 	// while the thread is ready.
108637ea7254SIngo Weinhold 
1087a63809d3SIngo Weinhold 	nanotime_t diffTime = fState->LastEventTime() - thread->lastTime;
108837ea7254SIngo Weinhold 	if (thread->state == RUNNING) {
108937ea7254SIngo Weinhold 		// This should never happen.
109037ea7254SIngo Weinhold 		thread->thread->AddRun(diffTime);
1091bea40bcdSIngo Weinhold 		if (thread->priority == 0)
1092bea40bcdSIngo Weinhold 			_AddIdleTime(cpu, diffTime);
109337ea7254SIngo Weinhold 	} else if (thread->state == READY || thread->state == PREEMPTED) {
109437ea7254SIngo Weinhold 		// Not really correct, but the case is rare and we keep it
109537ea7254SIngo Weinhold 		// simple.
109637ea7254SIngo Weinhold 		thread->thread->AddUnspecifiedWait(diffTime);
109737ea7254SIngo Weinhold 	}
109837ea7254SIngo Weinhold 
1099a63809d3SIngo Weinhold 	thread->lastTime = fState->LastEventTime();
110037ea7254SIngo Weinhold 	thread->state = WAITING;
1101a63809d3SIngo Weinhold 
1102a63809d3SIngo Weinhold 	thread->IncrementEventCount();
110337ea7254SIngo Weinhold }
110437ea7254SIngo Weinhold 
110537ea7254SIngo Weinhold 
110637ea7254SIngo Weinhold void
_HandleWaitObjectInfo(system_profiler_wait_object_info * event)110737ea7254SIngo Weinhold ModelLoader::_HandleWaitObjectInfo(system_profiler_wait_object_info* event)
110837ea7254SIngo Weinhold {
110937ea7254SIngo Weinhold 	if (fModel->AddWaitObject(event, NULL) == NULL)
111037ea7254SIngo Weinhold 		throw std::bad_alloc();
111137ea7254SIngo Weinhold }
111237ea7254SIngo Weinhold 
111337ea7254SIngo Weinhold 
1114c2354448SIngo Weinhold void
_HandleIOSchedulerAdded(system_profiler_io_scheduler_added * event)1115934a8d01SIngo Weinhold ModelLoader::_HandleIOSchedulerAdded(system_profiler_io_scheduler_added* event)
1116934a8d01SIngo Weinhold {
1117934a8d01SIngo Weinhold 	Model::IOScheduler* scheduler = fModel->IOSchedulerByID(event->scheduler);
1118934a8d01SIngo Weinhold 	if (scheduler != NULL) {
1119883b3e1dSMichael Lotz 		printf("Warning: Duplicate added event for I/O scheduler %" B_PRId32
1120883b3e1dSMichael Lotz 			"\n", event->scheduler);
1121934a8d01SIngo Weinhold 		return;
1122934a8d01SIngo Weinhold 	}
1123934a8d01SIngo Weinhold 
1124934a8d01SIngo Weinhold 	if (fModel->AddIOScheduler(event) == NULL)
1125934a8d01SIngo Weinhold 		throw std::bad_alloc();
1126934a8d01SIngo Weinhold }
1127934a8d01SIngo Weinhold 
1128934a8d01SIngo Weinhold 
1129934a8d01SIngo Weinhold void
_HandleIORequestScheduled(io_request_scheduled * event)1130c2354448SIngo Weinhold ModelLoader::_HandleIORequestScheduled(io_request_scheduled* event)
1131c2354448SIngo Weinhold {
1132c2354448SIngo Weinhold 	IORequest* request = fIORequests->Lookup(event->request);
1133c2354448SIngo Weinhold 	if (request != NULL) {
11345b78a987SIngo Weinhold 		printf("Warning: Duplicate schedule event for I/O request %p\n",
11355b78a987SIngo Weinhold 			event->request);
1136c2354448SIngo Weinhold 		return;
1137c2354448SIngo Weinhold 	}
1138c2354448SIngo Weinhold 
1139c2354448SIngo Weinhold 	ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
1140c2354448SIngo Weinhold 	if (thread == NULL) {
1141883b3e1dSMichael Lotz 		printf("Warning: I/O request for unknown thread %" B_PRId32 "\n",
1142883b3e1dSMichael Lotz 			event->thread);
11435b78a987SIngo Weinhold 		thread = _AddUnknownThread(event->thread);
1144c2354448SIngo Weinhold 	}
1145c2354448SIngo Weinhold 
1146934a8d01SIngo Weinhold 	if (fModel->IOSchedulerByID(event->scheduler) == NULL) {
1147883b3e1dSMichael Lotz 		printf("Warning: I/O requests for unknown scheduler %" B_PRId32 "\n",
11485b78a987SIngo Weinhold 			event->scheduler);
11495b78a987SIngo Weinhold 		// TODO: Add state for unknown scheduler, as we do for threads.
1150934a8d01SIngo Weinhold 		return;
1151934a8d01SIngo Weinhold 	}
1152934a8d01SIngo Weinhold 
1153c2354448SIngo Weinhold 	request = new(std::nothrow) IORequest(event);
1154c2354448SIngo Weinhold 	if (request == NULL)
1155c2354448SIngo Weinhold 		throw std::bad_alloc();
1156c2354448SIngo Weinhold 
1157c2354448SIngo Weinhold 	fIORequests->Insert(request);
1158c2354448SIngo Weinhold 	thread->AddIORequest(request);
1159c2354448SIngo Weinhold }
1160c2354448SIngo Weinhold 
1161c2354448SIngo Weinhold 
1162c2354448SIngo Weinhold void
_HandleIORequestFinished(io_request_finished * event)1163c2354448SIngo Weinhold ModelLoader::_HandleIORequestFinished(io_request_finished* event)
1164c2354448SIngo Weinhold {
1165c2354448SIngo Weinhold 	IORequest* request = fIORequests->Lookup(event->request);
1166c2354448SIngo Weinhold 	if (request == NULL)
1167c2354448SIngo Weinhold 		return;
1168c2354448SIngo Weinhold 
1169c2354448SIngo Weinhold 	request->finishedEvent = event;
1170c2354448SIngo Weinhold 
1171c2354448SIngo Weinhold 	fIORequests->Remove(request);
1172c2354448SIngo Weinhold 	fState->LookupThread(request->scheduledEvent->thread)
1173c2354448SIngo Weinhold 		->IORequestFinished(request);
1174c2354448SIngo Weinhold }
1175c2354448SIngo Weinhold 
1176c2354448SIngo Weinhold 
1177c2354448SIngo Weinhold void
_HandleIOOperationStarted(io_operation_started * event)1178c2354448SIngo Weinhold ModelLoader::_HandleIOOperationStarted(io_operation_started* event)
1179c2354448SIngo Weinhold {
1180c2354448SIngo Weinhold 	IORequest* request = fIORequests->Lookup(event->request);
1181934a8d01SIngo Weinhold 	if (request == NULL) {
11825b78a987SIngo Weinhold 		printf("Warning: I/O request for operation %p not found\n",
1183934a8d01SIngo Weinhold 			event->operation);
1184c2354448SIngo Weinhold 		return;
1185934a8d01SIngo Weinhold 	}
1186c2354448SIngo Weinhold 
1187c2354448SIngo Weinhold 	IOOperation* operation = new(std::nothrow) IOOperation(event);
1188c2354448SIngo Weinhold 	if (operation == NULL)
1189c2354448SIngo Weinhold 		throw std::bad_alloc();
1190c2354448SIngo Weinhold 
1191c2354448SIngo Weinhold 	request->AddOperation(operation);
1192c2354448SIngo Weinhold }
1193c2354448SIngo Weinhold 
1194c2354448SIngo Weinhold 
1195c2354448SIngo Weinhold void
_HandleIOOperationFinished(io_operation_finished * event)1196c2354448SIngo Weinhold ModelLoader::_HandleIOOperationFinished(io_operation_finished* event)
1197c2354448SIngo Weinhold {
1198c2354448SIngo Weinhold 	IORequest* request = fIORequests->Lookup(event->request);
1199934a8d01SIngo Weinhold 	if (request == NULL) {
12005b78a987SIngo Weinhold 		printf("Warning: I/O request for operation %p not found\n",
12015b78a987SIngo Weinhold 			event->operation);
1202c2354448SIngo Weinhold 		return;
1203934a8d01SIngo Weinhold 	}
1204c2354448SIngo Weinhold 
1205c2354448SIngo Weinhold 	IOOperation* operation = request->FindOperation(event->operation);
1206934a8d01SIngo Weinhold 	if (operation == NULL) {
12075b78a987SIngo Weinhold 		printf("Warning: operation %p not found\n", event->operation);
1208c2354448SIngo Weinhold 		return;
1209934a8d01SIngo Weinhold 	}
1210c2354448SIngo Weinhold 
1211c2354448SIngo Weinhold 	operation->finishedEvent = event;
1212c2354448SIngo Weinhold }
1213c2354448SIngo Weinhold 
1214c2354448SIngo Weinhold 
1215a63809d3SIngo Weinhold ModelLoader::ExtendedThreadSchedulingState*
_AddThread(system_profiler_thread_added * event)121637ea7254SIngo Weinhold ModelLoader::_AddThread(system_profiler_thread_added* event)
121737ea7254SIngo Weinhold {
121837ea7254SIngo Weinhold 	// do we know the thread already?
1219a63809d3SIngo Weinhold 	ExtendedThreadSchedulingState* info = fState->LookupThread(event->thread);
122037ea7254SIngo Weinhold 	if (info != NULL) {
12215b78a987SIngo Weinhold 		printf("Warning: Duplicate thread added event for thread %" B_PRId32
12225b78a987SIngo Weinhold 			"\n", event->thread);
122337ea7254SIngo Weinhold 		return info;
122437ea7254SIngo Weinhold 	}
122537ea7254SIngo Weinhold 
122637ea7254SIngo Weinhold 	// add the thread to the model
1227a63809d3SIngo Weinhold 	Model::Thread* thread = fModel->AddThread(event, fState->LastEventTime());
122837ea7254SIngo Weinhold 	if (thread == NULL)
12295b78a987SIngo Weinhold 		throw std::bad_alloc();
123037ea7254SIngo Weinhold 
1231d4d63490SIngo Weinhold 	// create and add a ThreadSchedulingState
1232a63809d3SIngo Weinhold 	info = new(std::nothrow) ExtendedThreadSchedulingState(thread);
123337ea7254SIngo Weinhold 	if (info == NULL)
12345b78a987SIngo Weinhold 		throw std::bad_alloc();
123537ea7254SIngo Weinhold 
1236bea40bcdSIngo Weinhold 	// TODO: The priority is missing from the system_profiler_thread_added
1237bea40bcdSIngo Weinhold 	// struct. For now guess at least whether this is an idle thread.
1238bea40bcdSIngo Weinhold 	if (strncmp(event->name, "idle thread", strlen("idle thread")) == 0)
1239bea40bcdSIngo Weinhold 		info->priority = 0;
1240bea40bcdSIngo Weinhold 	else
1241bea40bcdSIngo Weinhold 		info->priority = B_NORMAL_PRIORITY;
1242bea40bcdSIngo Weinhold 
1243a63809d3SIngo Weinhold 	fState->InsertThread(info);
124437ea7254SIngo Weinhold 
124537ea7254SIngo Weinhold 	return info;
124637ea7254SIngo Weinhold }
124737ea7254SIngo Weinhold 
124837ea7254SIngo Weinhold 
12495b78a987SIngo Weinhold ModelLoader::ExtendedThreadSchedulingState*
_AddUnknownThread(thread_id threadID)12505b78a987SIngo Weinhold ModelLoader::_AddUnknownThread(thread_id threadID)
12515b78a987SIngo Weinhold {
12525b78a987SIngo Weinhold 	// create a dummy "add thread" event
12535b78a987SIngo Weinhold 	system_profiler_thread_added* event = (system_profiler_thread_added*)
12545b78a987SIngo Weinhold 		malloc(sizeof(system_profiler_thread_added));
12555b78a987SIngo Weinhold 	if (event == NULL)
12565b78a987SIngo Weinhold 		throw std::bad_alloc();
12575b78a987SIngo Weinhold 
12585b78a987SIngo Weinhold 	if (!fModel->AddAssociatedData(event)) {
12595b78a987SIngo Weinhold 		free(event);
12605b78a987SIngo Weinhold 		throw std::bad_alloc();
12615b78a987SIngo Weinhold 	}
12625b78a987SIngo Weinhold 
12635b78a987SIngo Weinhold 	try {
12645b78a987SIngo Weinhold 		event->team = _AddUnknownTeam()->ID();
12655b78a987SIngo Weinhold 		event->thread = threadID;
12665b78a987SIngo Weinhold 		snprintf(event->name, sizeof(event->name), "unknown thread %" B_PRId32,
12675b78a987SIngo Weinhold 			threadID);
12685b78a987SIngo Weinhold 
12695b78a987SIngo Weinhold 		// add the thread to the model
12705b78a987SIngo Weinhold 		ExtendedThreadSchedulingState* state = _AddThread(event);
12715b78a987SIngo Weinhold 		return state;
12725b78a987SIngo Weinhold 	} catch (...) {
12735b78a987SIngo Weinhold 		throw;
12745b78a987SIngo Weinhold 	}
12755b78a987SIngo Weinhold }
12765b78a987SIngo Weinhold 
12775b78a987SIngo Weinhold Model::Team*
_AddUnknownTeam()12785b78a987SIngo Weinhold ModelLoader::_AddUnknownTeam()
12795b78a987SIngo Weinhold {
12805b78a987SIngo Weinhold 	team_id teamID = 0;
12815b78a987SIngo Weinhold 	Model::Team* team = fModel->TeamByID(teamID);
12825b78a987SIngo Weinhold 	if (team != NULL)
12835b78a987SIngo Weinhold 		return team;
12845b78a987SIngo Weinhold 
12855b78a987SIngo Weinhold 	// create a dummy "add team" event
12865b78a987SIngo Weinhold 	static const char* const kUnknownThreadsTeamName = "unknown threads";
12875b78a987SIngo Weinhold 	size_t nameLength = strlen(kUnknownThreadsTeamName);
12885b78a987SIngo Weinhold 
12895b78a987SIngo Weinhold 	system_profiler_team_added* event = (system_profiler_team_added*)
12905b78a987SIngo Weinhold 		malloc(sizeof(system_profiler_team_added) + nameLength);
12915b78a987SIngo Weinhold 	if (event == NULL)
12925b78a987SIngo Weinhold 		throw std::bad_alloc();
12935b78a987SIngo Weinhold 
12945b78a987SIngo Weinhold 	event->team = teamID;
12955b78a987SIngo Weinhold 	event->args_offset = nameLength;
12965b78a987SIngo Weinhold 	strlcpy(event->name, kUnknownThreadsTeamName, nameLength + 1);
12975b78a987SIngo Weinhold 
12985b78a987SIngo Weinhold 	// add the team to the model
12995b78a987SIngo Weinhold 	team = fModel->AddTeam(event, fState->LastEventTime());
13005b78a987SIngo Weinhold 	if (team == NULL)
13015b78a987SIngo Weinhold 		throw std::bad_alloc();
13025b78a987SIngo Weinhold 
13035b78a987SIngo Weinhold 	return team;
13045b78a987SIngo Weinhold }
13055b78a987SIngo Weinhold 
13065b78a987SIngo Weinhold 
130737ea7254SIngo Weinhold void
_AddThreadWaitObject(ExtendedThreadSchedulingState * thread,uint32 type,addr_t object)1308a63809d3SIngo Weinhold ModelLoader::_AddThreadWaitObject(ExtendedThreadSchedulingState* thread,
1309d4d63490SIngo Weinhold 	uint32 type, addr_t object)
131037ea7254SIngo Weinhold {
131137ea7254SIngo Weinhold 	Model::WaitObjectGroup* waitObjectGroup
131237ea7254SIngo Weinhold 		= fModel->WaitObjectGroupFor(type, object);
131337ea7254SIngo Weinhold 	if (waitObjectGroup == NULL) {
131437ea7254SIngo Weinhold 		// The algorithm should prevent this case.
1315883b3e1dSMichael Lotz 		printf("ModelLoader::_AddThreadWaitObject(): Unknown wait object: type:"
1316883b3e1dSMichael Lotz 			" %" B_PRIu32 ", " "object: %#" B_PRIxADDR "\n", type, object);
131737ea7254SIngo Weinhold 		return;
131837ea7254SIngo Weinhold 	}
131937ea7254SIngo Weinhold 
132037ea7254SIngo Weinhold 	Model::WaitObject* waitObject = waitObjectGroup->MostRecentWaitObject();
132137ea7254SIngo Weinhold 
132237ea7254SIngo Weinhold 	Model::ThreadWaitObjectGroup* threadWaitObjectGroup
132337ea7254SIngo Weinhold 		= fModel->ThreadWaitObjectGroupFor(thread->ID(), type, object);
132437ea7254SIngo Weinhold 
132537ea7254SIngo Weinhold 	if (threadWaitObjectGroup == NULL
132637ea7254SIngo Weinhold 		|| threadWaitObjectGroup->MostRecentWaitObject() != waitObject) {
132737ea7254SIngo Weinhold 		Model::ThreadWaitObject* threadWaitObject
132837ea7254SIngo Weinhold 			= fModel->AddThreadWaitObject(thread->ID(), waitObject,
132937ea7254SIngo Weinhold 				&threadWaitObjectGroup);
133037ea7254SIngo Weinhold 		if (threadWaitObject == NULL)
133137ea7254SIngo Weinhold 			throw std::bad_alloc();
133237ea7254SIngo Weinhold 	}
133337ea7254SIngo Weinhold 
133437ea7254SIngo Weinhold 	thread->waitObject = threadWaitObjectGroup->MostRecentThreadWaitObject();
133537ea7254SIngo Weinhold }
1336bea40bcdSIngo Weinhold 
1337bea40bcdSIngo Weinhold 
1338bea40bcdSIngo Weinhold void
_AddIdleTime(uint32 cpu,nanotime_t time)1339bea40bcdSIngo Weinhold ModelLoader::_AddIdleTime(uint32 cpu, nanotime_t time)
1340bea40bcdSIngo Weinhold {
1341bea40bcdSIngo Weinhold 	fCPUInfos[cpu].idleTime += time;
1342bea40bcdSIngo Weinhold }
1343