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