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