]>
Commit | Line | Data |
---|---|---|
bd6521f0 A |
1 | // |
2 | // CPUActivity.hpp | |
3 | // KDBG | |
4 | // | |
5 | // Created by James McIlree on 4/22/13. | |
6 | // Copyright (c) 2014 Apple. All rights reserved. | |
7 | // | |
8 | ||
9 | #ifndef kdprof_CPUActivity_hpp | |
10 | #define kdprof_CPUActivity_hpp | |
11 | ||
12 | // NOTE! Counted, not bits! | |
13 | enum class kCPUActivity : uint32_t { | |
14 | Unknown = 0x00000001, | |
15 | Idle = 0x00000002, | |
16 | INTR = 0x00000003, | |
17 | Run = 0x00000004 // *MUST* be the last definition. See "is_run()" | |
18 | }; | |
19 | ||
20 | template <typename SIZE> | |
21 | class CPUActivity : public AbsInterval { | |
22 | ||
23 | // Declaring this a union to make the behavior clearer. | |
24 | // | |
25 | // If _type > kCPUActivity::Run, the _thread portion of | |
26 | // the union is valid, the _type is coonsider to be Run. | |
27 | // | |
28 | // However, if the _thread is valid, the low order bit of | |
29 | // the thread indicates if this was a context switch. | |
30 | // | |
31 | // So: | |
32 | // | |
33 | // 0000000X == _type; | |
34 | // XXXXXXX[0/1] == _thread; | |
35 | ||
36 | union { | |
37 | MachineThread<SIZE>* thread; | |
38 | uintptr_t type; | |
39 | } _u; | |
40 | ||
41 | enum { | |
42 | kCPUActivityRunIsContextSwitch = 0x1 | |
43 | }; | |
44 | ||
45 | public: | |
46 | CPUActivity(kCPUActivity type, AbsInterval interval) : | |
47 | AbsInterval(interval) | |
48 | { | |
49 | ASSERT(type != kCPUActivity::Run, "Cannot be Run without a thread"); | |
50 | _u.type = (uintptr_t)type; | |
51 | } | |
52 | ||
53 | CPUActivity(MachineThread<SIZE>* thread, AbsInterval interval, bool is_cntx_swtch) : | |
54 | AbsInterval(interval) | |
55 | { | |
56 | _u.thread = thread; | |
57 | if (is_cntx_swtch) | |
58 | _u.type |= kCPUActivityRunIsContextSwitch; | |
59 | ||
60 | ASSERT(is_run(), "Sanity"); | |
61 | ASSERT(is_context_switch() == is_cntx_swtch, "Sanity"); | |
62 | } | |
63 | ||
64 | // We can safely assume that the memory system will never allocate | |
65 | // a thread in the first page of memory. | |
66 | bool is_run() const { return _u.type > (uintptr_t)kCPUActivity::Run; } | |
67 | bool is_idle() const { return _u.type == (uintptr_t)kCPUActivity::Idle; } | |
68 | bool is_intr() const { return _u.type == (uintptr_t)kCPUActivity::INTR; } | |
69 | bool is_unknown() const { return _u.type == (uintptr_t)kCPUActivity::Unknown; } | |
70 | ||
71 | bool is_context_switch() const { | |
72 | if (is_run() && (_u.type & kCPUActivityRunIsContextSwitch)) | |
73 | return true; | |
74 | return false; | |
75 | } | |
76 | ||
77 | kCPUActivity type() const { | |
78 | if (_u.type > (uintptr_t)kCPUActivity::Run) | |
79 | return kCPUActivity::Run; | |
80 | ||
81 | return (kCPUActivity)_u.type; | |
82 | } | |
83 | ||
84 | const MachineThread<SIZE>* thread() const { | |
85 | ASSERT(is_run(), "Sanity"); | |
86 | return (MachineThread<SIZE>* )((uintptr_t)_u.thread & ~kCPUActivityRunIsContextSwitch); | |
87 | } | |
88 | }; | |
89 | ||
90 | #endif |