Skip to content

Commit

Permalink
refactor: 重写cpu控制器
Browse files Browse the repository at this point in the history
  • Loading branch information
shadow3aaa committed Jun 29, 2024
1 parent 4b86bc4 commit f81b422
Show file tree
Hide file tree
Showing 17 changed files with 213 additions and 771 deletions.
1 change: 0 additions & 1 deletion module/games.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[config]
keep_std = true
userspace_governor = false
scene_game_list = true

[game_list]
Expand Down
81 changes: 81 additions & 0 deletions src/cpu_common/cpu_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use std::{
fs,
os::unix::fs::PermissionsExt,
path::{Path, PathBuf},
};

use anyhow::Result;

#[derive(Debug)]
pub struct Info {
pub policy: i32,
path: PathBuf,
pub freqs: Vec<isize>,
}

impl Info {
pub fn new(path: PathBuf) -> Result<Self> {
let policy = path.file_name().unwrap().to_str().unwrap()[6..].parse()?;

let mut freqs: Vec<_> = fs::read_to_string(path.join("scaling_available_frequencies"))?
.split_whitespace()
.map(|f| f.parse().unwrap())
.collect();

if let Ok(boost_freqs) = fs::read_to_string(path.join("scaling_boost_frequencies")) {
let boost_freqs = boost_freqs
.split_whitespace()
.map(|f| f.parse::<isize>().unwrap());
freqs.extend(boost_freqs);
}

freqs.sort_unstable();

Ok(Self {
policy,
path,
freqs,
})
}

pub fn write_freq(&self, freq: isize) -> Result<()> {
let freq = freq.to_string();
let max_freq_path = self.max_freq_path();
unlock_write(max_freq_path, &freq)?;

if self.policy != 0 {
let min_freq_path = self.min_freq_path();
unlock_write(min_freq_path, &freq)?;
}

Ok(())
}

pub fn reset_freq(&self) -> Result<()> {
let max_freq_path = self.max_freq_path();
let min_freq_path = self.min_freq_path();

unlock_write(max_freq_path, self.freqs.last().unwrap().to_string())?;
unlock_write(min_freq_path, self.freqs.first().unwrap().to_string())?;

Ok(())
}

fn max_freq_path(&self) -> PathBuf {
self.path.join("scaling_max_freq")
}

fn min_freq_path(&self) -> PathBuf {
self.path.join("scaling_min_freq")
}
}

fn unlock_write<P, C>(path: P, contents: C) -> Result<()>
where
P: AsRef<Path>,
C: AsRef<[u8]>,
{
let _ = fs::set_permissions(path.as_ref(), PermissionsExt::from_mode(0o644));
fs::write(path, contents)?;
Ok(())
}
160 changes: 75 additions & 85 deletions src/cpu_common/mod.rs
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,117 +1,107 @@
// Copyright 2023 [email protected]
//
// 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.

mod policy;

use std::{ffi::OsStr, fs, time::Duration};
mod cpu_info;

use std::{fs, time::Duration};

use anyhow::Result;

use cpu_info::Info;
#[cfg(debug_assertions)]
use log::debug;
use log::error;

use crate::framework::prelude::*;
use api::ApiV0;
use policy::Policy;

pub type Freq = usize; // khz
use crate::{api::ApiV0, Extension};

const BASE_STEP: Freq = 700_000;
const JANK_STEP: Freq = 500_000;
const BIG_JANK_STEP: Freq = 800_000;
const BASE_FREQ: isize = 700_000;

#[derive(Debug)]
pub struct CpuCommon {
policies: Vec<Policy>,
pub struct Controller {
max_freq: isize,
min_freq: isize,
policy_freq: isize,
cpu_infos: Vec<Info>,
}

impl CpuCommon {
pub fn new(c: &Config) -> Result<Self> {
let policies: Vec<_> = fs::read_dir("/sys/devices/system/cpu/cpufreq")?
.filter_map(|d| Some(d.ok()?.path()))
.filter(|p| p.is_dir())
.filter(|p| {
p.file_name()
.and_then(OsStr::to_str)
.unwrap()
.contains("policy")
impl Controller {
pub fn new() -> Result<Self> {
let cpu_infos: Vec<_> = fs::read_dir("/sys/devices/system/cpu/cpufreq")?
.map(|entry| entry.unwrap().path())
.filter(|path| {
path.is_dir()
&& path
.file_name()
.unwrap()
.to_str()
.unwrap()
.starts_with("policy")
})
.map(|p| Policy::new(c, p))
.map(Result::unwrap)
.map(|path| Info::new(path).unwrap())
.collect();

Ok(Self { policies })
}

pub fn limit(&self, target_fps: u32, frame: Duration, target: Duration) {
let target = target.as_nanos() as Freq;
let frame = frame.as_nanos() as Freq;

let step = BASE_STEP * (target - frame) / target;
let step = step * 120 / target_fps as Freq;

#[cfg(debug_assertions)]
debug!("step: -{step}khz");

self.decrease_fas_freq(step);
}

pub fn release(&self, target_fps: u32, frame: Duration, target: Duration) {
let target = target.as_nanos() as Freq;
let frame = frame.as_nanos() as Freq;

let step = BASE_STEP * (frame - target) / target;
let step = step * 120 / target_fps as Freq;

#[cfg(debug_assertions)]
debug!("step: +{step}khz");

self.increase_fas_freq(step);
}

pub fn jank(&self) {
self.increase_fas_freq(JANK_STEP);
}

pub fn big_jank(&self) {
self.increase_fas_freq(BIG_JANK_STEP);
debug!("cpu infos: {cpu_infos:?}");

let max_freq = cpu_infos
.iter()
.flat_map(|info| info.freqs.iter())
.max()
.copied()
.unwrap();

let min_freq = cpu_infos
.iter()
.flat_map(|info| info.freqs.iter())
.min()
.copied()
.unwrap();

Ok(Self {
max_freq,
min_freq,
policy_freq: max_freq,
cpu_infos,
})
}

pub fn init_game(&self, extension: &Extension) {
pub fn init_game(&mut self, extension: &Extension) {
self.policy_freq = self.max_freq;
extension.tigger_extentions(ApiV0::InitCpuFreq);

for policy in &self.policies {
let _ = policy.init_game();
for cpu in &self.cpu_infos {
cpu.write_freq(self.max_freq)
.unwrap_or_else(|e| error!("{e:?}"));
}
}

pub fn init_default(&self, config: &Config, extension: &Extension) {
pub fn init_default(&mut self, extension: &Extension) {
self.policy_freq = self.max_freq;
extension.tigger_extentions(ApiV0::ResetCpuFreq);

for policy in &self.policies {
let _ = policy.init_default(config);
for cpu in &self.cpu_infos {
cpu.reset_freq().unwrap_or_else(|e| error!("{e:?}"));
}
}

fn increase_fas_freq(&self, step: Freq) {
for policy in &self.policies {
let _ = policy.increase_fas_freq(step);
pub fn fas_update_freq(&mut self, factor: f64) {
self.policy_freq = self
.policy_freq
.saturating_add((BASE_FREQ as f64 * factor) as isize)
.clamp(self.min_freq, self.max_freq);
println!("{} {factor:.4}", self.policy_freq);
for cpu in &self.cpu_infos {
cpu.write_freq(self.policy_freq)
.unwrap_or_else(|e| error!("{e:?}"));
}
}

fn decrease_fas_freq(&self, step: Freq) {
for policy in &self.policies {
let _ = policy.decrease_fas_freq(step);
pub fn scale_factor(target_fps: u32, frame: Duration, target: Duration) -> f64 {
if frame > target {
let factor_a = (frame - target).as_nanos() as f64 / target.as_nanos() as f64;
let factor_b = 120.0 / target_fps as f64;
factor_a * f64::from(factor_b)
} else {
let factor_a = (target - frame).as_nanos() as f64 / target.as_nanos() as f64;
let factor_b = 120.0 / target_fps as f64;
factor_a * f64::from(factor_b) * -1.0
}
}
}
86 changes: 0 additions & 86 deletions src/cpu_common/policy/insider/cpuinfo.rs

This file was deleted.

Loading

0 comments on commit f81b422

Please sign in to comment.