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