C++程序  |  171行  |  4.17 KB

/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "Swappy"

#include "CpuInfo.h"

#include <limits>
#include <bitset>
#include <cstdlib>
#include <cstring>

#include "Log.h"

namespace {

bool startsWith(std::string &mainStr, const char *toMatch) {
    // std::string::find returns 0 if toMatch is found at beginning
    return mainStr.find(toMatch) == 0;
}

std::vector<std::string> split(const std::string& s, char c) {
    std::vector<std::string> v;
    std::string::size_type i = 0;
    std::string::size_type j = s.find(c);

    while (j != std::string::npos) {
        v.push_back(s.substr(i, j-i));
        i = ++j;
        j = s.find(c, j);

        if (j == std::string::npos) {
            v.push_back(s.substr(i, s.length()));
        }
    }
    return v;
}

std::string ReadFile(const std::string& path) {
    char buf[10240];
    FILE *fp = fopen(path.c_str(), "r");
    if (fp == nullptr)
        return std::string();

    fgets(buf, 10240, fp);
    fclose(fp);
    return std::string(buf);
}

} // anonymous namespace

namespace swappy {

std::string to_string(int n) {
  constexpr int kBufSize = 12; // strlen("−2147483648")+1
  static char buf[kBufSize];
  snprintf(buf, kBufSize, "%d", n);
  return buf;
}

CpuInfo::CpuInfo() {
    const auto BUFFER_LENGTH = 10240;

    char buf[BUFFER_LENGTH];
    FILE *fp = fopen("/proc/cpuinfo", "r");

    if (!fp) {
        return;
    }

    long mMaxFrequency = 0;
    long mMinFrequency = std::numeric_limits<long>::max();

    while (fgets(buf, BUFFER_LENGTH, fp) != NULL) {
        buf[strlen(buf) - 1] = '\0'; // eat the newline fgets() stores
        std::string line = buf;

        if (startsWith(line, "processor")) {
            Cpu core;
            core.id = mCpus.size();

            auto core_path = std::string("/sys/devices/system/cpu/cpu")
                             + to_string(core.id);

            auto package_id = ReadFile(core_path + "/topology/physical_package_id");
            auto frequency = ReadFile(core_path + "/cpufreq/cpuinfo_max_freq");

            core.package_id = atol(package_id.c_str());
            core.frequency = atol(frequency.c_str());

            mMinFrequency = std::min(mMinFrequency, core.frequency);
            mMaxFrequency = std::max(mMaxFrequency, core.frequency);

            mCpus.push_back(core);
        }
        else if (startsWith(line, "Hardware")) {
            mHardware = split(line, ':')[1];
        }
    }
    fclose(fp);

    CPU_ZERO(&mLittleCoresMask);
    CPU_ZERO(&mBigCoresMask);

    for (auto cpu : mCpus) {
        if (cpu.frequency == mMinFrequency) {
            ++mNumberOfLittleCores;
            cpu.type = Cpu::Type::Little;
            CPU_SET(cpu.id, &mLittleCoresMask);
        }
        else {
            ++mNumberOfBigCores;
            cpu.type = Cpu::Type::Big;
            CPU_SET(cpu.id, &mBigCoresMask);
        }
    }
}

unsigned int CpuInfo::getNumberOfCpus() const {
    return mCpus.size();
}

const std::vector<CpuInfo::Cpu>& CpuInfo::getCpus() const {
    return mCpus;
}

const std::string CpuInfo::getHardware() const {
    return mHardware;
}

unsigned int CpuInfo::getNumberOfLittleCores() const {
    return mNumberOfLittleCores;
}

unsigned int CpuInfo::getNumberOfBigCores() const {
    return mNumberOfBigCores;
}

cpu_set_t CpuInfo::getLittleCoresMask() const {
    return mLittleCoresMask;
}

cpu_set_t CpuInfo::getBigCoresMask() const {
    return mBigCoresMask;
}

unsigned int to_mask(cpu_set_t cpu_set) {
    std::bitset<32> mask;

    for (int i = 0; i < CPU_SETSIZE; ++i) {
        if (CPU_ISSET(i, &cpu_set))
            mask[i] = 1;
    }
    return (int) mask.to_ulong();
}

} // namespace swappy