1921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/* 2921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * Copyright (C) 2011 The Android Open Source Project 3921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * 4921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * you may not use this file except in compliance with the License. 6921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * You may obtain a copy of the License at 7921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * 8921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * 10921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * See the License for the specific language governing permissions and 14921832327619f7852b16f73a19504702c5a28a31Glenn Kasten * limitations under the License. 15921832327619f7852b16f73a19504702c5a28a31Glenn Kasten */ 16921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 17921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define LOG_TAG "ThreadCpuUsage" 18921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//#define LOG_NDEBUG 0 19921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 20921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include <errno.h> 21921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include <stdlib.h> 22921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include <time.h> 23921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 24921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include <utils/Debug.h> 25921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include <utils/Log.h> 26921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 27921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include <cpustats/ThreadCpuUsage.h> 28921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 29921832327619f7852b16f73a19504702c5a28a31Glenn Kastennamespace android { 30921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 31921832327619f7852b16f73a19504702c5a28a31Glenn Kastenbool ThreadCpuUsage::setEnabled(bool isEnabled) 32921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 33921832327619f7852b16f73a19504702c5a28a31Glenn Kasten bool wasEnabled = mIsEnabled; 34921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // only do something if there is a change 35921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (isEnabled != wasEnabled) { 36921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("setEnabled(%d)", isEnabled); 37921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int rc; 38921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // enabling 39921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (isEnabled) { 40921832327619f7852b16f73a19504702c5a28a31Glenn Kasten rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &mPreviousTs); 41921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (rc) { 42921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); 43921832327619f7852b16f73a19504702c5a28a31Glenn Kasten isEnabled = false; 44921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 45921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mWasEverEnabled = true; 46921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // record wall clock time at first enable 47921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (!mMonotonicKnown) { 48921832327619f7852b16f73a19504702c5a28a31Glenn Kasten rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs); 49921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (rc) { 50921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); 51921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 52921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mMonotonicKnown = true; 53921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 54921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 55921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 56921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // disabling 57921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 58921832327619f7852b16f73a19504702c5a28a31Glenn Kasten struct timespec ts; 59921832327619f7852b16f73a19504702c5a28a31Glenn Kasten rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); 60921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (rc) { 61921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); 62921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 63921832327619f7852b16f73a19504702c5a28a31Glenn Kasten long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL + 64921832327619f7852b16f73a19504702c5a28a31Glenn Kasten (ts.tv_nsec - mPreviousTs.tv_nsec); 65921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mAccumulator += delta; 66921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#if 0 67921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mPreviousTs = ts; 68921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#endif 69921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 70921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 71921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mIsEnabled = isEnabled; 72921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 73921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return wasEnabled; 74921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 75921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 76921832327619f7852b16f73a19504702c5a28a31Glenn Kastenbool ThreadCpuUsage::sampleAndEnable(double& ns) 77921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 78921832327619f7852b16f73a19504702c5a28a31Glenn Kasten bool ret; 79921832327619f7852b16f73a19504702c5a28a31Glenn Kasten bool wasEverEnabled = mWasEverEnabled; 80921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (enable()) { 81921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // already enabled, so add a new sample relative to previous 82921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return sample(ns); 83921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else if (wasEverEnabled) { 84921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // was disabled, but add sample for accumulated time while enabled 85921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = (double) mAccumulator; 86921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mAccumulator = 0; 87921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("sampleAndEnable %.0f", ns); 88921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return true; 89921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 90921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // first time called 91921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = 0.0; 92921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("sampleAndEnable false"); 93921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return false; 94921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 95921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 96921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 97921832327619f7852b16f73a19504702c5a28a31Glenn Kastenbool ThreadCpuUsage::sample(double &ns) 98921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 99921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (mWasEverEnabled) { 100921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (mIsEnabled) { 101921832327619f7852b16f73a19504702c5a28a31Glenn Kasten struct timespec ts; 102921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int rc; 103921832327619f7852b16f73a19504702c5a28a31Glenn Kasten rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); 104921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (rc) { 105921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); 106921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = 0.0; 107921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return false; 108921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 109921832327619f7852b16f73a19504702c5a28a31Glenn Kasten long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL + 110921832327619f7852b16f73a19504702c5a28a31Glenn Kasten (ts.tv_nsec - mPreviousTs.tv_nsec); 111921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mAccumulator += delta; 112921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mPreviousTs = ts; 113921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 114921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 115921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mWasEverEnabled = false; 116921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 117921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = (double) mAccumulator; 118921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("sample %.0f", ns); 119921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mAccumulator = 0; 120921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return true; 121921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 122921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't add sample because measurements have never been enabled"); 123921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = 0.0; 124921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return false; 125921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 126921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 127921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 128921832327619f7852b16f73a19504702c5a28a31Glenn Kastenlong long ThreadCpuUsage::elapsed() const 129921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 130921832327619f7852b16f73a19504702c5a28a31Glenn Kasten long long elapsed; 131921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (mMonotonicKnown) { 132921832327619f7852b16f73a19504702c5a28a31Glenn Kasten struct timespec ts; 133921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int rc; 134921832327619f7852b16f73a19504702c5a28a31Glenn Kasten rc = clock_gettime(CLOCK_MONOTONIC, &ts); 135921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (rc) { 136921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); 137921832327619f7852b16f73a19504702c5a28a31Glenn Kasten elapsed = 0; 138921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 139921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // mMonotonicTs is updated only at first enable and resetStatistics 140921832327619f7852b16f73a19504702c5a28a31Glenn Kasten elapsed = (ts.tv_sec - mMonotonicTs.tv_sec) * 1000000000LL + 141921832327619f7852b16f73a19504702c5a28a31Glenn Kasten (ts.tv_nsec - mMonotonicTs.tv_nsec); 142921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 143921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 144921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't compute elapsed time because measurements have never been enabled"); 145921832327619f7852b16f73a19504702c5a28a31Glenn Kasten elapsed = 0; 146921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 147921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("elapsed %lld", elapsed); 148921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return elapsed; 149921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 150921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 151921832327619f7852b16f73a19504702c5a28a31Glenn Kastenvoid ThreadCpuUsage::resetElapsed() 152921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 153921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("resetElapsed"); 154921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (mMonotonicKnown) { 155921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int rc; 156921832327619f7852b16f73a19504702c5a28a31Glenn Kasten rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs); 157921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (rc) { 158921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); 159921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mMonotonicKnown = false; 160921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 161921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 162921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 163921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 164921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/*static*/ 165921832327619f7852b16f73a19504702c5a28a31Glenn Kastenint ThreadCpuUsage::sScalingFds[ThreadCpuUsage::MAX_CPU]; 166921832327619f7852b16f73a19504702c5a28a31Glenn Kastenpthread_once_t ThreadCpuUsage::sOnceControl = PTHREAD_ONCE_INIT; 167921832327619f7852b16f73a19504702c5a28a31Glenn Kastenint ThreadCpuUsage::sKernelMax; 168921832327619f7852b16f73a19504702c5a28a31Glenn Kastenpthread_mutex_t ThreadCpuUsage::sMutex = PTHREAD_MUTEX_INITIALIZER; 169921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 170921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/*static*/ 171921832327619f7852b16f73a19504702c5a28a31Glenn Kastenvoid ThreadCpuUsage::init() 172921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 173921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // read the number of CPUs 174921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sKernelMax = 1; 175921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int fd = open("/sys/devices/system/cpu/kernel_max", O_RDONLY); 176921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (fd >= 0) { 177921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define KERNEL_MAX_SIZE 12 178921832327619f7852b16f73a19504702c5a28a31Glenn Kasten char kernelMax[KERNEL_MAX_SIZE]; 179921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ssize_t actual = read(fd, kernelMax, sizeof(kernelMax)); 180921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (actual >= 2 && kernelMax[actual-1] == '\n') { 181921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sKernelMax = atoi(kernelMax); 182921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (sKernelMax >= MAX_CPU - 1) { 183921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("kernel_max %d but MAX_CPU %d", sKernelMax, MAX_CPU); 184921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sKernelMax = MAX_CPU; 185921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else if (sKernelMax < 0) { 186921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("kernel_max invalid %d", sKernelMax); 187921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sKernelMax = 1; 188921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 189921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ++sKernelMax; 190921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("number of CPUs %d", sKernelMax); 191921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 192921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 193921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't read number of CPUs"); 194921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 195921832327619f7852b16f73a19504702c5a28a31Glenn Kasten (void) close(fd); 196921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 197921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't open number of CPUs"); 198921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 199921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int i; 200921832327619f7852b16f73a19504702c5a28a31Glenn Kasten for (i = 0; i < MAX_CPU; ++i) { 201921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sScalingFds[i] = -1; 202921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 203921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 204921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 205921832327619f7852b16f73a19504702c5a28a31Glenn Kastenuint32_t ThreadCpuUsage::getCpukHz(int cpuNum) 206921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 207921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (cpuNum < 0 || cpuNum >= MAX_CPU) { 208921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("getCpukHz called with invalid CPU %d", cpuNum); 209921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return 0; 210921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 211921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // double-checked locking idiom is not broken for atomic values such as fd 212921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int fd = sScalingFds[cpuNum]; 213921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (fd < 0) { 214921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // some kernels can't open a scaling file until hot plug complete 215921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pthread_mutex_lock(&sMutex); 216921832327619f7852b16f73a19504702c5a28a31Glenn Kasten fd = sScalingFds[cpuNum]; 217921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (fd < 0) { 218921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define FREQ_SIZE 64 219921832327619f7852b16f73a19504702c5a28a31Glenn Kasten char freq_path[FREQ_SIZE]; 220921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define FREQ_DIGIT 27 221921832327619f7852b16f73a19504702c5a28a31Glenn Kasten COMPILE_TIME_ASSERT_FUNCTION_SCOPE(MAX_CPU <= 10); 222921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define FREQ_PATH "/sys/devices/system/cpu/cpu?/cpufreq/scaling_cur_freq" 223921832327619f7852b16f73a19504702c5a28a31Glenn Kasten strlcpy(freq_path, FREQ_PATH, sizeof(freq_path)); 224921832327619f7852b16f73a19504702c5a28a31Glenn Kasten freq_path[FREQ_DIGIT] = cpuNum + '0'; 225921832327619f7852b16f73a19504702c5a28a31Glenn Kasten fd = open(freq_path, O_RDONLY | O_CLOEXEC); 226921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // keep this fd until process exit or exec 227921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sScalingFds[cpuNum] = fd; 228921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 229921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pthread_mutex_unlock(&sMutex); 230921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (fd < 0) { 231921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("getCpukHz can't open CPU %d", cpuNum); 232921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return 0; 233921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 234921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 235921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define KHZ_SIZE 12 236921832327619f7852b16f73a19504702c5a28a31Glenn Kasten char kHz[KHZ_SIZE]; // kHz base 10 237921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ssize_t actual = pread(fd, kHz, sizeof(kHz), (off_t) 0); 238921832327619f7852b16f73a19504702c5a28a31Glenn Kasten uint32_t ret; 239921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (actual >= 2 && kHz[actual-1] == '\n') { 240921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ret = atoi(kHz); 241921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 242921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ret = 0; 243921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 244921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (ret != mCurrentkHz[cpuNum]) { 245921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (ret > 0) { 246921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("CPU %d frequency %u kHz", cpuNum, ret); 247921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 248921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't read CPU %d frequency", cpuNum); 249921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 250921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mCurrentkHz[cpuNum] = ret; 251921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 252921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return ret; 253921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 254921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 255921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} // namespace android 256