Home | History | Annotate | Download | only in cpustats
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <errno.h>
     18 #include <time.h>
     19 
     20 #include <utils/Log.h>
     21 
     22 #include <cpustats/ThreadCpuUsage.h>
     23 
     24 bool ThreadCpuUsage::setEnabled(bool isEnabled)
     25 {
     26     bool wasEnabled = mIsEnabled;
     27     // only do something if there is a change
     28     if (isEnabled != wasEnabled) {
     29         int rc;
     30         // enabling
     31         if (isEnabled) {
     32             rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &mPreviousTs);
     33             if (rc) {
     34                 LOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno);
     35                 isEnabled = false;
     36             } else {
     37                 mWasEverEnabled = true;
     38                 // record wall clock time at first enable
     39                 if (!mMonotonicKnown) {
     40                     rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs);
     41                     if (rc) {
     42                         LOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno);
     43                     } else {
     44                         mMonotonicKnown = true;
     45                     }
     46                 }
     47             }
     48         // disabling
     49         } else {
     50             struct timespec ts;
     51             rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
     52             if (rc) {
     53                 LOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno);
     54             } else {
     55                 long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL +
     56                         (ts.tv_nsec - mPreviousTs.tv_nsec);
     57                 mAccumulator += delta;
     58 #if 0
     59                 mPreviousTs = ts;
     60 #endif
     61             }
     62         }
     63         mIsEnabled = isEnabled;
     64     }
     65     return wasEnabled;
     66 }
     67 
     68 void ThreadCpuUsage::sampleAndEnable()
     69 {
     70     bool wasEverEnabled = mWasEverEnabled;
     71     if (enable()) {
     72         // already enabled, so add a new sample relative to previous
     73         sample();
     74     } else if (wasEverEnabled) {
     75         // was disabled, but add sample for accumulated time while enabled
     76         mStatistics.sample((double) mAccumulator);
     77         mAccumulator = 0;
     78     }
     79 }
     80 
     81 void ThreadCpuUsage::sample()
     82 {
     83     if (mWasEverEnabled) {
     84         if (mIsEnabled) {
     85             struct timespec ts;
     86             int rc;
     87             rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
     88             if (rc) {
     89                 LOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno);
     90             } else {
     91                 long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL +
     92                         (ts.tv_nsec - mPreviousTs.tv_nsec);
     93                 mAccumulator += delta;
     94                 mPreviousTs = ts;
     95             }
     96         } else {
     97             mWasEverEnabled = false;
     98         }
     99         mStatistics.sample((double) mAccumulator);
    100         mAccumulator = 0;
    101     } else {
    102         LOGW("Can't add sample because measurements have never been enabled");
    103     }
    104 }
    105 
    106 long long ThreadCpuUsage::elapsed() const
    107 {
    108     long long elapsed;
    109     if (mMonotonicKnown) {
    110         struct timespec ts;
    111         int rc;
    112         rc = clock_gettime(CLOCK_MONOTONIC, &ts);
    113         if (rc) {
    114             LOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno);
    115             elapsed = 0;
    116         } else {
    117             // mMonotonicTs is updated only at first enable and resetStatistics
    118             elapsed = (ts.tv_sec - mMonotonicTs.tv_sec) * 1000000000LL +
    119                     (ts.tv_nsec - mMonotonicTs.tv_nsec);
    120         }
    121     } else {
    122         LOGW("Can't compute elapsed time because measurements have never been enabled");
    123         elapsed = 0;
    124     }
    125     return elapsed;
    126 }
    127 
    128 void ThreadCpuUsage::resetStatistics()
    129 {
    130     mStatistics.reset();
    131     if (mMonotonicKnown) {
    132         int rc;
    133         rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs);
    134         if (rc) {
    135             LOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno);
    136             mMonotonicKnown = false;
    137         }
    138     }
    139 }
    140