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