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: 561 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 582 size_t HashKey(thread_id key) const 583 { return (size_t)key; } 584 585 size_t Hash(const ThreadSchedulingState* value) const 586 { return (size_t)value->ID(); } 587 588 bool Compare(thread_id key, const ThreadSchedulingState* value) const 589 { return key == value->ID(); } 590 591 ThreadSchedulingState*& GetLink(ThreadSchedulingState* value) const 592 { return value->next; } 593 }; 594 595 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 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(); 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* 655 Model::DataSourceName() const 656 { 657 return fDataSourceName.String(); 658 } 659 660 661 void* 662 Model::EventData() const 663 { 664 return fEventData; 665 } 666 667 668 size_t 669 Model::EventDataSize() const 670 { 671 return fEventDataSize; 672 } 673 674 675 system_profiler_event_header** 676 Model::Events() const 677 { 678 return fEvents; 679 } 680 681 682 size_t 683 Model::CountEvents() const 684 { 685 return fEventCount; 686 } 687 688 689 nanotime_t 690 Model::BaseTime() const 691 { 692 return fBaseTime; 693 } 694 695 696 nanotime_t 697 Model::LastEventTime() const 698 { 699 return fLastEventTime; 700 } 701 702 703 nanotime_t 704 Model::IdleTime() const 705 { 706 return fIdleTime; 707 } 708 709 710 int32 711 Model::CountCPUs() const 712 { 713 return fCPUCount; 714 } 715 716 717 Model::CPU* 718 Model::CPUAt(int32 index) const 719 { 720 return fCPUs.ItemAt(index); 721 } 722 723 724 // #pragma mark - CPU 725 726 727 nanotime_t 728 Model::CPU::IdleTime() const 729 { 730 return fIdleTime; 731 } 732 733 734 // #pragma mark - IOOperation 735 736 737 nanotime_t 738 Model::IOOperation::StartedTime() const 739 { 740 return startedEvent->time; 741 } 742 743 744 nanotime_t 745 Model::IOOperation::FinishedTime() const 746 { 747 return finishedEvent != NULL ? finishedEvent->time : 0; 748 } 749 750 751 bool 752 Model::IOOperation::IsFinished() const 753 { 754 return finishedEvent != NULL; 755 } 756 757 758 off_t 759 Model::IOOperation::Offset() const 760 { 761 return startedEvent->offset; 762 } 763 764 765 size_t 766 Model::IOOperation::Length() const 767 { 768 return startedEvent->length; 769 } 770 771 772 bool 773 Model::IOOperation::IsWrite() const 774 { 775 return startedEvent->write; 776 } 777 778 779 status_t 780 Model::IOOperation::Status() const 781 { 782 return finishedEvent != NULL ? finishedEvent->status : B_OK; 783 } 784 785 786 size_t 787 Model::IOOperation::BytesTransferred() const 788 { 789 return finishedEvent != NULL ? finishedEvent->transferred : 0; 790 } 791 792 793 /*static*/ int 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 809 Model::IORequest::ScheduledTime() const 810 { 811 return scheduledEvent->time; 812 } 813 814 815 nanotime_t 816 Model::IORequest::FinishedTime() const 817 { 818 return finishedEvent != NULL ? finishedEvent->time : 0; 819 } 820 821 822 bool 823 Model::IORequest::IsFinished() const 824 { 825 return finishedEvent != NULL; 826 } 827 828 829 int32 830 Model::IORequest::Scheduler() const 831 { 832 return scheduledEvent->scheduler; 833 } 834 835 836 off_t 837 Model::IORequest::Offset() const 838 { 839 return scheduledEvent->offset; 840 } 841 842 843 size_t 844 Model::IORequest::Length() const 845 { 846 return scheduledEvent->length; 847 } 848 849 850 bool 851 Model::IORequest::IsWrite() const 852 { 853 return scheduledEvent->write; 854 } 855 856 857 uint8 858 Model::IORequest::Priority() const 859 { 860 return scheduledEvent->priority; 861 } 862 863 864 status_t 865 Model::IORequest::Status() const 866 { 867 return finishedEvent != NULL ? finishedEvent->status : B_OK; 868 } 869 870 871 size_t 872 Model::IORequest::BytesTransferred() const 873 { 874 return finishedEvent != NULL ? finishedEvent->transferred : 0; 875 } 876 877 878 /*static*/ bool 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 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 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 914 Model::IOScheduler::ID() const 915 { 916 return fAddedEvent->scheduler; 917 } 918 919 920 const char* 921 Model::IOScheduler::Name() const 922 { 923 return fAddedEvent->name; 924 } 925 926 927 int32 928 Model::IOScheduler::Index() const 929 { 930 return fIndex; 931 } 932 933 934 // #pragma mark - WaitObject 935 936 937 uint32 938 Model::WaitObject::Type() const 939 { 940 return fEvent->type; 941 } 942 943 944 addr_t 945 Model::WaitObject::Object() const 946 { 947 return fEvent->object; 948 } 949 950 951 const char* 952 Model::WaitObject::Name() const 953 { 954 return fEvent->name; 955 } 956 957 958 addr_t 959 Model::WaitObject::ReferencedObject() 960 { 961 return fEvent->referenced_object; 962 } 963 964 965 int64 966 Model::WaitObject::Waits() const 967 { 968 return fWaits; 969 } 970 971 972 nanotime_t 973 Model::WaitObject::TotalWaitTime() const 974 { 975 return fTotalWaitTime; 976 } 977 978 979 /*static*/ int 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 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 1008 Model::WaitObjectGroup::Type() const 1009 { 1010 return MostRecentWaitObject()->Type(); 1011 } 1012 1013 1014 addr_t 1015 Model::WaitObjectGroup::Object() const 1016 { 1017 return MostRecentWaitObject()->Object(); 1018 } 1019 1020 1021 const char* 1022 Model::WaitObjectGroup::Name() const 1023 { 1024 return MostRecentWaitObject()->Name(); 1025 } 1026 1027 1028 Model::WaitObject* 1029 Model::WaitObjectGroup::MostRecentWaitObject() const 1030 { 1031 return fWaitObjects.ItemAt(fWaitObjects.CountItems() - 1); 1032 } 1033 1034 1035 int32 1036 Model::WaitObjectGroup::CountWaitObjects() const 1037 { 1038 return fWaitObjects.CountItems(); 1039 } 1040 1041 1042 Model::WaitObject* 1043 Model::WaitObjectGroup::WaitObjectAt(int32 index) const 1044 { 1045 return fWaitObjects.ItemAt(index); 1046 } 1047 1048 1049 void 1050 Model::WaitObjectGroup::AddWaitObject(WaitObject* waitObject) 1051 { 1052 fWaitObjects.AddItem(waitObject); 1053 } 1054 1055 1056 /*static*/ int 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 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* 1078 Model::ThreadWaitObject::GetWaitObject() const 1079 { 1080 return fWaitObject; 1081 } 1082 1083 1084 uint32 1085 Model::ThreadWaitObject::Type() const 1086 { 1087 return fWaitObject->Type(); 1088 } 1089 1090 1091 addr_t 1092 Model::ThreadWaitObject::Object() const 1093 { 1094 return fWaitObject->Object(); 1095 } 1096 1097 1098 const char* 1099 Model::ThreadWaitObject::Name() const 1100 { 1101 return fWaitObject->Name(); 1102 } 1103 1104 1105 addr_t 1106 Model::ThreadWaitObject::ReferencedObject() 1107 { 1108 return fWaitObject->ReferencedObject(); 1109 } 1110 1111 1112 int64 1113 Model::ThreadWaitObject::Waits() const 1114 { 1115 return fWaits; 1116 } 1117 1118 1119 nanotime_t 1120 Model::ThreadWaitObject::TotalWaitTime() const 1121 { 1122 return fTotalWaitTime; 1123 } 1124 1125 1126 // #pragma mark - ThreadWaitObjectGroup 1127 1128 1129 uint32 1130 Model::ThreadWaitObjectGroup::Type() const 1131 { 1132 return MostRecentThreadWaitObject()->Type(); 1133 } 1134 1135 1136 addr_t 1137 Model::ThreadWaitObjectGroup::Object() const 1138 { 1139 return MostRecentThreadWaitObject()->Object(); 1140 } 1141 1142 1143 const char* 1144 Model::ThreadWaitObjectGroup::Name() const 1145 { 1146 return MostRecentThreadWaitObject()->Name(); 1147 } 1148 1149 1150 Model::ThreadWaitObject* 1151 Model::ThreadWaitObjectGroup::MostRecentThreadWaitObject() const 1152 { 1153 return fWaitObjects.Head(); 1154 } 1155 1156 1157 Model::WaitObject* 1158 Model::ThreadWaitObjectGroup::MostRecentWaitObject() const 1159 { 1160 return MostRecentThreadWaitObject()->GetWaitObject(); 1161 } 1162 1163 1164 void 1165 Model::ThreadWaitObjectGroup::AddWaitObject(ThreadWaitObject* threadWaitObject) 1166 { 1167 fWaitObjects.Add(threadWaitObject); 1168 } 1169 1170 1171 /*static*/ int 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 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 1193 Model::Team::ID() const 1194 { 1195 return fCreationEvent->team; 1196 } 1197 1198 1199 const char* 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 1208 Model::Team::CreationTime() const 1209 { 1210 return fCreationTime; 1211 } 1212 1213 1214 nanotime_t 1215 Model::Team::DeletionTime() const 1216 { 1217 return fDeletionTime; 1218 } 1219 1220 1221 void 1222 Model::Team::SetDeletionTime(nanotime_t time) 1223 { 1224 fDeletionTime = time; 1225 } 1226 1227 1228 /*static*/ int 1229 Model::Team::CompareByID(const Team* a, const Team* b) 1230 { 1231 return a->ID() - b->ID(); 1232 } 1233 1234 1235 /*static*/ int 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 1246 Model::Thread::ID() const 1247 { 1248 return fCreationEvent->thread; 1249 } 1250 1251 1252 const char* 1253 Model::Thread::Name() const 1254 { 1255 return fCreationEvent->name; 1256 } 1257 1258 1259 Model::Team* 1260 Model::Thread::GetTeam() const 1261 { 1262 return fTeam; 1263 } 1264 1265 1266 nanotime_t 1267 Model::Thread::CreationTime() const 1268 { 1269 return fCreationTime; 1270 } 1271 1272 1273 nanotime_t 1274 Model::Thread::DeletionTime() const 1275 { 1276 return fDeletionTime; 1277 } 1278 1279 1280 int32 1281 Model::Thread::Index() const 1282 { 1283 return fIndex; 1284 } 1285 1286 1287 void 1288 Model::Thread::SetIndex(int32 index) 1289 { 1290 fIndex = index; 1291 } 1292 1293 1294 system_profiler_event_header** 1295 Model::Thread::Events() const 1296 { 1297 return fEvents; 1298 } 1299 1300 1301 size_t 1302 Model::Thread::CountEvents() const 1303 { 1304 return fEventCount; 1305 } 1306 1307 1308 Model::IORequest** 1309 Model::Thread::IORequests() const 1310 { 1311 return fIORequests; 1312 } 1313 1314 1315 size_t 1316 Model::Thread::CountIORequests() const 1317 { 1318 return fIORequestCount; 1319 } 1320 1321 1322 int64 1323 Model::Thread::Runs() const 1324 { 1325 return fRuns; 1326 } 1327 1328 1329 nanotime_t 1330 Model::Thread::TotalRunTime() const 1331 { 1332 return fTotalRunTime; 1333 } 1334 1335 1336 int64 1337 Model::Thread::Reruns() const 1338 { 1339 return fReruns; 1340 } 1341 1342 1343 nanotime_t 1344 Model::Thread::TotalRerunTime() const 1345 { 1346 return fTotalRerunTime; 1347 } 1348 1349 1350 int64 1351 Model::Thread::Latencies() const 1352 { 1353 return fLatencies; 1354 } 1355 1356 1357 nanotime_t 1358 Model::Thread::TotalLatency() const 1359 { 1360 return fTotalLatency; 1361 } 1362 1363 1364 int64 1365 Model::Thread::Preemptions() const 1366 { 1367 return fPreemptions; 1368 } 1369 1370 1371 int64 1372 Model::Thread::Waits() const 1373 { 1374 return fWaits; 1375 } 1376 1377 1378 nanotime_t 1379 Model::Thread::TotalWaitTime() const 1380 { 1381 return fTotalWaitTime; 1382 } 1383 1384 1385 nanotime_t 1386 Model::Thread::UnspecifiedWaitTime() const 1387 { 1388 return fUnspecifiedWaitTime; 1389 } 1390 1391 1392 int64 1393 Model::Thread::IOCount() const 1394 { 1395 return fIOCount; 1396 } 1397 1398 1399 nanotime_t 1400 Model::Thread::IOTime() const 1401 { 1402 return fIOTime; 1403 } 1404 1405 1406 int32 1407 Model::Thread::CountThreadWaitObjectGroups() const 1408 { 1409 return fWaitObjectGroups.CountItems(); 1410 } 1411 1412 1413 Model::ThreadWaitObjectGroup* 1414 Model::Thread::ThreadWaitObjectGroupAt(int32 index) const 1415 { 1416 return fWaitObjectGroups.ItemAt(index); 1417 } 1418 1419 1420 void 1421 Model::Thread::SetDeletionTime(nanotime_t time) 1422 { 1423 fDeletionTime = time; 1424 } 1425 1426 1427 /*static*/ int 1428 Model::Thread::CompareByID(const Thread* a, const Thread* b) 1429 { 1430 return a->ID() - b->ID(); 1431 } 1432 1433 1434 /*static*/ int 1435 Model::Thread::CompareWithID(const thread_id* id, const Thread* thread) 1436 { 1437 return *id - thread->ID(); 1438 } 1439 1440 1441 /*static*/ int 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 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 1481 Model::ThreadSchedulingState::ThreadSchedulingState( 1482 const CompactThreadSchedulingState& other) 1483 { 1484 this->CompactThreadSchedulingState::operator=(other); 1485 } 1486 1487 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 1500 Model::SchedulingState::SchedulingState() 1501 : 1502 fLastEventTime(-1) 1503 { 1504 } 1505 1506 1507 void 1508 Model::SchedulingState::SetLastEventTime(nanotime_t time) 1509 { 1510 fLastEventTime = time; 1511 } 1512 1513 1514 Model::ThreadSchedulingState* 1515 Model::SchedulingState::LookupThread(thread_id threadID) const 1516 { 1517 return fThreadStates.Lookup(threadID); 1518 } 1519 1520 1521 void 1522 Model::SchedulingState::InsertThread(ThreadSchedulingState* thread) 1523 { 1524 fThreadStates.Insert(thread); 1525 } 1526 1527 1528 void 1529 Model::SchedulingState::RemoveThread(ThreadSchedulingState* thread) 1530 { 1531 fThreadStates.Remove(thread); 1532 } 1533 1534 1535 const Model::ThreadSchedulingStateTable& 1536 Model::SchedulingState::ThreadStates() const 1537 { 1538 return fThreadStates; 1539 } 1540 1541 1542 // #pragma mark - CompactSchedulingState 1543 1544 1545 off_t 1546 Model::CompactSchedulingState::EventOffset() const 1547 { 1548 return fEventOffset; 1549 } 1550 1551 1552 nanotime_t 1553 Model::CompactSchedulingState::LastEventTime() const 1554 { 1555 return fLastEventTime; 1556 } 1557 1558 1559 int32 1560 Model::CompactSchedulingState::CountThreadsStates() const 1561 { 1562 return fThreadCount; 1563 } 1564 1565 1566 const Model::CompactThreadSchedulingState* 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