extern crate errno;
extern crate libc;
use ::base::*;
use ::policy::*;
use ::stat::*;
use ::result::Result;
use ::types::{CpuId, Frequency};
use ::adapters::Extract;
use std::ffi::{CStr, CString};
use std::iter;
use std::str;
use std::string::String;
use std::vec::Vec;
use std::fmt;
pub struct Iterator {
next_id: CpuId,
}
impl iter::Iterator for Iterator {
type Item = Cpu;
fn next(&mut self) -> Option<Self::Item> {
let current_id = self.next_id;
self.next_id += 1;
match Cpu::exists(current_id) {
true => Some(Cpu::new(current_id)),
_ => None
}
}
}
#[derive(Debug)]
pub struct Cpu {
id: CpuId
}
impl Cpu {
pub fn get_all() -> Iterator {
Iterator {
next_id: 0
}
}
pub fn exists(id: CpuId) -> bool {
unsafe {
cpufreq_cpu_exists(id as u32) == 0
}
}
pub fn new(id: CpuId) -> Cpu {
Cpu {
id: id
}
}
pub fn get_freq(&self) -> Result<Frequency> {
self.get_freq_hardware().or_else(|_|{self.get_freq_kernel()})
}
pub fn get_freq_kernel(&self) -> Result<Frequency> {
unsafe {
let frequency = cpufreq_get_freq_kernel(self.id as u32);
match frequency {
0 => Err(::error::CpuPowerError::SystemError(errno::errno())),
_ => Ok(frequency)
}
}
}
pub fn get_freq_hardware(&self) -> Result<Frequency> {
unsafe {
let frequency = cpufreq_get_freq_hardware(self.id as u32);
match frequency {
0 => Err(::error::CpuPowerError::SystemError(errno::errno())),
_ => Ok(frequency)
}
}
}
pub fn set_freq(&self, freq: Frequency) -> Result<&Cpu> {
unsafe {
let result = cpufreq_set_frequency(self.id, freq);
match result {
0 => Ok(&self),
_ => Err(::error::CpuPowerError::SystemError(errno::errno()))
}
}
}
pub fn get_transition_latency(&self) -> Result<u64> {
unsafe {
let latency = cpufreq_get_transition_latency(self.id as u32);
match latency {
0 => Err(::error::CpuPowerError::SystemError(errno::errno())),
_ => Ok(latency)
}
}
}
pub fn modify_policy_max(&self, max: Frequency) -> Result<()> {
unsafe {
let result = cpufreq_modify_policy_max(self.id as u32, max);
match result {
0 => Ok(()),
_ => Err(::error::CpuPowerError::SystemError(errno::errno()))
}
}
}
pub fn modify_policy_min(&self, min: Frequency) -> Result<()> {
unsafe {
let result = cpufreq_modify_policy_min(self.id as u32, min);
match result {
0 => Ok(()),
_ => Err(::error::CpuPowerError::SystemError(errno::errno()))
}
}
}
pub fn modify_policy_governor(&self, governor: &str) -> Result<()> {
let governor = try!(CString::new(governor));
unsafe {
let result = cpufreq_modify_policy_governor(self.id as u32, governor.as_ptr() as *mut libc::c_char);
match result {
0 => Ok(()),
_ => Err(::error::CpuPowerError::SystemError(errno::errno()))
}
}
}
pub fn get_hardware_limits(&self) -> Result<(Frequency, Frequency)> {
unsafe {
let mut min: u64 = 0;
let mut max: u64 = 0;
let response = cpufreq_get_hardware_limits(self.id as u32, &mut min as *mut u64, &mut max as *mut u64);
match response {
0 => Ok((min, max)),
_ => Err(::error::CpuPowerError::SystemError(errno::errno())),
}
}
}
pub fn get_id(&self) -> CpuId {
self.id
}
pub fn get_driver(&self) -> Result<String> {
unsafe {
let driver = cpufreq_get_driver(self.id as u32);
let result = try!(str::from_utf8(CStr::from_ptr(driver).to_bytes())).to_owned();
cpufreq_put_driver(driver);
Ok(result)
}
}
pub fn get_policy(&self) -> Result<Policy> {
unsafe {
let policy = cpufreq_get_policy(self.id as u32);
if policy.is_null() {
return Err(::error::CpuPowerError::SystemError(errno::errno()));
}
let min = (*policy).min;
let max = (*policy).max;
let governor_name = try!(str::from_utf8(CStr::from_ptr((*policy).governor).to_bytes()));
let result = Policy::new(min, max, governor_name);
cpufreq_put_policy(policy);
Ok(result)
}
}
pub fn set_policy(&self, policy: &Policy) -> Result<()> {
unsafe {
let governor_name = try!(CString::new(policy.governor.clone())); let mut policy = Struct_cpufreq_policy{
min: policy.min,
max: policy.max,
governor: governor_name.as_ptr() as *mut libc::c_char
};
let result = cpufreq_set_policy(self.id as u32, &mut policy as *mut Struct_cpufreq_policy);
match result {
0 => Ok(()),
_ => Err(::error::CpuPowerError::SystemError(errno::errno()))
}
}
}
pub fn get_available_governors(&self) -> Result<Vec<String>> {
::adapters::AvailableGovernors::extract(self.get_id())
}
pub fn get_available_frequencies(&self) -> Result<Vec<Frequency>> {
::adapters::AvailableFrequencies::extract(self.get_id())
}
pub fn get_affected_cpus(&self) -> Result<Vec<Cpu>> {
let cpus = try!(::adapters::AffectedCpus::extract(self.get_id()));
let mut result = Vec::<Cpu>::new();
result.extend(cpus.iter().map(|cpu_id| Cpu::new(*cpu_id)));
Ok(result)
}
pub fn get_related_cpus(&self) -> Result<Vec<Cpu>> {
let cpus = try!(::adapters::RelatedCpus::extract(self.get_id()));
let mut result = Vec::<Cpu>::new();
result.extend(cpus.iter().map(|cpu_id| Cpu::new(*cpu_id)));
Ok(result)
}
pub fn get_stats(&self) -> Result<Vec<Stat>> {
::adapters::Stats::extract(self.get_id())
}
pub fn get_transitions(&self) -> Result<u64> {
let result: u64;
errno::errno();
unsafe {
result = cpufreq_get_transitions(self.id as u32) as u64;
}
if result == 0 {
let errno = errno::errno();
if errno.0 != 0 {
return Err(::error::CpuPowerError::SystemError(errno))
}
}
Ok(result)
}
}
impl fmt::Display for Cpu {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Cpu{{id: {}, frequency: {}}}", self.get_id(), self.get_freq().map(|freq| freq.to_string()).unwrap_or(String::from("Unknown")))
}
}