• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 #define LOG_TAG "Swappy"
18 
19 #include "CpuInfo.h"
20 
21 #include <limits>
22 #include <bitset>
23 #include <cstdlib>
24 #include <cstring>
25 
26 #include "Log.h"
27 
28 namespace {
29 
startsWith(std::string & mainStr,const char * toMatch)30 bool startsWith(std::string &mainStr, const char *toMatch) {
31     // std::string::find returns 0 if toMatch is found at beginning
32     return mainStr.find(toMatch) == 0;
33 }
34 
split(const std::string & s,char c)35 std::vector<std::string> split(const std::string& s, char c) {
36     std::vector<std::string> v;
37     std::string::size_type i = 0;
38     std::string::size_type j = s.find(c);
39 
40     while (j != std::string::npos) {
41         v.push_back(s.substr(i, j-i));
42         i = ++j;
43         j = s.find(c, j);
44 
45         if (j == std::string::npos) {
46             v.push_back(s.substr(i, s.length()));
47         }
48     }
49     return v;
50 }
51 
ReadFile(const std::string & path)52 std::string ReadFile(const std::string& path) {
53     char buf[10240];
54     FILE *fp = fopen(path.c_str(), "r");
55     if (fp == nullptr)
56         return std::string();
57 
58     fgets(buf, 10240, fp);
59     fclose(fp);
60     return std::string(buf);
61 }
62 
63 } // anonymous namespace
64 
65 namespace swappy {
66 
to_string(int n)67 std::string to_string(int n) {
68   constexpr int kBufSize = 12; // strlen("−2147483648")+1
69   static char buf[kBufSize];
70   snprintf(buf, kBufSize, "%d", n);
71   return buf;
72 }
73 
CpuInfo()74 CpuInfo::CpuInfo() {
75     const auto BUFFER_LENGTH = 10240;
76 
77     char buf[BUFFER_LENGTH];
78     FILE *fp = fopen("/proc/cpuinfo", "r");
79 
80     if (!fp) {
81         return;
82     }
83 
84     long mMaxFrequency = 0;
85     long mMinFrequency = std::numeric_limits<long>::max();
86 
87     while (fgets(buf, BUFFER_LENGTH, fp) != NULL) {
88         buf[strlen(buf) - 1] = '\0'; // eat the newline fgets() stores
89         std::string line = buf;
90 
91         if (startsWith(line, "processor")) {
92             Cpu core;
93             core.id = mCpus.size();
94 
95             auto core_path = std::string("/sys/devices/system/cpu/cpu")
96                              + to_string(core.id);
97 
98             auto package_id = ReadFile(core_path + "/topology/physical_package_id");
99             auto frequency = ReadFile(core_path + "/cpufreq/cpuinfo_max_freq");
100 
101             core.package_id = atol(package_id.c_str());
102             core.frequency = atol(frequency.c_str());
103 
104             mMinFrequency = std::min(mMinFrequency, core.frequency);
105             mMaxFrequency = std::max(mMaxFrequency, core.frequency);
106 
107             mCpus.push_back(core);
108         }
109         else if (startsWith(line, "Hardware")) {
110             mHardware = split(line, ':')[1];
111         }
112     }
113     fclose(fp);
114 
115     CPU_ZERO(&mLittleCoresMask);
116     CPU_ZERO(&mBigCoresMask);
117 
118     for (auto cpu : mCpus) {
119         if (cpu.frequency == mMinFrequency) {
120             ++mNumberOfLittleCores;
121             cpu.type = Cpu::Type::Little;
122             CPU_SET(cpu.id, &mLittleCoresMask);
123         }
124         else {
125             ++mNumberOfBigCores;
126             cpu.type = Cpu::Type::Big;
127             CPU_SET(cpu.id, &mBigCoresMask);
128         }
129     }
130 }
131 
getNumberOfCpus() const132 unsigned int CpuInfo::getNumberOfCpus() const {
133     return mCpus.size();
134 }
135 
getCpus() const136 const std::vector<CpuInfo::Cpu>& CpuInfo::getCpus() const {
137     return mCpus;
138 }
139 
getHardware() const140 const std::string CpuInfo::getHardware() const {
141     return mHardware;
142 }
143 
getNumberOfLittleCores() const144 unsigned int CpuInfo::getNumberOfLittleCores() const {
145     return mNumberOfLittleCores;
146 }
147 
getNumberOfBigCores() const148 unsigned int CpuInfo::getNumberOfBigCores() const {
149     return mNumberOfBigCores;
150 }
151 
getLittleCoresMask() const152 cpu_set_t CpuInfo::getLittleCoresMask() const {
153     return mLittleCoresMask;
154 }
155 
getBigCoresMask() const156 cpu_set_t CpuInfo::getBigCoresMask() const {
157     return mBigCoresMask;
158 }
159 
to_mask(cpu_set_t cpu_set)160 unsigned int to_mask(cpu_set_t cpu_set) {
161     std::bitset<32> mask;
162 
163     for (int i = 0; i < CPU_SETSIZE; ++i) {
164         if (CPU_ISSET(i, &cpu_set))
165             mask[i] = 1;
166     }
167     return (int) mask.to_ulong();
168 }
169 
170 } // namespace swappy
171