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> 229d014d04bd1e26b68ea979885ccbc6f131a7eda3Elliott Hughes#include <string.h> 23921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include <time.h> 24921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 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 wasEverEnabled = mWasEverEnabled; 79921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (enable()) { 80921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // already enabled, so add a new sample relative to previous 81921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return sample(ns); 82921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else if (wasEverEnabled) { 83921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // was disabled, but add sample for accumulated time while enabled 84921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = (double) mAccumulator; 85921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mAccumulator = 0; 86921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("sampleAndEnable %.0f", ns); 87921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return true; 88921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 89921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // first time called 90921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = 0.0; 91921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("sampleAndEnable false"); 92921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return false; 93921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 94921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 95921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 96921832327619f7852b16f73a19504702c5a28a31Glenn Kastenbool ThreadCpuUsage::sample(double &ns) 97921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 98921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (mWasEverEnabled) { 99921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (mIsEnabled) { 100921832327619f7852b16f73a19504702c5a28a31Glenn Kasten struct timespec ts; 101921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int rc; 102921832327619f7852b16f73a19504702c5a28a31Glenn Kasten rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); 103921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (rc) { 104921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); 105921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = 0.0; 106921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return false; 107921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 108921832327619f7852b16f73a19504702c5a28a31Glenn Kasten long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL + 109921832327619f7852b16f73a19504702c5a28a31Glenn Kasten (ts.tv_nsec - mPreviousTs.tv_nsec); 110921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mAccumulator += delta; 111921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mPreviousTs = ts; 112921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 113921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 114921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mWasEverEnabled = false; 115921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 116921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = (double) mAccumulator; 117921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("sample %.0f", ns); 118921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mAccumulator = 0; 119921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return true; 120921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 121921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't add sample because measurements have never been enabled"); 122921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ns = 0.0; 123921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return false; 124921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 125921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 126921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 127921832327619f7852b16f73a19504702c5a28a31Glenn Kastenlong long ThreadCpuUsage::elapsed() const 128921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 129921832327619f7852b16f73a19504702c5a28a31Glenn Kasten long long elapsed; 130921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (mMonotonicKnown) { 131921832327619f7852b16f73a19504702c5a28a31Glenn Kasten struct timespec ts; 132921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int rc; 133921832327619f7852b16f73a19504702c5a28a31Glenn Kasten rc = clock_gettime(CLOCK_MONOTONIC, &ts); 134921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (rc) { 135921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); 136921832327619f7852b16f73a19504702c5a28a31Glenn Kasten elapsed = 0; 137921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 138921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // mMonotonicTs is updated only at first enable and resetStatistics 139921832327619f7852b16f73a19504702c5a28a31Glenn Kasten elapsed = (ts.tv_sec - mMonotonicTs.tv_sec) * 1000000000LL + 140921832327619f7852b16f73a19504702c5a28a31Glenn Kasten (ts.tv_nsec - mMonotonicTs.tv_nsec); 141921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 142921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 143921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't compute elapsed time because measurements have never been enabled"); 144921832327619f7852b16f73a19504702c5a28a31Glenn Kasten elapsed = 0; 145921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 146921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("elapsed %lld", elapsed); 147921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return elapsed; 148921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 149921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 150921832327619f7852b16f73a19504702c5a28a31Glenn Kastenvoid ThreadCpuUsage::resetElapsed() 151921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 152921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("resetElapsed"); 153921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (mMonotonicKnown) { 154921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int rc; 155921832327619f7852b16f73a19504702c5a28a31Glenn Kasten rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs); 156921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (rc) { 157921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); 158921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mMonotonicKnown = false; 159921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 160921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 161921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 162921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 163921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/*static*/ 164921832327619f7852b16f73a19504702c5a28a31Glenn Kastenint ThreadCpuUsage::sScalingFds[ThreadCpuUsage::MAX_CPU]; 165921832327619f7852b16f73a19504702c5a28a31Glenn Kastenpthread_once_t ThreadCpuUsage::sOnceControl = PTHREAD_ONCE_INIT; 166921832327619f7852b16f73a19504702c5a28a31Glenn Kastenint ThreadCpuUsage::sKernelMax; 167921832327619f7852b16f73a19504702c5a28a31Glenn Kastenpthread_mutex_t ThreadCpuUsage::sMutex = PTHREAD_MUTEX_INITIALIZER; 168921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 169921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/*static*/ 170921832327619f7852b16f73a19504702c5a28a31Glenn Kastenvoid ThreadCpuUsage::init() 171921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 172921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // read the number of CPUs 173921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sKernelMax = 1; 174921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int fd = open("/sys/devices/system/cpu/kernel_max", O_RDONLY); 175921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (fd >= 0) { 176921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define KERNEL_MAX_SIZE 12 177921832327619f7852b16f73a19504702c5a28a31Glenn Kasten char kernelMax[KERNEL_MAX_SIZE]; 178921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ssize_t actual = read(fd, kernelMax, sizeof(kernelMax)); 179921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (actual >= 2 && kernelMax[actual-1] == '\n') { 180921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sKernelMax = atoi(kernelMax); 181921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (sKernelMax >= MAX_CPU - 1) { 182921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("kernel_max %d but MAX_CPU %d", sKernelMax, MAX_CPU); 183921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sKernelMax = MAX_CPU; 184921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else if (sKernelMax < 0) { 185921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("kernel_max invalid %d", sKernelMax); 186921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sKernelMax = 1; 187921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 188921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ++sKernelMax; 189921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("number of CPUs %d", sKernelMax); 190921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 191921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 192921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't read number of CPUs"); 193921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 194921832327619f7852b16f73a19504702c5a28a31Glenn Kasten (void) close(fd); 195921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 196921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't open number of CPUs"); 197921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 198921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int i; 199921832327619f7852b16f73a19504702c5a28a31Glenn Kasten for (i = 0; i < MAX_CPU; ++i) { 200921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sScalingFds[i] = -1; 201921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 202921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 203921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 204921832327619f7852b16f73a19504702c5a28a31Glenn Kastenuint32_t ThreadCpuUsage::getCpukHz(int cpuNum) 205921832327619f7852b16f73a19504702c5a28a31Glenn Kasten{ 206921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (cpuNum < 0 || cpuNum >= MAX_CPU) { 207921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("getCpukHz called with invalid CPU %d", cpuNum); 208921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return 0; 209921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 210921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // double-checked locking idiom is not broken for atomic values such as fd 211921832327619f7852b16f73a19504702c5a28a31Glenn Kasten int fd = sScalingFds[cpuNum]; 212921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (fd < 0) { 213921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // some kernels can't open a scaling file until hot plug complete 214921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pthread_mutex_lock(&sMutex); 215921832327619f7852b16f73a19504702c5a28a31Glenn Kasten fd = sScalingFds[cpuNum]; 216921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (fd < 0) { 217921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define FREQ_SIZE 64 218921832327619f7852b16f73a19504702c5a28a31Glenn Kasten char freq_path[FREQ_SIZE]; 219921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define FREQ_DIGIT 27 220fc3afda925f4b493ef68a745fdd753d9330316adMark Salyzyn static_assert(MAX_CPU <= 10, "MAX_CPU too large"); 221921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define FREQ_PATH "/sys/devices/system/cpu/cpu?/cpufreq/scaling_cur_freq" 222921832327619f7852b16f73a19504702c5a28a31Glenn Kasten strlcpy(freq_path, FREQ_PATH, sizeof(freq_path)); 223921832327619f7852b16f73a19504702c5a28a31Glenn Kasten freq_path[FREQ_DIGIT] = cpuNum + '0'; 224921832327619f7852b16f73a19504702c5a28a31Glenn Kasten fd = open(freq_path, O_RDONLY | O_CLOEXEC); 225921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // keep this fd until process exit or exec 226921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sScalingFds[cpuNum] = fd; 227921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 228921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pthread_mutex_unlock(&sMutex); 229921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (fd < 0) { 230921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("getCpukHz can't open CPU %d", cpuNum); 231921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return 0; 232921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 233921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 234921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#define KHZ_SIZE 12 235921832327619f7852b16f73a19504702c5a28a31Glenn Kasten char kHz[KHZ_SIZE]; // kHz base 10 236921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ssize_t actual = pread(fd, kHz, sizeof(kHz), (off_t) 0); 237921832327619f7852b16f73a19504702c5a28a31Glenn Kasten uint32_t ret; 238921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (actual >= 2 && kHz[actual-1] == '\n') { 239921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ret = atoi(kHz); 240921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 241921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ret = 0; 242921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 243921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (ret != mCurrentkHz[cpuNum]) { 244921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (ret > 0) { 245921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGV("CPU %d frequency %u kHz", cpuNum, ret); 246921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } else { 247921832327619f7852b16f73a19504702c5a28a31Glenn Kasten ALOGW("Can't read CPU %d frequency", cpuNum); 248921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 249921832327619f7852b16f73a19504702c5a28a31Glenn Kasten mCurrentkHz[cpuNum] = ret; 250921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 251921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return ret; 252921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 253921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 254921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} // namespace android 255