xref: /haiku/src/apps/debuganalyzer/model/Model.h (revision 25a7b01d15612846f332751841da3579db313082)
1 /*
2  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef MODEL_H
6 #define MODEL_H
7 
8 
9 #include <stdlib.h>
10 
11 #include <OS.h>
12 #include <String.h>
13 
14 #include <ObjectList.h>
15 #include <Referenceable.h>
16 #include <util/OpenHashTable.h>
17 
18 #include <system_profiler_defs.h>
19 #include <util/SinglyLinkedList.h>
20 
21 
22 enum ThreadState {
23 	RUNNING,
24 	STILL_RUNNING,
25 	PREEMPTED,
26 	READY,
27 	WAITING,
28 	UNKNOWN
29 };
30 
31 const char* thread_state_name(ThreadState state);
32 const char* wait_object_type_name(uint32 type);
33 
34 
35 class Model : public BReferenceable {
36 public:
37 			struct creation_time_id;
38 			struct type_and_object;
39 			class CPU;
40 			struct IOOperation;
41 			struct IORequest;
42 			class IOScheduler;
43 			class WaitObjectGroup;
44 			class WaitObject;
45 			class ThreadWaitObject;
46 			class ThreadWaitObjectGroup;
47 			class Team;
48 			class Thread;
49 			struct CompactThreadSchedulingState;
50 			struct ThreadSchedulingState;
51 			struct ThreadSchedulingStateDefinition;
52 			typedef BOpenHashTable<ThreadSchedulingStateDefinition>
53 				ThreadSchedulingStateTable;
54 			class SchedulingState;
55 			class CompactSchedulingState;
56 
57 public:
58 								Model(const char* dataSourceName,
59 									void* eventData, size_t eventDataSize,
60 									system_profiler_event_header** events,
61 									size_t eventCount);
62 								~Model();
63 
64 	inline	const char*			DataSourceName() const;
65 	inline	void*				EventData() const;
66 	inline	size_t				EventDataSize() const;
67 	inline	system_profiler_event_header** Events() const;
68 	inline	size_t				CountEvents() const;
69 			size_t				ClosestEventIndex(nanotime_t eventTime) const;
70 									// finds the greatest event with event
71 									// time >= eventTime; may return
72 									// CountEvents()
73 
74 			bool				AddAssociatedData(void* data);
75 			void				RemoveAssociatedData(void* data);
76 
77 			void				LoadingFinished();
78 
79 	inline	nanotime_t			BaseTime() const;
80 			void				SetBaseTime(nanotime_t time);
81 
82 	inline	nanotime_t			LastEventTime() const;
83 			void				SetLastEventTime(nanotime_t time);
84 
85 	inline	nanotime_t			IdleTime() const;
86 
87 	inline	int32				CountCPUs() const;
88 			bool				SetCPUCount(int32 count);
89 	inline	CPU*				CPUAt(int32 index) const;
90 
91 			int32				CountTeams() const;
92 			Team*				TeamAt(int32 index) const;
93 			Team*				TeamByID(team_id id) const;
94 			Team*				AddTeam(
95 									const system_profiler_team_added* event,
96 									nanotime_t time);
97 
98 			int32				CountThreads() const;
99 			Thread*				ThreadAt(int32 index) const;
100 			Thread*				ThreadByID(thread_id id) const;
101 			Thread*				AddThread(
102 									const system_profiler_thread_added* event,
103 									nanotime_t time);
104 
105 			WaitObject*			AddWaitObject(
106 									const system_profiler_wait_object_info*
107 										event,
108 									WaitObjectGroup** _waitObjectGroup);
109 
110 			int32				CountWaitObjectGroups() const;
111 			WaitObjectGroup*	WaitObjectGroupAt(int32 index) const;
112 			WaitObjectGroup*	WaitObjectGroupFor(uint32 type,
113 									addr_t object) const;
114 
115 			ThreadWaitObject*	AddThreadWaitObject(thread_id threadID,
116 									WaitObject* waitObject,
117 									ThreadWaitObjectGroup**
118 										_threadWaitObjectGroup);
119 			ThreadWaitObjectGroup* ThreadWaitObjectGroupFor(
120 									thread_id threadID, uint32 type,
121 									addr_t object) const;
122 
123 			int32				CountIOSchedulers() const;
124 			IOScheduler*		IOSchedulerAt(int32 index) const;
125 			IOScheduler*		IOSchedulerByID(int32 id) const;
126 			IOScheduler*		AddIOScheduler(
127 									system_profiler_io_scheduler_added* event);
128 
129 			bool				AddSchedulingStateSnapshot(
130 									const SchedulingState& state,
131 									off_t eventOffset);
132 									// must be added in order (of time)
133 			const CompactSchedulingState* ClosestSchedulingState(
134 									nanotime_t eventTime) const;
135 									// returns the closest previous state
136 
137 private:
138 			typedef BObjectList<CPU> CPUList;
139 			typedef BObjectList<Team> TeamList;
140 			typedef BObjectList<Thread> ThreadList;
141 			typedef BObjectList<WaitObjectGroup> WaitObjectGroupList;
142 			typedef BObjectList<IOScheduler> IOSchedulerList;
143 			typedef BObjectList<CompactSchedulingState> SchedulingStateList;
144 
145 private:
146 	static	int					_CompareEventTimeSchedulingState(
147 									const nanotime_t* time,
148 									const CompactSchedulingState* state);
149 
150 private:
151 			BString				fDataSourceName;
152 			void*				fEventData;
153 			system_profiler_event_header** fEvents;
154 			size_t				fEventDataSize;
155 			size_t				fEventCount;
156 			int32				fCPUCount;
157 			nanotime_t			fBaseTime;
158 			nanotime_t			fLastEventTime;
159 			nanotime_t			fIdleTime;
160 			CPUList				fCPUs;
161 			TeamList			fTeams;		// sorted by ID
162 			ThreadList			fThreads;	// sorted by ID
163 			WaitObjectGroupList	fWaitObjectGroups;
164 			IOSchedulerList		fIOSchedulers;
165 			SchedulingStateList	fSchedulingStates;
166 			BList				fAssociatedData;
167 };
168 
169 
170 struct Model::creation_time_id {
171 	nanotime_t	time;
172 	thread_id	id;
173 };
174 
175 
176 struct Model::type_and_object {
177 	uint32		type;
178 	addr_t		object;
179 };
180 
181 
182 class Model::CPU {
183 public:
184 								CPU();
185 
186 	inline	nanotime_t			IdleTime() const;
187 			void				SetIdleTime(nanotime_t time);
188 
189 private:
190 			nanotime_t			fIdleTime;
191 };
192 
193 
194 struct Model::IOOperation {
195 	system_profiler_io_operation_started*	startedEvent;
196 	system_profiler_io_operation_finished*	finishedEvent;
197 
198 	static inline int			CompareByTime(const IOOperation* a,
199 									const IOOperation* b);
200 
201 	inline	nanotime_t			StartedTime() const;
202 	inline	nanotime_t			FinishedTime() const;
203 	inline	bool				IsFinished() const;
204 	inline	off_t				Offset() const;
205 	inline	size_t				Length() const;
206 	inline	bool				IsWrite() const;
207 	inline	status_t			Status() const;
208 	inline	size_t				BytesTransferred() const;
209 };
210 
211 
212 struct Model::IORequest {
213 	system_profiler_io_request_scheduled*	scheduledEvent;
214 	system_profiler_io_request_finished*	finishedEvent;
215 	size_t									operationCount;
216 	IOOperation								operations[0];
217 
218 								IORequest(
219 									system_profiler_io_request_scheduled*
220 										scheduledEvent,
221 									system_profiler_io_request_finished*
222 										finishedEvent,
223 									size_t operationCount);
224 								~IORequest();
225 
226 	static	IORequest*			Create(
227 									system_profiler_io_request_scheduled*
228 										scheduledEvent,
229 									system_profiler_io_request_finished*
230 									finishedEvent,
231 									size_t operationCount);
232 			void				Delete();
233 
234 	inline	nanotime_t			ScheduledTime() const;
235 	inline	nanotime_t			FinishedTime() const;
236 	inline	bool				IsFinished() const;
237 	inline	int32				Scheduler() const;
238 	inline	off_t				Offset() const;
239 	inline	size_t				Length() const;
240 	inline	bool				IsWrite() const;
241 	inline	uint8				Priority() const;
242 	inline	status_t			Status() const;
243 	inline	size_t				BytesTransferred() const;
244 
245 
246 	static inline bool			TimeLess(const IORequest* a,
247 									const IORequest* b);
248 	static inline bool			SchedulerTimeLess(const IORequest* a,
249 									const IORequest* b);
250 	static inline int			CompareSchedulerTime(const IORequest* a,
251 									const IORequest* b);
252 };
253 
254 
255 class Model::IOScheduler {
256 public:
257 								IOScheduler(
258 									system_profiler_io_scheduler_added* event,
259 									int32 index);
260 
261 	inline	int32				ID() const;
262 	inline	const char*			Name() const;
263 	inline	int32				Index() const;
264 
265 private:
266 			system_profiler_io_scheduler_added* fAddedEvent;
267 			int32				fIndex;
268 };
269 
270 
271 class Model::WaitObject {
272 public:
273 								WaitObject(
274 									const system_profiler_wait_object_info*
275 										event);
276 								~WaitObject();
277 
278 	inline	uint32				Type() const;
279 	inline	addr_t				Object() const;
280 	inline	const char*			Name() const;
281 	inline	addr_t				ReferencedObject();
282 
283 	inline	int64				Waits() const;
284 	inline	nanotime_t			TotalWaitTime() const;
285 
286 			void				AddWait(nanotime_t waitTime);
287 
288 	static inline int			CompareByTypeObject(const WaitObject* a,
289 									const WaitObject* b);
290 	static inline int			CompareWithTypeObject(
291 									const type_and_object* key,
292 									const WaitObject* object);
293 
294 private:
295 			const system_profiler_wait_object_info* fEvent;
296 
297 private:
298 			int64				fWaits;
299 			nanotime_t			fTotalWaitTime;
300 };
301 
302 
303 class Model::WaitObjectGroup {
304 public:
305 								WaitObjectGroup(WaitObject* waitObject);
306 								~WaitObjectGroup();
307 
308 	inline	uint32				Type() const;
309 	inline	addr_t				Object() const;
310 	inline	const char*			Name() const;
311 
312 			int64				Waits();
313 			nanotime_t			TotalWaitTime();
314 
315 	inline	WaitObject*			MostRecentWaitObject() const;
316 
317 	inline	int32				CountWaitObjects() const;
318 	inline	Model::WaitObject*	WaitObjectAt(int32 index) const;
319 
320 	inline	void				AddWaitObject(WaitObject* waitObject);
321 
322 	static inline int			CompareByTypeObject(const WaitObjectGroup* a,
323 									const WaitObjectGroup* b);
324 	static inline int			CompareWithTypeObject(
325 									const type_and_object* key,
326 									const WaitObjectGroup* group);
327 
328 private:
329 			typedef BObjectList<WaitObject> WaitObjectList;
330 
331 			void				_ComputeWaits();
332 
333 private:
334 			WaitObjectList		fWaitObjects;
335 			int64				fWaits;
336 			nanotime_t			fTotalWaitTime;
337 };
338 
339 
340 class Model::ThreadWaitObject
341 	: public SinglyLinkedListLinkImpl<ThreadWaitObject> {
342 public:
343 								ThreadWaitObject(WaitObject* waitObject);
344 								~ThreadWaitObject();
345 
346 	inline	WaitObject*			GetWaitObject() const;
347 
348 	inline	uint32				Type() const;
349 	inline	addr_t				Object() const;
350 	inline	const char*			Name() const;
351 	inline	addr_t				ReferencedObject();
352 
353 	inline	int64				Waits() const;
354 	inline	nanotime_t			TotalWaitTime() const;
355 
356 			void				AddWait(nanotime_t waitTime);
357 
358 private:
359 			WaitObject*			fWaitObject;
360 			int64				fWaits;
361 			nanotime_t			fTotalWaitTime;
362 };
363 
364 
365 class Model::ThreadWaitObjectGroup {
366 public:
367 								ThreadWaitObjectGroup(
368 									ThreadWaitObject* threadWaitObject);
369 								~ThreadWaitObjectGroup();
370 
371 	inline	uint32				Type() const;
372 	inline	addr_t				Object() const;
373 	inline	const char*			Name() const;
374 
375 	inline	ThreadWaitObject*	MostRecentThreadWaitObject() const;
376 	inline	WaitObject*			MostRecentWaitObject() const;
377 
378 	inline	void				AddWaitObject(
379 									ThreadWaitObject* threadWaitObject);
380 
381 			bool				GetThreadWaitObjects(
382 									BObjectList<ThreadWaitObject>& objects);
383 
384 	static inline int			CompareByTypeObject(
385 									const ThreadWaitObjectGroup* a,
386 									const ThreadWaitObjectGroup* b);
387 	static inline int			CompareWithTypeObject(
388 									const type_and_object* key,
389 									const ThreadWaitObjectGroup* group);
390 
391 private:
392 			typedef SinglyLinkedList<ThreadWaitObject> ThreadWaitObjectList;
393 
394 private:
395 			ThreadWaitObjectList fWaitObjects;
396 };
397 
398 
399 class Model::Team {
400 public:
401 								Team(const system_profiler_team_added* event,
402 									nanotime_t time);
403 								~Team();
404 
405 	inline	team_id				ID() const;
406 	inline	const char*			Name() const;
407 
408 	inline	nanotime_t			CreationTime() const;
409 	inline	nanotime_t			DeletionTime() const;
410 
411 			bool				AddThread(Thread* thread);
412 
413 	inline	void				SetDeletionTime(nanotime_t time);
414 
415 	static inline int			CompareByID(const Team* a, const Team* b);
416 	static inline int			CompareWithID(const team_id* id,
417 									const Team* team);
418 
419 private:
420 			typedef BObjectList<Thread> ThreadList;
421 
422 private:
423 			const system_profiler_team_added* fCreationEvent;
424 			nanotime_t			fCreationTime;
425 			nanotime_t			fDeletionTime;
426 			ThreadList			fThreads;	// sorted by creation time, ID
427 };
428 
429 
430 class Model::Thread {
431 public:
432 								Thread(Team* team,
433 									const system_profiler_thread_added* event,
434 									nanotime_t time);
435 								~Thread();
436 
437 	inline	thread_id			ID() const;
438 	inline	const char*			Name() const;
439 	inline	Team*				GetTeam() const;
440 
441 	inline	int32				Index() const;
442 	inline	void				SetIndex(int32 index);
443 
444 	inline	system_profiler_event_header** Events() const;
445 	inline	size_t				CountEvents() const;
446 			void				SetEvents(system_profiler_event_header** events,
447 									size_t eventCount);
448 
449 	inline	IORequest**			IORequests() const;
450 	inline	size_t				CountIORequests() const;
451 			void				SetIORequests(IORequest** requests,
452 									size_t requestCount);
453 			size_t				ClosestRequestStartIndex(
454 									nanotime_t minRequestStartTime) const;
455 									// Returns the index of the first request
456 									// with a start time >= minRequestStartTime.
457 									// minRequestStartTime is absolute, not
458 									// base time relative.
459 
460 	inline	nanotime_t			CreationTime() const;
461 	inline	nanotime_t			DeletionTime() const;
462 
463 	inline	int64				Runs() const;
464 	inline	nanotime_t			TotalRunTime() const;
465 	inline	int64				Reruns() const;
466 	inline	nanotime_t			TotalRerunTime() const;
467 	inline	int64				Latencies() const;
468 	inline	nanotime_t			TotalLatency() const;
469 	inline	int64				Preemptions() const;
470 	inline	int64				Waits() const;
471 	inline	nanotime_t			TotalWaitTime() const;
472 	inline	nanotime_t			UnspecifiedWaitTime() const;
473 
474 	inline	int64				IOCount() const;
475 	inline	nanotime_t			IOTime() const;
476 
477 			ThreadWaitObjectGroup* ThreadWaitObjectGroupFor(uint32 type,
478 									addr_t object) const;
479 	inline	int32				CountThreadWaitObjectGroups() const;
480 	inline	ThreadWaitObjectGroup* ThreadWaitObjectGroupAt(int32 index) const;
481 
482 	inline	void				SetDeletionTime(nanotime_t time);
483 
484 			void				AddRun(nanotime_t runTime);
485 			void				AddRerun(nanotime_t runTime);
486 			void				AddLatency(nanotime_t latency);
487 			void				AddPreemption(nanotime_t runTime);
488 			void				AddWait(nanotime_t waitTime);
489 			void				AddUnspecifiedWait(nanotime_t waitTime);
490 
491 			ThreadWaitObject*	AddThreadWaitObject(WaitObject* waitObject,
492 									ThreadWaitObjectGroup**
493 										_threadWaitObjectGroup);
494 
495 			void				SetIOs(int64 count, nanotime_t time);
496 
497 	static inline int			CompareByID(const Thread* a, const Thread* b);
498 	static inline int			CompareWithID(const thread_id* id,
499 									const Thread* thread);
500 
501 	static inline int			CompareByCreationTimeID(const Thread* a,
502 									const Thread* b);
503 	static inline int			CompareWithCreationTimeID(
504 									const creation_time_id* key,
505 									const Thread* thread);
506 
507 private:
508 			typedef BObjectList<ThreadWaitObjectGroup>
509 				ThreadWaitObjectGroupList;
510 
511 private:
512 			system_profiler_event_header** fEvents;
513 			size_t				fEventCount;
514 
515 			IORequest**			fIORequests;
516 			size_t				fIORequestCount;
517 
518 			Team*				fTeam;
519 			const system_profiler_thread_added* fCreationEvent;
520 			nanotime_t			fCreationTime;
521 			nanotime_t			fDeletionTime;
522 
523 			int64				fRuns;
524 			nanotime_t			fTotalRunTime;
525 			nanotime_t			fMinRunTime;
526 			nanotime_t			fMaxRunTime;
527 
528 			int64				fLatencies;
529 			nanotime_t			fTotalLatency;
530 			nanotime_t			fMinLatency;
531 			nanotime_t			fMaxLatency;
532 
533 			int64				fReruns;
534 			nanotime_t			fTotalRerunTime;
535 			nanotime_t			fMinRerunTime;
536 			nanotime_t			fMaxRerunTime;
537 
538 			int64				fWaits;
539 			nanotime_t			fTotalWaitTime;
540 			nanotime_t			fUnspecifiedWaitTime;
541 
542 			int64				fIOCount;
543 			nanotime_t			fIOTime;
544 
545 			int64				fPreemptions;
546 
547 			int32				fIndex;
548 
549 			ThreadWaitObjectGroupList fWaitObjectGroups;
550 };
551 
552 
553 struct Model::CompactThreadSchedulingState {
554 			nanotime_t			lastTime;
555 			Model::Thread*		thread;
556 			ThreadWaitObject*	waitObject;
557 			ThreadState			state;
558 			uint8				priority;
559 
560 public:
IDCompactThreadSchedulingState561 			thread_id			ID() const	{ return thread->ID(); }
562 
563 	inline	CompactThreadSchedulingState& operator=(
564 									const CompactThreadSchedulingState& other);
565 };
566 
567 
568 struct Model::ThreadSchedulingState : CompactThreadSchedulingState {
569 			ThreadSchedulingState* next;
570 
571 public:
572 	inline						ThreadSchedulingState(
573 									const CompactThreadSchedulingState& other);
574 	inline						ThreadSchedulingState(Thread* thread);
575 };
576 
577 
578 struct Model::ThreadSchedulingStateDefinition {
579 	typedef thread_id				KeyType;
580 	typedef	ThreadSchedulingState	ValueType;
581 
HashKeyThreadSchedulingStateDefinition582 	size_t HashKey(thread_id key) const
583 		{ return (size_t)key; }
584 
HashThreadSchedulingStateDefinition585 	size_t Hash(const ThreadSchedulingState* value) const
586 		{ return (size_t)value->ID(); }
587 
CompareThreadSchedulingStateDefinition588 	bool Compare(thread_id key, const ThreadSchedulingState* value) const
589 		{ return key == value->ID(); }
590 
GetLinkThreadSchedulingStateDefinition591 	ThreadSchedulingState*& GetLink(ThreadSchedulingState* value) const
592 		{ return value->next; }
593 };
594 
595 
596 class Model::SchedulingState {
597 public:
598 	inline						SchedulingState();
599 	virtual						~SchedulingState();
600 
601 			status_t			Init();
602 			status_t			Init(const CompactSchedulingState* state);
603 			void				Clear();
604 
LastEventTime()605 	inline	nanotime_t			LastEventTime() const { return fLastEventTime; }
606 	inline	void				SetLastEventTime(nanotime_t time);
607 
608 	inline	ThreadSchedulingState* LookupThread(thread_id threadID) const;
609 	inline	void				InsertThread(ThreadSchedulingState* thread);
610 	inline	void				RemoveThread(ThreadSchedulingState* thread);
611 	inline	const ThreadSchedulingStateTable& ThreadStates() const;
612 
613 protected:
614 	virtual	void				DeleteThread(ThreadSchedulingState* thread);
615 
616 private:
617 			nanotime_t			fLastEventTime;
618 			ThreadSchedulingStateTable fThreadStates;
619 };
620 
621 
622 class Model::CompactSchedulingState {
623 public:
624 	static	CompactSchedulingState* Create(const SchedulingState& state,
625 									off_t eventOffset);
626 			void				Delete();
627 
628 	inline	off_t				EventOffset() const;
629 	inline	nanotime_t			LastEventTime() const;
630 
631 	inline	int32				CountThreadsStates() const;
632 	inline	const CompactThreadSchedulingState* ThreadStateAt(int32 index)
633 									const;
634 
635 private:
636 	friend class BObjectList<CompactSchedulingState>;
637 		// work-around for our private destructor
638 
639 private:
640 								CompactSchedulingState();
~CompactSchedulingState()641 	inline						~CompactSchedulingState() {}
642 
643 private:
644 			nanotime_t			fLastEventTime;
645 			off_t				fEventOffset;
646 			int32				fThreadCount;
647 			CompactThreadSchedulingState fThreadStates[0];
648 };
649 
650 
651 // #pragma mark - Model
652 
653 
654 const char*
DataSourceName()655 Model::DataSourceName() const
656 {
657 	return fDataSourceName.String();
658 }
659 
660 
661 void*
EventData()662 Model::EventData() const
663 {
664 	return fEventData;
665 }
666 
667 
668 size_t
EventDataSize()669 Model::EventDataSize() const
670 {
671 	return fEventDataSize;
672 }
673 
674 
675 system_profiler_event_header**
Events()676 Model::Events() const
677 {
678 	return fEvents;
679 }
680 
681 
682 size_t
CountEvents()683 Model::CountEvents() const
684 {
685 	return fEventCount;
686 }
687 
688 
689 nanotime_t
BaseTime()690 Model::BaseTime() const
691 {
692 	return fBaseTime;
693 }
694 
695 
696 nanotime_t
LastEventTime()697 Model::LastEventTime() const
698 {
699 	return fLastEventTime;
700 }
701 
702 
703 nanotime_t
IdleTime()704 Model::IdleTime() const
705 {
706 	return fIdleTime;
707 }
708 
709 
710 int32
CountCPUs()711 Model::CountCPUs() const
712 {
713 	return fCPUCount;
714 }
715 
716 
717 Model::CPU*
CPUAt(int32 index)718 Model::CPUAt(int32 index) const
719 {
720 	return fCPUs.ItemAt(index);
721 }
722 
723 
724 // #pragma mark - CPU
725 
726 
727 nanotime_t
IdleTime()728 Model::CPU::IdleTime() const
729 {
730 	return fIdleTime;
731 }
732 
733 
734 // #pragma mark - IOOperation
735 
736 
737 nanotime_t
StartedTime()738 Model::IOOperation::StartedTime() const
739 {
740 	return startedEvent->time;
741 }
742 
743 
744 nanotime_t
FinishedTime()745 Model::IOOperation::FinishedTime() const
746 {
747 	return finishedEvent != NULL ? finishedEvent->time : 0;
748 }
749 
750 
751 bool
IsFinished()752 Model::IOOperation::IsFinished() const
753 {
754 	return finishedEvent != NULL;
755 }
756 
757 
758 off_t
Offset()759 Model::IOOperation::Offset() const
760 {
761 	return startedEvent->offset;
762 }
763 
764 
765 size_t
Length()766 Model::IOOperation::Length() const
767 {
768 	return startedEvent->length;
769 }
770 
771 
772 bool
IsWrite()773 Model::IOOperation::IsWrite() const
774 {
775 	return startedEvent->write;
776 }
777 
778 
779 status_t
Status()780 Model::IOOperation::Status() const
781 {
782 	return finishedEvent != NULL ? finishedEvent->status : B_OK;
783 }
784 
785 
786 size_t
BytesTransferred()787 Model::IOOperation::BytesTransferred() const
788 {
789 	return finishedEvent != NULL ? finishedEvent->transferred : 0;
790 }
791 
792 
793 /*static*/ int
CompareByTime(const IOOperation * a,const IOOperation * b)794 Model::IOOperation::CompareByTime(const IOOperation* a, const IOOperation* b)
795 {
796 	nanotime_t timeA = a->startedEvent->time;
797 	nanotime_t timeB = b->startedEvent->time;
798 
799 	if (timeA < timeB)
800 		return -1;
801 	return timeA == timeB ? 0 : 1;
802 }
803 
804 
805 // #pragma mark - IORequest
806 
807 
808 nanotime_t
ScheduledTime()809 Model::IORequest::ScheduledTime() const
810 {
811 	return scheduledEvent->time;
812 }
813 
814 
815 nanotime_t
FinishedTime()816 Model::IORequest::FinishedTime() const
817 {
818 	return finishedEvent != NULL ? finishedEvent->time : 0;
819 }
820 
821 
822 bool
IsFinished()823 Model::IORequest::IsFinished() const
824 {
825 	return finishedEvent != NULL;
826 }
827 
828 
829 int32
Scheduler()830 Model::IORequest::Scheduler() const
831 {
832 	return scheduledEvent->scheduler;
833 }
834 
835 
836 off_t
Offset()837 Model::IORequest::Offset() const
838 {
839 	return scheduledEvent->offset;
840 }
841 
842 
843 size_t
Length()844 Model::IORequest::Length() const
845 {
846 	return scheduledEvent->length;
847 }
848 
849 
850 bool
IsWrite()851 Model::IORequest::IsWrite() const
852 {
853 	return scheduledEvent->write;
854 }
855 
856 
857 uint8
Priority()858 Model::IORequest::Priority() const
859 {
860 	return scheduledEvent->priority;
861 }
862 
863 
864 status_t
Status()865 Model::IORequest::Status() const
866 {
867 	return finishedEvent != NULL ? finishedEvent->status : B_OK;
868 }
869 
870 
871 size_t
BytesTransferred()872 Model::IORequest::BytesTransferred() const
873 {
874 	return finishedEvent != NULL ? finishedEvent->transferred : 0;
875 }
876 
877 
878 /*static*/ bool
TimeLess(const IORequest * a,const IORequest * b)879 Model::IORequest::TimeLess(const IORequest* a, const IORequest* b)
880 {
881 	return a->scheduledEvent->time < b->scheduledEvent->time;
882 }
883 
884 
885 /*static*/ bool
SchedulerTimeLess(const IORequest * a,const IORequest * b)886 Model::IORequest::SchedulerTimeLess(const IORequest* a, const IORequest* b)
887 {
888 	int32 cmp = a->scheduledEvent->scheduler - b->scheduledEvent->scheduler;
889 	if (cmp != 0)
890 		return cmp < 0;
891 
892 	return a->scheduledEvent->time < b->scheduledEvent->time;
893 }
894 
895 
896 /*static*/ int
CompareSchedulerTime(const IORequest * a,const IORequest * b)897 Model::IORequest::CompareSchedulerTime(const IORequest* a, const IORequest* b)
898 {
899 	int32 cmp = a->scheduledEvent->scheduler - b->scheduledEvent->scheduler;
900 	if (cmp != 0)
901 		return cmp < 0;
902 
903 	nanotime_t timeCmp = a->scheduledEvent->time - b->scheduledEvent->time;
904 	if (timeCmp == 0)
905 		return 0;
906 	return timeCmp < 0 ? -1 : 1;
907 }
908 
909 
910 // #pragma mark - IOScheduler
911 
912 
913 int32
ID()914 Model::IOScheduler::ID() const
915 {
916 	return fAddedEvent->scheduler;
917 }
918 
919 
920 const char*
Name()921 Model::IOScheduler::Name() const
922 {
923 	return fAddedEvent->name;
924 }
925 
926 
927 int32
Index()928 Model::IOScheduler::Index() const
929 {
930 	return fIndex;
931 }
932 
933 
934 // #pragma mark - WaitObject
935 
936 
937 uint32
Type()938 Model::WaitObject::Type() const
939 {
940 	return fEvent->type;
941 }
942 
943 
944 addr_t
Object()945 Model::WaitObject::Object() const
946 {
947 	return fEvent->object;
948 }
949 
950 
951 const char*
Name()952 Model::WaitObject::Name() const
953 {
954 	return fEvent->name;
955 }
956 
957 
958 addr_t
ReferencedObject()959 Model::WaitObject::ReferencedObject()
960 {
961 	return fEvent->referenced_object;
962 }
963 
964 
965 int64
Waits()966 Model::WaitObject::Waits() const
967 {
968 	return fWaits;
969 }
970 
971 
972 nanotime_t
TotalWaitTime()973 Model::WaitObject::TotalWaitTime() const
974 {
975 	return fTotalWaitTime;
976 }
977 
978 
979 /*static*/ int
CompareByTypeObject(const WaitObject * a,const WaitObject * b)980 Model::WaitObject::CompareByTypeObject(const WaitObject* a, const WaitObject* b)
981 {
982 	type_and_object key;
983 	key.type = a->Type();
984 	key.object = a->Object();
985 
986 	return CompareWithTypeObject(&key, b);
987 }
988 
989 
990 /*static*/ int
CompareWithTypeObject(const type_and_object * key,const WaitObject * object)991 Model::WaitObject::CompareWithTypeObject(const type_and_object* key,
992 	const WaitObject* object)
993 {
994 	if (key->type == object->Type()) {
995 		if (key->object == object->Object())
996 			return 0;
997 		return key->object < object->Object() ? -1 : 1;
998 	}
999 
1000 	return key->type < object->Type() ? -1 : 1;
1001 }
1002 
1003 
1004 // #pragma mark - WaitObjectGroup
1005 
1006 
1007 uint32
Type()1008 Model::WaitObjectGroup::Type() const
1009 {
1010 	return MostRecentWaitObject()->Type();
1011 }
1012 
1013 
1014 addr_t
Object()1015 Model::WaitObjectGroup::Object() const
1016 {
1017 	return MostRecentWaitObject()->Object();
1018 }
1019 
1020 
1021 const char*
Name()1022 Model::WaitObjectGroup::Name() const
1023 {
1024 	return MostRecentWaitObject()->Name();
1025 }
1026 
1027 
1028 Model::WaitObject*
MostRecentWaitObject()1029 Model::WaitObjectGroup::MostRecentWaitObject() const
1030 {
1031 	return fWaitObjects.ItemAt(fWaitObjects.CountItems() - 1);
1032 }
1033 
1034 
1035 int32
CountWaitObjects()1036 Model::WaitObjectGroup::CountWaitObjects() const
1037 {
1038 	return fWaitObjects.CountItems();
1039 }
1040 
1041 
1042 Model::WaitObject*
WaitObjectAt(int32 index)1043 Model::WaitObjectGroup::WaitObjectAt(int32 index) const
1044 {
1045 	return fWaitObjects.ItemAt(index);
1046 }
1047 
1048 
1049 void
AddWaitObject(WaitObject * waitObject)1050 Model::WaitObjectGroup::AddWaitObject(WaitObject* waitObject)
1051 {
1052 	fWaitObjects.AddItem(waitObject);
1053 }
1054 
1055 
1056 /*static*/ int
CompareByTypeObject(const WaitObjectGroup * a,const WaitObjectGroup * b)1057 Model::WaitObjectGroup::CompareByTypeObject(
1058 	const WaitObjectGroup* a, const WaitObjectGroup* b)
1059 {
1060 	return WaitObject::CompareByTypeObject(a->MostRecentWaitObject(),
1061 		b->MostRecentWaitObject());
1062 }
1063 
1064 
1065 /*static*/ int
CompareWithTypeObject(const type_and_object * key,const WaitObjectGroup * group)1066 Model::WaitObjectGroup::CompareWithTypeObject(const type_and_object* key,
1067 	const WaitObjectGroup* group)
1068 {
1069 	return WaitObject::CompareWithTypeObject(key,
1070 		group->MostRecentWaitObject());
1071 }
1072 
1073 
1074 // #pragma mark - ThreadWaitObject
1075 
1076 
1077 Model::WaitObject*
GetWaitObject()1078 Model::ThreadWaitObject::GetWaitObject() const
1079 {
1080 	return fWaitObject;
1081 }
1082 
1083 
1084 uint32
Type()1085 Model::ThreadWaitObject::Type() const
1086 {
1087 	return fWaitObject->Type();
1088 }
1089 
1090 
1091 addr_t
Object()1092 Model::ThreadWaitObject::Object() const
1093 {
1094 	return fWaitObject->Object();
1095 }
1096 
1097 
1098 const char*
Name()1099 Model::ThreadWaitObject::Name() const
1100 {
1101 	return fWaitObject->Name();
1102 }
1103 
1104 
1105 addr_t
ReferencedObject()1106 Model::ThreadWaitObject::ReferencedObject()
1107 {
1108 	return fWaitObject->ReferencedObject();
1109 }
1110 
1111 
1112 int64
Waits()1113 Model::ThreadWaitObject::Waits() const
1114 {
1115 	return fWaits;
1116 }
1117 
1118 
1119 nanotime_t
TotalWaitTime()1120 Model::ThreadWaitObject::TotalWaitTime() const
1121 {
1122 	return fTotalWaitTime;
1123 }
1124 
1125 
1126 // #pragma mark - ThreadWaitObjectGroup
1127 
1128 
1129 uint32
Type()1130 Model::ThreadWaitObjectGroup::Type() const
1131 {
1132 	return MostRecentThreadWaitObject()->Type();
1133 }
1134 
1135 
1136 addr_t
Object()1137 Model::ThreadWaitObjectGroup::Object() const
1138 {
1139 	return MostRecentThreadWaitObject()->Object();
1140 }
1141 
1142 
1143 const char*
Name()1144 Model::ThreadWaitObjectGroup::Name() const
1145 {
1146 	return MostRecentThreadWaitObject()->Name();
1147 }
1148 
1149 
1150 Model::ThreadWaitObject*
MostRecentThreadWaitObject()1151 Model::ThreadWaitObjectGroup::MostRecentThreadWaitObject() const
1152 {
1153 	return fWaitObjects.Head();
1154 }
1155 
1156 
1157 Model::WaitObject*
MostRecentWaitObject()1158 Model::ThreadWaitObjectGroup::MostRecentWaitObject() const
1159 {
1160 	return MostRecentThreadWaitObject()->GetWaitObject();
1161 }
1162 
1163 
1164 void
AddWaitObject(ThreadWaitObject * threadWaitObject)1165 Model::ThreadWaitObjectGroup::AddWaitObject(ThreadWaitObject* threadWaitObject)
1166 {
1167 	fWaitObjects.Add(threadWaitObject);
1168 }
1169 
1170 
1171 /*static*/ int
CompareByTypeObject(const ThreadWaitObjectGroup * a,const ThreadWaitObjectGroup * b)1172 Model::ThreadWaitObjectGroup::CompareByTypeObject(
1173 	const ThreadWaitObjectGroup* a, const ThreadWaitObjectGroup* b)
1174 {
1175 	return WaitObject::CompareByTypeObject(a->MostRecentWaitObject(),
1176 		b->MostRecentWaitObject());
1177 }
1178 
1179 
1180 /*static*/ int
CompareWithTypeObject(const type_and_object * key,const ThreadWaitObjectGroup * group)1181 Model::ThreadWaitObjectGroup::CompareWithTypeObject(const type_and_object* key,
1182 	const ThreadWaitObjectGroup* group)
1183 {
1184 	return WaitObject::CompareWithTypeObject(key,
1185 		group->MostRecentWaitObject());
1186 }
1187 
1188 
1189 // #pragma mark - Team
1190 
1191 
1192 team_id
ID()1193 Model::Team::ID() const
1194 {
1195 	return fCreationEvent->team;
1196 }
1197 
1198 
1199 const char*
Name()1200 Model::Team::Name() const
1201 {
1202 	return fCreationEvent->name;
1203 		// TODO: We should probably return the last exec name!
1204 }
1205 
1206 
1207 nanotime_t
CreationTime()1208 Model::Team::CreationTime() const
1209 {
1210 	return fCreationTime;
1211 }
1212 
1213 
1214 nanotime_t
DeletionTime()1215 Model::Team::DeletionTime() const
1216 {
1217 	return fDeletionTime;
1218 }
1219 
1220 
1221 void
SetDeletionTime(nanotime_t time)1222 Model::Team::SetDeletionTime(nanotime_t time)
1223 {
1224 	fDeletionTime = time;
1225 }
1226 
1227 
1228 /*static*/ int
CompareByID(const Team * a,const Team * b)1229 Model::Team::CompareByID(const Team* a, const Team* b)
1230 {
1231 	return a->ID() - b->ID();
1232 }
1233 
1234 
1235 /*static*/ int
CompareWithID(const team_id * id,const Team * team)1236 Model::Team::CompareWithID(const team_id* id, const Team* team)
1237 {
1238 	return *id - team->ID();
1239 }
1240 
1241 
1242 // #pragma mark - Thread
1243 
1244 
1245 thread_id
ID()1246 Model::Thread::ID() const
1247 {
1248 	return fCreationEvent->thread;
1249 }
1250 
1251 
1252 const char*
Name()1253 Model::Thread::Name() const
1254 {
1255 	return fCreationEvent->name;
1256 }
1257 
1258 
1259 Model::Team*
GetTeam()1260 Model::Thread::GetTeam() const
1261 {
1262 	return fTeam;
1263 }
1264 
1265 
1266 nanotime_t
CreationTime()1267 Model::Thread::CreationTime() const
1268 {
1269 	return fCreationTime;
1270 }
1271 
1272 
1273 nanotime_t
DeletionTime()1274 Model::Thread::DeletionTime() const
1275 {
1276 	return fDeletionTime;
1277 }
1278 
1279 
1280 int32
Index()1281 Model::Thread::Index() const
1282 {
1283 	return fIndex;
1284 }
1285 
1286 
1287 void
SetIndex(int32 index)1288 Model::Thread::SetIndex(int32 index)
1289 {
1290 	fIndex = index;
1291 }
1292 
1293 
1294 system_profiler_event_header**
Events()1295 Model::Thread::Events() const
1296 {
1297 	return fEvents;
1298 }
1299 
1300 
1301 size_t
CountEvents()1302 Model::Thread::CountEvents() const
1303 {
1304 	return fEventCount;
1305 }
1306 
1307 
1308 Model::IORequest**
IORequests()1309 Model::Thread::IORequests() const
1310 {
1311 	return fIORequests;
1312 }
1313 
1314 
1315 size_t
CountIORequests()1316 Model::Thread::CountIORequests() const
1317 {
1318 	return fIORequestCount;
1319 }
1320 
1321 
1322 int64
Runs()1323 Model::Thread::Runs() const
1324 {
1325 	return fRuns;
1326 }
1327 
1328 
1329 nanotime_t
TotalRunTime()1330 Model::Thread::TotalRunTime() const
1331 {
1332 	return fTotalRunTime;
1333 }
1334 
1335 
1336 int64
Reruns()1337 Model::Thread::Reruns() const
1338 {
1339 	return fReruns;
1340 }
1341 
1342 
1343 nanotime_t
TotalRerunTime()1344 Model::Thread::TotalRerunTime() const
1345 {
1346 	return fTotalRerunTime;
1347 }
1348 
1349 
1350 int64
Latencies()1351 Model::Thread::Latencies() const
1352 {
1353 	return fLatencies;
1354 }
1355 
1356 
1357 nanotime_t
TotalLatency()1358 Model::Thread::TotalLatency() const
1359 {
1360 	return fTotalLatency;
1361 }
1362 
1363 
1364 int64
Preemptions()1365 Model::Thread::Preemptions() const
1366 {
1367 	return fPreemptions;
1368 }
1369 
1370 
1371 int64
Waits()1372 Model::Thread::Waits() const
1373 {
1374 	return fWaits;
1375 }
1376 
1377 
1378 nanotime_t
TotalWaitTime()1379 Model::Thread::TotalWaitTime() const
1380 {
1381 	return fTotalWaitTime;
1382 }
1383 
1384 
1385 nanotime_t
UnspecifiedWaitTime()1386 Model::Thread::UnspecifiedWaitTime() const
1387 {
1388 	return fUnspecifiedWaitTime;
1389 }
1390 
1391 
1392 int64
IOCount()1393 Model::Thread::IOCount() const
1394 {
1395 	return fIOCount;
1396 }
1397 
1398 
1399 nanotime_t
IOTime()1400 Model::Thread::IOTime() const
1401 {
1402 	return fIOTime;
1403 }
1404 
1405 
1406 int32
CountThreadWaitObjectGroups()1407 Model::Thread::CountThreadWaitObjectGroups() const
1408 {
1409 	return fWaitObjectGroups.CountItems();
1410 }
1411 
1412 
1413 Model::ThreadWaitObjectGroup*
ThreadWaitObjectGroupAt(int32 index)1414 Model::Thread::ThreadWaitObjectGroupAt(int32 index) const
1415 {
1416 	return fWaitObjectGroups.ItemAt(index);
1417 }
1418 
1419 
1420 void
SetDeletionTime(nanotime_t time)1421 Model::Thread::SetDeletionTime(nanotime_t time)
1422 {
1423 	fDeletionTime = time;
1424 }
1425 
1426 
1427 /*static*/ int
CompareByID(const Thread * a,const Thread * b)1428 Model::Thread::CompareByID(const Thread* a, const Thread* b)
1429 {
1430 	return a->ID() - b->ID();
1431 }
1432 
1433 
1434 /*static*/ int
CompareWithID(const thread_id * id,const Thread * thread)1435 Model::Thread::CompareWithID(const thread_id* id, const Thread* thread)
1436 {
1437 	return *id - thread->ID();
1438 }
1439 
1440 
1441 /*static*/ int
CompareByCreationTimeID(const Thread * a,const Thread * b)1442 Model::Thread::CompareByCreationTimeID(const Thread* a, const Thread* b)
1443 {
1444 	creation_time_id key;
1445 	key.time = a->fCreationTime;
1446 	key.id = a->ID();
1447 	return CompareWithCreationTimeID(&key, b);
1448 }
1449 
1450 
1451 /*static*/ int
CompareWithCreationTimeID(const creation_time_id * key,const Thread * thread)1452 Model::Thread::CompareWithCreationTimeID(const creation_time_id* key,
1453 	const Thread* thread)
1454 {
1455 	nanotime_t cmp = key->time - thread->fCreationTime;
1456 	if (cmp == 0)
1457 		return key->id - thread->ID();
1458 	return cmp < 0 ? -1 : 1;
1459 }
1460 
1461 
1462 // #pragma mark - CompactThreadSchedulingState
1463 
1464 
1465 Model::CompactThreadSchedulingState&
1466 Model::CompactThreadSchedulingState::operator=(
1467 	const CompactThreadSchedulingState& other)
1468 {
1469 	lastTime = other.lastTime;
1470 	thread = other.thread;
1471 	waitObject = other.waitObject;
1472 	state = other.state;
1473 	priority = other.priority;
1474 	return *this;
1475 }
1476 
1477 
1478 // #pragma mark - ThreadSchedulingState
1479 
1480 
ThreadSchedulingState(const CompactThreadSchedulingState & other)1481 Model::ThreadSchedulingState::ThreadSchedulingState(
1482 	const CompactThreadSchedulingState& other)
1483 {
1484 	this->CompactThreadSchedulingState::operator=(other);
1485 }
1486 
1487 
ThreadSchedulingState(Thread * thread)1488 Model::ThreadSchedulingState::ThreadSchedulingState(Thread* thread)
1489 {
1490 	lastTime = 0;
1491 	this->thread = thread;
1492 	waitObject = NULL;
1493 	state = UNKNOWN;
1494 }
1495 
1496 
1497 // #pragma mark - SchedulingState
1498 
1499 
SchedulingState()1500 Model::SchedulingState::SchedulingState()
1501 	:
1502 	fLastEventTime(-1)
1503 {
1504 }
1505 
1506 
1507 void
SetLastEventTime(nanotime_t time)1508 Model::SchedulingState::SetLastEventTime(nanotime_t time)
1509 {
1510 	fLastEventTime = time;
1511 }
1512 
1513 
1514 Model::ThreadSchedulingState*
LookupThread(thread_id threadID)1515 Model::SchedulingState::LookupThread(thread_id threadID) const
1516 {
1517 	return fThreadStates.Lookup(threadID);
1518 }
1519 
1520 
1521 void
InsertThread(ThreadSchedulingState * thread)1522 Model::SchedulingState::InsertThread(ThreadSchedulingState* thread)
1523 {
1524 	fThreadStates.Insert(thread);
1525 }
1526 
1527 
1528 void
RemoveThread(ThreadSchedulingState * thread)1529 Model::SchedulingState::RemoveThread(ThreadSchedulingState* thread)
1530 {
1531 	fThreadStates.Remove(thread);
1532 }
1533 
1534 
1535 const Model::ThreadSchedulingStateTable&
ThreadStates()1536 Model::SchedulingState::ThreadStates() const
1537 {
1538 	return fThreadStates;
1539 }
1540 
1541 
1542 // #pragma mark - CompactSchedulingState
1543 
1544 
1545 off_t
EventOffset()1546 Model::CompactSchedulingState::EventOffset() const
1547 {
1548 	return fEventOffset;
1549 }
1550 
1551 
1552 nanotime_t
LastEventTime()1553 Model::CompactSchedulingState::LastEventTime() const
1554 {
1555 	return fLastEventTime;
1556 }
1557 
1558 
1559 int32
CountThreadsStates()1560 Model::CompactSchedulingState::CountThreadsStates() const
1561 {
1562 	return fThreadCount;
1563 }
1564 
1565 
1566 const Model::CompactThreadSchedulingState*
ThreadStateAt(int32 index)1567 Model::CompactSchedulingState::ThreadStateAt(int32 index) const
1568 {
1569 	return index >= 0 && index < fThreadCount ? &fThreadStates[index] : NULL;
1570 }
1571 
1572 
1573 #endif	// MODEL_H
1574