summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2012-05-14 17:06:48 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-05-14 17:06:48 -0700
commitbd1132249479e52ddd128171da24327358e2191c (patch)
treea82cb977d87872dc02d6d759ff38c2638f79bda9
parent9cab4ca1ca74068e50192296badd0ae7a61f3927 (diff)
parent542af12d10e5923a6e811c72e2bbe4e7507b6448 (diff)
downloadframeworks_native-bd1132249479e52ddd128171da24327358e2191c.zip
frameworks_native-bd1132249479e52ddd128171da24327358e2191c.tar.gz
frameworks_native-bd1132249479e52ddd128171da24327358e2191c.tar.bz2
Merge "Fix log spam about CPU frequency on one device" into jb-dev
-rw-r--r--include/cpustats/ThreadCpuUsage.h3
-rw-r--r--libs/cpustats/ThreadCpuUsage.cpp41
2 files changed, 24 insertions, 20 deletions
diff --git a/include/cpustats/ThreadCpuUsage.h b/include/cpustats/ThreadCpuUsage.h
index 9cd93d8..9756844 100644
--- a/include/cpustats/ThreadCpuUsage.h
+++ b/include/cpustats/ThreadCpuUsage.h
@@ -131,7 +131,8 @@ private:
uint32_t mCurrentkHz[MAX_CPU]; // current CPU frequency in kHz, not static to avoid a race
static pthread_once_t sOnceControl;
static int sKernelMax; // like MAX_CPU, but determined at runtime == cpu/kernel_max + 1
- static void init();
+ static void init(); // called once at first ThreadCpuUsage construction
+ static pthread_mutex_t sMutex; // protects sScalingFds[] after initialization
};
} // namespace android
diff --git a/libs/cpustats/ThreadCpuUsage.cpp b/libs/cpustats/ThreadCpuUsage.cpp
index 99b4c83..637402a 100644
--- a/libs/cpustats/ThreadCpuUsage.cpp
+++ b/libs/cpustats/ThreadCpuUsage.cpp
@@ -165,6 +165,7 @@ void ThreadCpuUsage::resetElapsed()
int ThreadCpuUsage::sScalingFds[ThreadCpuUsage::MAX_CPU];
pthread_once_t ThreadCpuUsage::sOnceControl = PTHREAD_ONCE_INIT;
int ThreadCpuUsage::sKernelMax;
+pthread_mutex_t ThreadCpuUsage::sMutex = PTHREAD_MUTEX_INITIALIZER;
/*static*/
void ThreadCpuUsage::init()
@@ -195,27 +196,10 @@ void ThreadCpuUsage::init()
} else {
ALOGW("Can't open number of CPUs");
}
-
- // open fd to each frequency per CPU
-#define FREQ_SIZE 64
- char freq_path[FREQ_SIZE];
-#define FREQ_DIGIT 27
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE(MAX_CPU <= 10);
- strlcpy(freq_path, "/sys/devices/system/cpu/cpu?/cpufreq/scaling_cur_freq", sizeof(freq_path));
int i;
for (i = 0; i < MAX_CPU; ++i) {
sScalingFds[i] = -1;
}
- for (i = 0; i < sKernelMax; ++i) {
- freq_path[FREQ_DIGIT] = i + '0';
- fd = open(freq_path, O_RDONLY);
- if (fd >= 0) {
- // keep this fd until process exit
- sScalingFds[i] = fd;
- } else {
- ALOGW("Can't open CPU %d", i);
- }
- }
}
uint32_t ThreadCpuUsage::getCpukHz(int cpuNum)
@@ -224,10 +208,29 @@ uint32_t ThreadCpuUsage::getCpukHz(int cpuNum)
ALOGW("getCpukHz called with invalid CPU %d", cpuNum);
return 0;
}
+ // double-checked locking idiom is not broken for atomic values such as fd
int fd = sScalingFds[cpuNum];
if (fd < 0) {
- ALOGW("getCpukHz called for unopened CPU %d", cpuNum);
- return 0;
+ // some kernels can't open a scaling file until hot plug complete
+ pthread_mutex_lock(&sMutex);
+ fd = sScalingFds[cpuNum];
+ if (fd < 0) {
+#define FREQ_SIZE 64
+ char freq_path[FREQ_SIZE];
+#define FREQ_DIGIT 27
+ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(MAX_CPU <= 10);
+#define FREQ_PATH "/sys/devices/system/cpu/cpu?/cpufreq/scaling_cur_freq"
+ strlcpy(freq_path, FREQ_PATH, sizeof(freq_path));
+ freq_path[FREQ_DIGIT] = cpuNum + '0';
+ fd = open(freq_path, O_RDONLY | O_CLOEXEC);
+ // keep this fd until process exit or exec
+ sScalingFds[cpuNum] = fd;
+ }
+ pthread_mutex_unlock(&sMutex);
+ if (fd < 0) {
+ ALOGW("getCpukHz can't open CPU %d", cpuNum);
+ return 0;
+ }
}
#define KHZ_SIZE 12
char kHz[KHZ_SIZE]; // kHz base 10