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