1284345Ssjg/*
2284345Ssjg * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3284345Ssjg * Distributed under the terms of the MIT License.
4284345Ssjg */
5284345Ssjg#ifndef MODEL_H
6284345Ssjg#define MODEL_H
7284345Ssjg
8284345Ssjg
9284345Ssjg#include <stdlib.h>
10284345Ssjg
11284345Ssjg#include <OS.h>
12284345Ssjg#include <String.h>
13284345Ssjg
14284345Ssjg#include <ObjectList.h>
15284345Ssjg#include <Referenceable.h>
16284345Ssjg#include <util/OpenHashTable.h>
17284345Ssjg
18284345Ssjg#include <system_profiler_defs.h>
19284345Ssjg#include <util/SinglyLinkedList.h>
20284345Ssjg
21284345Ssjg
22284345Ssjgenum ThreadState {
23	RUNNING,
24	STILL_RUNNING,
25	PREEMPTED,
26	READY,
27	WAITING,
28	UNKNOWN
29};
30
31const char* thread_state_name(ThreadState state);
32const char* wait_object_type_name(uint32 type);
33
34
35class Model : public BReferenceable {
36public:
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
57public:
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
137private:
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
145private:
146	static	int					_CompareEventTimeSchedulingState(
147									const nanotime_t* time,
148									const CompactSchedulingState* state);
149
150private:
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
170struct Model::creation_time_id {
171	nanotime_t	time;
172	thread_id	id;
173};
174
175
176struct Model::type_and_object {
177	uint32		type;
178	addr_t		object;
179};
180
181
182class Model::CPU {
183public:
184								CPU();
185
186	inline	nanotime_t			IdleTime() const;
187			void				SetIdleTime(nanotime_t time);
188
189private:
190			nanotime_t			fIdleTime;
191};
192
193
194struct 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
212struct 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
255class Model::IOScheduler {
256public:
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
265private:
266			system_profiler_io_scheduler_added* fAddedEvent;
267			int32				fIndex;
268};
269
270
271class Model::WaitObject {
272public:
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
294private:
295			const system_profiler_wait_object_info* fEvent;
296
297private:
298			int64				fWaits;
299			nanotime_t			fTotalWaitTime;
300};
301
302
303class Model::WaitObjectGroup {
304public:
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
328private:
329			typedef BObjectList<WaitObject> WaitObjectList;
330
331			void				_ComputeWaits();
332
333private:
334			WaitObjectList		fWaitObjects;
335			int64				fWaits;
336			nanotime_t			fTotalWaitTime;
337};
338
339
340class Model::ThreadWaitObject
341	: public SinglyLinkedListLinkImpl<ThreadWaitObject> {
342public:
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
358private:
359			WaitObject*			fWaitObject;
360			int64				fWaits;
361			nanotime_t			fTotalWaitTime;
362};
363
364
365class Model::ThreadWaitObjectGroup {
366public:
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
391private:
392			typedef SinglyLinkedList<ThreadWaitObject> ThreadWaitObjectList;
393
394private:
395			ThreadWaitObjectList fWaitObjects;
396};
397
398
399class Model::Team {
400public:
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
419private:
420			typedef BObjectList<Thread> ThreadList;
421
422private:
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
430class Model::Thread {
431public:
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
507private:
508			typedef BObjectList<ThreadWaitObjectGroup>
509				ThreadWaitObjectGroupList;
510
511private:
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
553struct Model::CompactThreadSchedulingState {
554			nanotime_t			lastTime;
555			Model::Thread*		thread;
556			ThreadWaitObject*	waitObject;
557			ThreadState			state;
558			uint8				priority;
559
560public:
561			thread_id			ID() const	{ return thread->ID(); }
562
563	inline	CompactThreadSchedulingState& operator=(
564									const CompactThreadSchedulingState& other);
565};
566
567
568struct Model::ThreadSchedulingState : CompactThreadSchedulingState {
569			ThreadSchedulingState* next;
570
571public:
572	inline						ThreadSchedulingState(
573									const CompactThreadSchedulingState& other);
574	inline						ThreadSchedulingState(Thread* thread);
575};
576
577
578struct Model::ThreadSchedulingStateDefinition {
579	typedef thread_id				KeyType;
580	typedef	ThreadSchedulingState	ValueType;
581
582	size_t HashKey(thread_id key) const
583		{ return (size_t)key; }
584
585	size_t Hash(const ThreadSchedulingState* value) const
586		{ return (size_t)value->ID(); }
587
588	bool Compare(thread_id key, const ThreadSchedulingState* value) const
589		{ return key == value->ID(); }
590
591	ThreadSchedulingState*& GetLink(ThreadSchedulingState* value) const
592		{ return value->next; }
593};
594
595
596class Model::SchedulingState {
597public:
598	inline						SchedulingState();
599	virtual						~SchedulingState();
600
601			status_t			Init();
602			status_t			Init(const CompactSchedulingState* state);
603			void				Clear();
604
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
613protected:
614	virtual	void				DeleteThread(ThreadSchedulingState* thread);
615
616private:
617			nanotime_t			fLastEventTime;
618			ThreadSchedulingStateTable fThreadStates;
619};
620
621
622class Model::CompactSchedulingState {
623public:
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
635private:
636	friend class BObjectList<CompactSchedulingState>;
637		// work-around for our private destructor
638
639private:
640								CompactSchedulingState();
641	inline						~CompactSchedulingState() {}
642
643private:
644			nanotime_t			fLastEventTime;
645			off_t				fEventOffset;
646			int32				fThreadCount;
647			CompactThreadSchedulingState fThreadStates[0];
648};
649
650
651// #pragma mark - Model
652
653
654const char*
655Model::DataSourceName() const
656{
657	return fDataSourceName.String();
658}
659
660
661void*
662Model::EventData() const
663{
664	return fEventData;
665}
666
667
668size_t
669Model::EventDataSize() const
670{
671	return fEventDataSize;
672}
673
674
675system_profiler_event_header**
676Model::Events() const
677{
678	return fEvents;
679}
680
681
682size_t
683Model::CountEvents() const
684{
685	return fEventCount;
686}
687
688
689nanotime_t
690Model::BaseTime() const
691{
692	return fBaseTime;
693}
694
695
696nanotime_t
697Model::LastEventTime() const
698{
699	return fLastEventTime;
700}
701
702
703nanotime_t
704Model::IdleTime() const
705{
706	return fIdleTime;
707}
708
709
710int32
711Model::CountCPUs() const
712{
713	return fCPUCount;
714}
715
716
717Model::CPU*
718Model::CPUAt(int32 index) const
719{
720	return fCPUs.ItemAt(index);
721}
722
723
724// #pragma mark - CPU
725
726
727nanotime_t
728Model::CPU::IdleTime() const
729{
730	return fIdleTime;
731}
732
733
734// #pragma mark - IOOperation
735
736
737nanotime_t
738Model::IOOperation::StartedTime() const
739{
740	return startedEvent->time;
741}
742
743
744nanotime_t
745Model::IOOperation::FinishedTime() const
746{
747	return finishedEvent != NULL ? finishedEvent->time : 0;
748}
749
750
751bool
752Model::IOOperation::IsFinished() const
753{
754	return finishedEvent != NULL;
755}
756
757
758off_t
759Model::IOOperation::Offset() const
760{
761	return startedEvent->offset;
762}
763
764
765size_t
766Model::IOOperation::Length() const
767{
768	return startedEvent->length;
769}
770
771
772bool
773Model::IOOperation::IsWrite() const
774{
775	return startedEvent->write;
776}
777
778
779status_t
780Model::IOOperation::Status() const
781{
782	return finishedEvent != NULL ? finishedEvent->status : B_OK;
783}
784
785
786size_t
787Model::IOOperation::BytesTransferred() const
788{
789	return finishedEvent != NULL ? finishedEvent->transferred : 0;
790}
791
792
793/*static*/ int
794Model::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
808nanotime_t
809Model::IORequest::ScheduledTime() const
810{
811	return scheduledEvent->time;
812}
813
814
815nanotime_t
816Model::IORequest::FinishedTime() const
817{
818	return finishedEvent != NULL ? finishedEvent->time : 0;
819}
820
821
822bool
823Model::IORequest::IsFinished() const
824{
825	return finishedEvent != NULL;
826}
827
828
829int32
830Model::IORequest::Scheduler() const
831{
832	return scheduledEvent->scheduler;
833}
834
835
836off_t
837Model::IORequest::Offset() const
838{
839	return scheduledEvent->offset;
840}
841
842
843size_t
844Model::IORequest::Length() const
845{
846	return scheduledEvent->length;
847}
848
849
850bool
851Model::IORequest::IsWrite() const
852{
853	return scheduledEvent->write;
854}
855
856
857uint8
858Model::IORequest::Priority() const
859{
860	return scheduledEvent->priority;
861}
862
863
864status_t
865Model::IORequest::Status() const
866{
867	return finishedEvent != NULL ? finishedEvent->status : B_OK;
868}
869
870
871size_t
872Model::IORequest::BytesTransferred() const
873{
874	return finishedEvent != NULL ? finishedEvent->transferred : 0;
875}
876
877
878/*static*/ bool
879Model::IORequest::TimeLess(const IORequest* a, const IORequest* b)
880{
881	return a->scheduledEvent->time < b->scheduledEvent->time;
882}
883
884
885/*static*/ bool
886Model::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
897Model::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
913int32
914Model::IOScheduler::ID() const
915{
916	return fAddedEvent->scheduler;
917}
918
919
920const char*
921Model::IOScheduler::Name() const
922{
923	return fAddedEvent->name;
924}
925
926
927int32
928Model::IOScheduler::Index() const
929{
930	return fIndex;
931}
932
933
934// #pragma mark - WaitObject
935
936
937uint32
938Model::WaitObject::Type() const
939{
940	return fEvent->type;
941}
942
943
944addr_t
945Model::WaitObject::Object() const
946{
947	return fEvent->object;
948}
949
950
951const char*
952Model::WaitObject::Name() const
953{
954	return fEvent->name;
955}
956
957
958addr_t
959Model::WaitObject::ReferencedObject()
960{
961	return fEvent->referenced_object;
962}
963
964
965int64
966Model::WaitObject::Waits() const
967{
968	return fWaits;
969}
970
971
972nanotime_t
973Model::WaitObject::TotalWaitTime() const
974{
975	return fTotalWaitTime;
976}
977
978
979/*static*/ int
980Model::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
991Model::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
1007uint32
1008Model::WaitObjectGroup::Type() const
1009{
1010	return MostRecentWaitObject()->Type();
1011}
1012
1013
1014addr_t
1015Model::WaitObjectGroup::Object() const
1016{
1017	return MostRecentWaitObject()->Object();
1018}
1019
1020
1021const char*
1022Model::WaitObjectGroup::Name() const
1023{
1024	return MostRecentWaitObject()->Name();
1025}
1026
1027
1028Model::WaitObject*
1029Model::WaitObjectGroup::MostRecentWaitObject() const
1030{
1031	return fWaitObjects.ItemAt(fWaitObjects.CountItems() - 1);
1032}
1033
1034
1035int32
1036Model::WaitObjectGroup::CountWaitObjects() const
1037{
1038	return fWaitObjects.CountItems();
1039}
1040
1041
1042Model::WaitObject*
1043Model::WaitObjectGroup::WaitObjectAt(int32 index) const
1044{
1045	return fWaitObjects.ItemAt(index);
1046}
1047
1048
1049void
1050Model::WaitObjectGroup::AddWaitObject(WaitObject* waitObject)
1051{
1052	fWaitObjects.AddItem(waitObject);
1053}
1054
1055
1056/*static*/ int
1057Model::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
1066Model::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
1077Model::WaitObject*
1078Model::ThreadWaitObject::GetWaitObject() const
1079{
1080	return fWaitObject;
1081}
1082
1083
1084uint32
1085Model::ThreadWaitObject::Type() const
1086{
1087	return fWaitObject->Type();
1088}
1089
1090
1091addr_t
1092Model::ThreadWaitObject::Object() const
1093{
1094	return fWaitObject->Object();
1095}
1096
1097
1098const char*
1099Model::ThreadWaitObject::Name() const
1100{
1101	return fWaitObject->Name();
1102}
1103
1104
1105addr_t
1106Model::ThreadWaitObject::ReferencedObject()
1107{
1108	return fWaitObject->ReferencedObject();
1109}
1110
1111
1112int64
1113Model::ThreadWaitObject::Waits() const
1114{
1115	return fWaits;
1116}
1117
1118
1119nanotime_t
1120Model::ThreadWaitObject::TotalWaitTime() const
1121{
1122	return fTotalWaitTime;
1123}
1124
1125
1126// #pragma mark - ThreadWaitObjectGroup
1127
1128
1129uint32
1130Model::ThreadWaitObjectGroup::Type() const
1131{
1132	return MostRecentThreadWaitObject()->Type();
1133}
1134
1135
1136addr_t
1137Model::ThreadWaitObjectGroup::Object() const
1138{
1139	return MostRecentThreadWaitObject()->Object();
1140}
1141
1142
1143const char*
1144Model::ThreadWaitObjectGroup::Name() const
1145{
1146	return MostRecentThreadWaitObject()->Name();
1147}
1148
1149
1150Model::ThreadWaitObject*
1151Model::ThreadWaitObjectGroup::MostRecentThreadWaitObject() const
1152{
1153	return fWaitObjects.Head();
1154}
1155
1156
1157Model::WaitObject*
1158Model::ThreadWaitObjectGroup::MostRecentWaitObject() const
1159{
1160	return MostRecentThreadWaitObject()->GetWaitObject();
1161}
1162
1163
1164void
1165Model::ThreadWaitObjectGroup::AddWaitObject(ThreadWaitObject* threadWaitObject)
1166{
1167	fWaitObjects.Add(threadWaitObject);
1168}
1169
1170
1171/*static*/ int
1172Model::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
1181Model::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
1192team_id
1193Model::Team::ID() const
1194{
1195	return fCreationEvent->team;
1196}
1197
1198
1199const char*
1200Model::Team::Name() const
1201{
1202	return fCreationEvent->name;
1203		// TODO: We should probably return the last exec name!
1204}
1205
1206
1207nanotime_t
1208Model::Team::CreationTime() const
1209{
1210	return fCreationTime;
1211}
1212
1213
1214nanotime_t
1215Model::Team::DeletionTime() const
1216{
1217	return fDeletionTime;
1218}
1219
1220
1221void
1222Model::Team::SetDeletionTime(nanotime_t time)
1223{
1224	fDeletionTime = time;
1225}
1226
1227
1228/*static*/ int
1229Model::Team::CompareByID(const Team* a, const Team* b)
1230{
1231	return a->ID() - b->ID();
1232}
1233
1234
1235/*static*/ int
1236Model::Team::CompareWithID(const team_id* id, const Team* team)
1237{
1238	return *id - team->ID();
1239}
1240
1241
1242// #pragma mark - Thread
1243
1244
1245thread_id
1246Model::Thread::ID() const
1247{
1248	return fCreationEvent->thread;
1249}
1250
1251
1252const char*
1253Model::Thread::Name() const
1254{
1255	return fCreationEvent->name;
1256}
1257
1258
1259Model::Team*
1260Model::Thread::GetTeam() const
1261{
1262	return fTeam;
1263}
1264
1265
1266nanotime_t
1267Model::Thread::CreationTime() const
1268{
1269	return fCreationTime;
1270}
1271
1272
1273nanotime_t
1274Model::Thread::DeletionTime() const
1275{
1276	return fDeletionTime;
1277}
1278
1279
1280int32
1281Model::Thread::Index() const
1282{
1283	return fIndex;
1284}
1285
1286
1287void
1288Model::Thread::SetIndex(int32 index)
1289{
1290	fIndex = index;
1291}
1292
1293
1294system_profiler_event_header**
1295Model::Thread::Events() const
1296{
1297	return fEvents;
1298}
1299
1300
1301size_t
1302Model::Thread::CountEvents() const
1303{
1304	return fEventCount;
1305}
1306
1307
1308Model::IORequest**
1309Model::Thread::IORequests() const
1310{
1311	return fIORequests;
1312}
1313
1314
1315size_t
1316Model::Thread::CountIORequests() const
1317{
1318	return fIORequestCount;
1319}
1320
1321
1322int64
1323Model::Thread::Runs() const
1324{
1325	return fRuns;
1326}
1327
1328
1329nanotime_t
1330Model::Thread::TotalRunTime() const
1331{
1332	return fTotalRunTime;
1333}
1334
1335
1336int64
1337Model::Thread::Reruns() const
1338{
1339	return fReruns;
1340}
1341
1342
1343nanotime_t
1344Model::Thread::TotalRerunTime() const
1345{
1346	return fTotalRerunTime;
1347}
1348
1349
1350int64
1351Model::Thread::Latencies() const
1352{
1353	return fLatencies;
1354}
1355
1356
1357nanotime_t
1358Model::Thread::TotalLatency() const
1359{
1360	return fTotalLatency;
1361}
1362
1363
1364int64
1365Model::Thread::Preemptions() const
1366{
1367	return fPreemptions;
1368}
1369
1370
1371int64
1372Model::Thread::Waits() const
1373{
1374	return fWaits;
1375}
1376
1377
1378nanotime_t
1379Model::Thread::TotalWaitTime() const
1380{
1381	return fTotalWaitTime;
1382}
1383
1384
1385nanotime_t
1386Model::Thread::UnspecifiedWaitTime() const
1387{
1388	return fUnspecifiedWaitTime;
1389}
1390
1391
1392int64
1393Model::Thread::IOCount() const
1394{
1395	return fIOCount;
1396}
1397
1398
1399nanotime_t
1400Model::Thread::IOTime() const
1401{
1402	return fIOTime;
1403}
1404
1405
1406int32
1407Model::Thread::CountThreadWaitObjectGroups() const
1408{
1409	return fWaitObjectGroups.CountItems();
1410}
1411
1412
1413Model::ThreadWaitObjectGroup*
1414Model::Thread::ThreadWaitObjectGroupAt(int32 index) const
1415{
1416	return fWaitObjectGroups.ItemAt(index);
1417}
1418
1419
1420void
1421Model::Thread::SetDeletionTime(nanotime_t time)
1422{
1423	fDeletionTime = time;
1424}
1425
1426
1427/*static*/ int
1428Model::Thread::CompareByID(const Thread* a, const Thread* b)
1429{
1430	return a->ID() - b->ID();
1431}
1432
1433
1434/*static*/ int
1435Model::Thread::CompareWithID(const thread_id* id, const Thread* thread)
1436{
1437	return *id - thread->ID();
1438}
1439
1440
1441/*static*/ int
1442Model::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
1452Model::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
1465Model::CompactThreadSchedulingState&
1466Model::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
1481Model::ThreadSchedulingState::ThreadSchedulingState(
1482	const CompactThreadSchedulingState& other)
1483{
1484	this->CompactThreadSchedulingState::operator=(other);
1485}
1486
1487
1488Model::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
1500Model::SchedulingState::SchedulingState()
1501	:
1502	fLastEventTime(-1)
1503{
1504}
1505
1506
1507void
1508Model::SchedulingState::SetLastEventTime(nanotime_t time)
1509{
1510	fLastEventTime = time;
1511}
1512
1513
1514Model::ThreadSchedulingState*
1515Model::SchedulingState::LookupThread(thread_id threadID) const
1516{
1517	return fThreadStates.Lookup(threadID);
1518}
1519
1520
1521void
1522Model::SchedulingState::InsertThread(ThreadSchedulingState* thread)
1523{
1524	fThreadStates.Insert(thread);
1525}
1526
1527
1528void
1529Model::SchedulingState::RemoveThread(ThreadSchedulingState* thread)
1530{
1531	fThreadStates.Remove(thread);
1532}
1533
1534
1535const Model::ThreadSchedulingStateTable&
1536Model::SchedulingState::ThreadStates() const
1537{
1538	return fThreadStates;
1539}
1540
1541
1542// #pragma mark - CompactSchedulingState
1543
1544
1545off_t
1546Model::CompactSchedulingState::EventOffset() const
1547{
1548	return fEventOffset;
1549}
1550
1551
1552nanotime_t
1553Model::CompactSchedulingState::LastEventTime() const
1554{
1555	return fLastEventTime;
1556}
1557
1558
1559int32
1560Model::CompactSchedulingState::CountThreadsStates() const
1561{
1562	return fThreadCount;
1563}
1564
1565
1566const Model::CompactThreadSchedulingState*
1567Model::CompactSchedulingState::ThreadStateAt(int32 index) const
1568{
1569	return index >= 0 && index < fThreadCount ? &fThreadStates[index] : NULL;
1570}
1571
1572
1573#endif	// MODEL_H
1574