[go: nahoru, domu]

blob: ecfd672fc7d9e6c8d1b03e2395bcd68a09cdce14 [file] [log] [blame]
/*
* Copyright 2019 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.
*/
package androidx.benchmark
import android.util.Log
import java.io.File
import java.io.IOException
internal object CpuInfo {
private const val TAG = "Benchmark"
val coreDirs: List<CoreDir>
val locked: Boolean
val maxFreqHz: Long
/**
* Representation of clock info in `/sys/devices/system/cpu/cpu#/`
*/
data class CoreDir(
// online, or true if can't access
val online: Boolean,
// sorted list of scaling_available_frequencies, or listOf(-1) if can't access
val availableFreqs: List<Int>,
// scaling_min_freq, or -1 if can't access
val currentMinFreq: Int,
// cpuinfo_max_freq, or -1 if can't access
val maxFreqKhz: Long
)
init {
val cpuDir = File("/sys/devices/system/cpu")
coreDirs = cpuDir.list { current, name ->
File(current, name).isDirectory && name.matches(Regex("^cpu[0-9]+"))
}?.map {
val path = "${cpuDir.path}/$it"
CoreDir(
// online, or true if can't access
online = readFileTextOrNull("$path/online") != "0",
// sorted list of scaling_available_frequencies, or listOf(-1) if can't access
availableFreqs = readFileTextOrNull("$path/cpufreq/scaling_available_frequencies")
?.split(Regex("\\s+"))
?.filter { it.isNotBlank() }
?.map { Integer.parseInt(it) }
?.sorted()
?: listOf(-1),
// scaling_min_freq, or -1 if can't access
currentMinFreq = readFileTextOrNull("$path/cpufreq/scaling_min_freq")?.toInt()
?: -1,
maxFreqKhz = readFileTextOrNull("$path/cpufreq/cpuinfo_max_freq")?.toLong() ?: -1L
)
} ?: emptyList()
maxFreqHz = coreDirs
.filter { it.maxFreqKhz != -1L }
.maxByOrNull { it.maxFreqKhz }
?.maxFreqKhz?.times(1000) ?: -1
locked = isCpuLocked(coreDirs)
coreDirs.forEachIndexed { index, coreDir ->
Log.d(TAG, "cpu$index $coreDir")
}
}
fun isCpuLocked(coreDirs: List<CoreDir>): Boolean {
val onlineCores = coreDirs.filter { it.online }
if (onlineCores.any {
it.availableFreqs.maxOrNull() != onlineCores[0].availableFreqs.maxOrNull()
}
) {
Log.d(TAG, "Clocks not locked: cores with different max frequencies")
return false
}
if (onlineCores.any { it.currentMinFreq != onlineCores[0].currentMinFreq }) {
Log.d(TAG, "Clocks not locked: cores with different current min freq")
return false
}
if (onlineCores.any { it.availableFreqs.minOrNull() == it.currentMinFreq }) {
Log.d(TAG, "Clocks not locked: online cores with min freq == min avail freq")
return false
}
return true
}
/**
* Read the text of a file as a String, null if file doesn't exist or can't be read.
*/
private fun readFileTextOrNull(path: String): String? {
try {
File(path).run {
return if (exists()) {
readText().trim()
} else null
}
} catch (e: IOException) {
return null
}
}
}