10b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten/* 20b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * Copyright (C) 2011 The Android Open Source Project 30b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * 40b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 50b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * you may not use this file except in compliance with the License. 60b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * You may obtain a copy of the License at 70b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * 80b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 90b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * 100b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * Unless required by applicable law or agreed to in writing, software 110b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 120b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * See the License for the specific language governing permissions and 140b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten * limitations under the License. 150b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten */ 160b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 170b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#define LOG_TAG "ThreadCpuUsage" 180b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten//#define LOG_NDEBUG 0 190b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 200b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#include <errno.h> 210b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#include <stdlib.h> 220b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#include <time.h> 230b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 240b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#include <utils/Debug.h> 250b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#include <utils/Log.h> 260b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 270b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#include <cpustats/ThreadCpuUsage.h> 280b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 290b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastennamespace android { 300b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 310b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenbool ThreadCpuUsage::setEnabled(bool isEnabled) 320b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten{ 330b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten bool wasEnabled = mIsEnabled; 340b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten // only do something if there is a change 350b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (isEnabled != wasEnabled) { 360b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGV("setEnabled(%d)", isEnabled); 370b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten int rc; 380b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten // enabling 390b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (isEnabled) { 400b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &mPreviousTs); 410b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (rc) { 420b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); 430b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten isEnabled = false; 440b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 450b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mWasEverEnabled = true; 460b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten // record wall clock time at first enable 470b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (!mMonotonicKnown) { 480b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs); 490b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (rc) { 500b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); 510b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 520b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mMonotonicKnown = true; 530b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 540b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 550b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 560b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten // disabling 570b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 580b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten struct timespec ts; 590b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); 600b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (rc) { 610b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); 620b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 630b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL + 640b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten (ts.tv_nsec - mPreviousTs.tv_nsec); 650b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mAccumulator += delta; 660b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#if 0 670b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mPreviousTs = ts; 680b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#endif 690b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 700b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 710b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mIsEnabled = isEnabled; 720b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 730b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return wasEnabled; 740b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten} 750b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 760b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenbool ThreadCpuUsage::sampleAndEnable(double& ns) 770b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten{ 780b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten bool ret; 790b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten bool wasEverEnabled = mWasEverEnabled; 800b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (enable()) { 810b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten // already enabled, so add a new sample relative to previous 820b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return sample(ns); 830b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else if (wasEverEnabled) { 840b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten // was disabled, but add sample for accumulated time while enabled 850b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ns = (double) mAccumulator; 860b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mAccumulator = 0; 870b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGV("sampleAndEnable %.0f", ns); 880b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return true; 890b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 900b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten // first time called 910b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ns = 0.0; 920b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGV("sampleAndEnable false"); 930b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return false; 940b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 950b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten} 960b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 970b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenbool ThreadCpuUsage::sample(double &ns) 980b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten{ 990b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (mWasEverEnabled) { 1000b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (mIsEnabled) { 1010b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten struct timespec ts; 1020b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten int rc; 1030b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); 1040b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (rc) { 1050b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); 1060b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ns = 0.0; 1070b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return false; 1080b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 1090b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL + 1100b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten (ts.tv_nsec - mPreviousTs.tv_nsec); 1110b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mAccumulator += delta; 1120b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mPreviousTs = ts; 1130b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1140b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 1150b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mWasEverEnabled = false; 1160b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1170b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ns = (double) mAccumulator; 1180b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGV("sample %.0f", ns); 1190b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mAccumulator = 0; 1200b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return true; 1210b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 1220b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGW("Can't add sample because measurements have never been enabled"); 1230b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ns = 0.0; 1240b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return false; 1250b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1260b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten} 1270b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 1280b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenlong long ThreadCpuUsage::elapsed() const 1290b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten{ 1300b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten long long elapsed; 1310b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (mMonotonicKnown) { 1320b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten struct timespec ts; 1330b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten int rc; 1340b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten rc = clock_gettime(CLOCK_MONOTONIC, &ts); 1350b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (rc) { 1360b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); 1370b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten elapsed = 0; 1380b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 1390b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten // mMonotonicTs is updated only at first enable and resetStatistics 1400b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten elapsed = (ts.tv_sec - mMonotonicTs.tv_sec) * 1000000000LL + 1410b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten (ts.tv_nsec - mMonotonicTs.tv_nsec); 1420b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1430b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 1440b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGW("Can't compute elapsed time because measurements have never been enabled"); 1450b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten elapsed = 0; 1460b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1470b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGV("elapsed %lld", elapsed); 1480b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return elapsed; 1490b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten} 1500b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 1510b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenvoid ThreadCpuUsage::resetElapsed() 1520b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten{ 1530b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGV("resetElapsed"); 1540b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (mMonotonicKnown) { 1550b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten int rc; 1560b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs); 1570b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (rc) { 1580b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); 1590b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mMonotonicKnown = false; 1600b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1610b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1620b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten} 1630b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 1640b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten/*static*/ 1650b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenint ThreadCpuUsage::sScalingFds[ThreadCpuUsage::MAX_CPU]; 1660b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenpthread_once_t ThreadCpuUsage::sOnceControl = PTHREAD_ONCE_INIT; 1670b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenint ThreadCpuUsage::sKernelMax; 168542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kastenpthread_mutex_t ThreadCpuUsage::sMutex = PTHREAD_MUTEX_INITIALIZER; 1690b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 1700b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten/*static*/ 1710b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenvoid ThreadCpuUsage::init() 1720b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten{ 1730b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten // read the number of CPUs 1740b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten sKernelMax = 1; 1750b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten int fd = open("/sys/devices/system/cpu/kernel_max", O_RDONLY); 1760b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (fd >= 0) { 1770b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#define KERNEL_MAX_SIZE 12 1780b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten char kernelMax[KERNEL_MAX_SIZE]; 1790b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ssize_t actual = read(fd, kernelMax, sizeof(kernelMax)); 1800b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (actual >= 2 && kernelMax[actual-1] == '\n') { 1810b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten sKernelMax = atoi(kernelMax); 1820b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (sKernelMax >= MAX_CPU - 1) { 1830b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGW("kernel_max %d but MAX_CPU %d", sKernelMax, MAX_CPU); 1840b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten sKernelMax = MAX_CPU; 1850b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else if (sKernelMax < 0) { 1860b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGW("kernel_max invalid %d", sKernelMax); 1870b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten sKernelMax = 1; 1880b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 1890b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ++sKernelMax; 1900b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGV("number of CPUs %d", sKernelMax); 1910b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1920b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 1930b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGW("Can't read number of CPUs"); 1940b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1950b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten (void) close(fd); 1960b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 1970b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGW("Can't open number of CPUs"); 1980b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 1990b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten int i; 2000b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten for (i = 0; i < MAX_CPU; ++i) { 2010b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten sScalingFds[i] = -1; 2020b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 2030b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten} 2040b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 2050b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenuint32_t ThreadCpuUsage::getCpukHz(int cpuNum) 2060b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten{ 2070b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (cpuNum < 0 || cpuNum >= MAX_CPU) { 2080b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGW("getCpukHz called with invalid CPU %d", cpuNum); 2090b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return 0; 2100b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 211542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten // double-checked locking idiom is not broken for atomic values such as fd 2120b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten int fd = sScalingFds[cpuNum]; 2130b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (fd < 0) { 214542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten // some kernels can't open a scaling file until hot plug complete 215542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten pthread_mutex_lock(&sMutex); 216542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten fd = sScalingFds[cpuNum]; 217542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten if (fd < 0) { 218542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten#define FREQ_SIZE 64 219542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten char freq_path[FREQ_SIZE]; 220542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten#define FREQ_DIGIT 27 221542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten COMPILE_TIME_ASSERT_FUNCTION_SCOPE(MAX_CPU <= 10); 222542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten#define FREQ_PATH "/sys/devices/system/cpu/cpu?/cpufreq/scaling_cur_freq" 223542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten strlcpy(freq_path, FREQ_PATH, sizeof(freq_path)); 224542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten freq_path[FREQ_DIGIT] = cpuNum + '0'; 225542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten fd = open(freq_path, O_RDONLY | O_CLOEXEC); 226542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten // keep this fd until process exit or exec 227542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten sScalingFds[cpuNum] = fd; 228542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten } 229542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten pthread_mutex_unlock(&sMutex); 230542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten if (fd < 0) { 231542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten ALOGW("getCpukHz can't open CPU %d", cpuNum); 232542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten return 0; 233542af12d10e5923a6e811c72e2bbe4e7507b6448Glenn Kasten } 2340b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 2350b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#define KHZ_SIZE 12 2360b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten char kHz[KHZ_SIZE]; // kHz base 10 2370b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ssize_t actual = pread(fd, kHz, sizeof(kHz), (off_t) 0); 2380b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten uint32_t ret; 2390b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (actual >= 2 && kHz[actual-1] == '\n') { 2400b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ret = atoi(kHz); 2410b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 2420b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ret = 0; 2430b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 2440b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (ret != mCurrentkHz[cpuNum]) { 2450b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten if (ret > 0) { 2460b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGV("CPU %d frequency %u kHz", cpuNum, ret); 2470b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } else { 2480b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten ALOGW("Can't read CPU %d frequency", cpuNum); 2490b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 2500b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten mCurrentkHz[cpuNum] = ret; 2510b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten } 2520b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten return ret; 2530b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten} 2540b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten 2550b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten} // namespace android 256