Fix log spam about CPU frequency on one device

Previous kernels have allowed opening the CPU frequency file regardless
whether the CPU is up or not.  This fixes some log spam on one device
with dynamic hot plug CPU feature, which does not allow opening the CPU
frequency file if CPU is down.

Also, since the file descriptors are global and have long lives, add
the close-on-exec flag.

Change-Id: Ia14a2b9e20038dfb96a573920176a47a96bd3f5a
This commit is contained in:
Glenn Kasten 2012-05-14 10:49:17 -07:00
parent b194ec926b
commit 542af12d10
2 changed files with 24 additions and 20 deletions

View File

@ -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

View File

@ -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