1717#ifndef _THREAD_CPU_USAGE_H
1818#define _THREAD_CPU_USAGE_H
1919
20- #include < cpustats/CentralTendencyStatistics.h>
20+ #include < fcntl.h>
21+ #include < pthread.h>
2122
22- // Track CPU usage for the current thread, and maintain statistics on
23- // the CPU usage. Units are in per-thread CPU ns, as reported by
23+ namespace android {
24+
25+ // Track CPU usage for the current thread.
26+ // Units are in per-thread CPU ns, as reported by
2427// clock_gettime(CLOCK_THREAD_CPUTIME_ID). Simple usage: for cyclic
2528// threads where you want to measure the execution time of the whole
2629// cycle, just call sampleAndEnable() at the start of each cycle.
27- // Then call statistics() to get the results, and resetStatistics()
28- // to start a new set of measurements.
29- // For acyclic threads, or for cyclic threads where you want to measure
30+ // For acyclic threads, or for cyclic threads where you want to measure/track
3031// only part of each cycle, call enable(), disable(), and/or setEnabled()
3132// to demarcate the region(s) of interest, and then call sample() periodically.
3233// This class is not thread-safe for concurrent calls from multiple threads;
@@ -44,13 +45,17 @@ class ThreadCpuUsage
4445 // mPreviousTs
4546 // mMonotonicTs
4647 mMonotonicKnown (false )
47- // mStatistics
48- { }
48+ {
49+ (void ) pthread_once (&sOnceControl , &init);
50+ for (int i = 0 ; i < sKernelMax ; ++i) {
51+ mCurrentkHz [i] = (uint32_t ) ~0 ; // unknown
52+ }
53+ }
4954
5055 ~ThreadCpuUsage () { }
5156
5257 // Return whether currently tracking CPU usage by current thread
53- bool isEnabled () { return mIsEnabled ; }
58+ bool isEnabled () const { return mIsEnabled ; }
5459
5560 // Enable tracking of CPU usage by current thread;
5661 // any CPU used from this point forward will be tracked.
@@ -66,39 +71,52 @@ class ThreadCpuUsage
6671 // This method is intended to be used for safe nested enable/disabling.
6772 bool setEnabled (bool isEnabled);
6873
69- // Add a sample point for central tendency statistics, and also
70- // enable tracking if needed. If tracking has never been enabled, then
71- // enables tracking but does not add a sample (it is not possible to add
72- // a sample the first time because no previous). Otherwise if tracking is
73- // enabled, then adds a sample for tracked CPU ns since the previous
74+ // Add a sample point, and also enable tracking if needed.
75+ // If tracking has never been enabled, then this call enables tracking but
76+ // does _not_ add a sample -- it is not possible to add a sample the
77+ // first time because there is no previous point to subtract from.
78+ // Otherwise, if tracking is enabled,
79+ // then adds a sample for tracked CPU ns since the previous
7480 // sample, or since the first call to sampleAndEnable(), enable(), or
7581 // setEnabled(true). If there was a previous sample but tracking is
7682 // now disabled, then adds a sample for the tracked CPU ns accumulated
7783 // up until the most recent disable(), resets this accumulator, and then
7884 // enables tracking. Calling this method rather than enable() followed
7985 // by sample() avoids a race condition for the first sample.
80- void sampleAndEnable ();
86+ // Returns true if the sample 'ns' is valid, or false if invalid.
87+ // Note that 'ns' is an output parameter passed by reference.
88+ // The caller does not need to initialize this variable.
89+ // The units are CPU nanoseconds consumed by current thread.
90+ bool sampleAndEnable (double & ns);
8191
82- // Add a sample point for central tendency statistics , but do not
92+ // Add a sample point, but do not
8393 // change the tracking enabled status. If tracking has either never been
8494 // enabled, or has never been enabled since the last sample, then log a warning
8595 // and don't add sample. Otherwise, adds a sample for tracked CPU ns since
8696 // the previous sample or since the first call to sampleAndEnable(),
8797 // enable(), or setEnabled(true) if no previous sample.
88- void sample ();
98+ // Returns true if the sample is valid, or false if invalid.
99+ // Note that 'ns' is an output parameter passed by reference.
100+ // The caller does not need to initialize this variable.
101+ // The units are CPU nanoseconds consumed by current thread.
102+ bool sample (double & ns);
89103
90- // Return the elapsed delta wall clock ns since initial enable or statistics reset,
104+ // Return the elapsed delta wall clock ns since initial enable or reset,
91105 // as reported by clock_gettime(CLOCK_MONOTONIC).
92106 long long elapsed () const ;
93107
94- // Reset statistics and elapsed . Has no effect on tracking or accumulator.
95- void resetStatistics ();
108+ // Reset elapsed wall clock . Has no effect on tracking or accumulator.
109+ void resetElapsed ();
96110
97- // Return a const reference to the central tendency statistics.
98- // Note that only the const methods can be called on this object.
99- const CentralTendencyStatistics& statistics () const {
100- return mStatistics ;
101- }
111+ // Return current clock frequency for specified CPU, in kHz.
112+ // You can get your CPU number using sched_getcpu(2). Note that, unless CPU affinity
113+ // has been configured appropriately, the CPU number can change.
114+ // Also note that, unless the CPU governor has been configured appropriately,
115+ // the CPU frequency can change. And even if the CPU frequency is locked down
116+ // to a particular value, that the frequency might still be adjusted
117+ // to prevent thermal overload. Therefore you should poll for your thread's
118+ // current CPU number and clock frequency periodically.
119+ uint32_t getCpukHz (int cpuNum);
102120
103121private:
104122 bool mIsEnabled ; // whether tracking is currently enabled
@@ -107,7 +125,15 @@ class ThreadCpuUsage
107125 struct timespec mPreviousTs ; // most recent thread CPU time, valid only if mIsEnabled is true
108126 struct timespec mMonotonicTs ; // most recent monotonic time
109127 bool mMonotonicKnown ; // whether mMonotonicTs has been set
110- CentralTendencyStatistics mStatistics ;
128+
129+ static const int MAX_CPU = 8 ;
130+ static int sScalingFds [MAX_CPU];// file descriptor per CPU for reading scaling_cur_freq
131+ uint32_t mCurrentkHz [MAX_CPU]; // current CPU frequency in kHz, not static to avoid a race
132+ static pthread_once_t sOnceControl ;
133+ static int sKernelMax ; // like MAX_CPU, but determined at runtime == cpu/kernel_max + 1
134+ static void init ();
111135};
112136
137+ } // namespace android
138+
113139#endif // _THREAD_CPU_USAGE_H
0 commit comments