ThreadCpuUsage.cpp revision 0b94dcd03d8764eab7f1fb00f0f1f37904732aa1
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;
1680b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten
1690b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten/*static*/
1700b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenvoid ThreadCpuUsage::init()
1710b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten{
1720b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    // read the number of CPUs
1730b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    sKernelMax = 1;
1740b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    int fd = open("/sys/devices/system/cpu/kernel_max", O_RDONLY);
1750b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    if (fd >= 0) {
1760b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#define KERNEL_MAX_SIZE 12
1770b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        char kernelMax[KERNEL_MAX_SIZE];
1780b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        ssize_t actual = read(fd, kernelMax, sizeof(kernelMax));
1790b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        if (actual >= 2 && kernelMax[actual-1] == '\n') {
1800b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            sKernelMax = atoi(kernelMax);
1810b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            if (sKernelMax >= MAX_CPU - 1) {
1820b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten                ALOGW("kernel_max %d but MAX_CPU %d", sKernelMax, MAX_CPU);
1830b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten                sKernelMax = MAX_CPU;
1840b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            } else if (sKernelMax < 0) {
1850b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten                ALOGW("kernel_max invalid %d", sKernelMax);
1860b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten                sKernelMax = 1;
1870b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            } else {
1880b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten                ++sKernelMax;
1890b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten                ALOGV("number of CPUs %d", sKernelMax);
1900b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            }
1910b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        } else {
1920b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            ALOGW("Can't read number of CPUs");
1930b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        }
1940b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        (void) close(fd);
1950b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    } else {
1960b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        ALOGW("Can't open number of CPUs");
1970b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    }
1980b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten
1990b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    // open fd to each frequency per CPU
2000b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#define FREQ_SIZE 64
2010b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    char freq_path[FREQ_SIZE];
2020b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#define FREQ_DIGIT 27
2030b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(MAX_CPU <= 10);
2040b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    strlcpy(freq_path, "/sys/devices/system/cpu/cpu?/cpufreq/scaling_cur_freq", sizeof(freq_path));
2050b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    int i;
2060b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    for (i = 0; i < MAX_CPU; ++i) {
2070b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        sScalingFds[i] = -1;
2080b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    }
2090b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    for (i = 0; i < sKernelMax; ++i) {
2100b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        freq_path[FREQ_DIGIT] = i + '0';
2110b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        fd = open(freq_path, O_RDONLY);
2120b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        if (fd >= 0) {
2130b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            // keep this fd until process exit
2140b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            sScalingFds[i] = fd;
2150b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        } else {
2160b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            ALOGW("Can't open CPU %d", i);
2170b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        }
2180b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    }
2190b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten}
2200b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten
2210b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kastenuint32_t ThreadCpuUsage::getCpukHz(int cpuNum)
2220b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten{
2230b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    if (cpuNum < 0 || cpuNum >= MAX_CPU) {
2240b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        ALOGW("getCpukHz called with invalid CPU %d", cpuNum);
2250b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        return 0;
2260b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    }
2270b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    int fd = sScalingFds[cpuNum];
2280b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    if (fd < 0) {
2290b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        ALOGW("getCpukHz called for unopened CPU %d", cpuNum);
2300b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        return 0;
2310b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    }
2320b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten#define KHZ_SIZE 12
2330b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    char kHz[KHZ_SIZE];   // kHz base 10
2340b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    ssize_t actual = pread(fd, kHz, sizeof(kHz), (off_t) 0);
2350b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    uint32_t ret;
2360b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    if (actual >= 2 && kHz[actual-1] == '\n') {
2370b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        ret = atoi(kHz);
2380b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    } else {
2390b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        ret = 0;
2400b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    }
2410b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    if (ret != mCurrentkHz[cpuNum]) {
2420b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        if (ret > 0) {
2430b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            ALOGV("CPU %d frequency %u kHz", cpuNum, ret);
2440b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        } else {
2450b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten            ALOGW("Can't read CPU %d frequency", cpuNum);
2460b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        }
2470b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten        mCurrentkHz[cpuNum] = ret;
2480b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    }
2490b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten    return ret;
2500b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten}
2510b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten
2520b94dcd03d8764eab7f1fb00f0f1f37904732aa1Glenn Kasten}   // namespace android
253