/// Handles a SetMaxPowerConsumption message. If an error is encountered in the execution of
/// this method, CpuManager will keep itself in a usable state by using pessimistic estimates of
/// any value that it cannot determine and then propagate the error to the caller.
Handles a SetMaxPowerConsumption message. If an error is encountered in the execution of
this method, CpuManager will keep itself in a usable state by using pessimistic estimates of
any value that it cannot determine and then propagate the error to the caller.
Handles a SetMaxPowerConsumption message . If an error is encountered in the execution of this method CpuManager will keep itself in a usable state by using pessimistic estimates of any value that it cannot determine and then propagate the error to the caller .
async fn handle_set_max_power_consumption(&self, available_power: Watts) -> MessageResult {
        fuchsia_trace::duration!(
            "power_manager",
            "CpuManager::handle_set_max_power_consumption",
            "available_power" => available_power.0
        );
        self.inspect.available_power.set(available_power.0);
        // Gather CPU loads over the last time interval. In the unlikely event of an error, use the
        // worst-case CPU load of 1.0 for all CPUs and throttle accordingly before propagating the
        // error.
        let (cpu_loads, load_query_error) = match self.get_cpu_loads().await {
            Ok(loads) => (loads, None),
            Err(e) => {
                log::error!(
                    "Error querying CPU loads: {}\nWill throttle assuming maximal load.",
                    e
                );
                self.inspect.last_error.set(&e.to_string());
                (vec![1.0; self.num_cpus as usize], Some(e))
            }
        };
        // Determine the normalized performance over the last interval.
        let mut last_performance = NormPerfs(0.0);
        for cluster in self.clusters.iter() {
            let (load, performance) = cluster.process_fractional_loads(&cpu_loads);
            last_performance += performance;
            fuchsia_trace::counter!(
                "power_manager",
                "CpuManager cluster_load",
                cluster.cluster_index as u64,
                &cluster.name => load as f64
            );
            self.inspect.last_cluster_loads[cluster.cluster_index].set(load as f64);
        }
        self.inspect.last_performance.set(last_performance.0);
        fuchsia_trace::counter!(
            "power_manager",
            "CpuManager last_performance",
            0,
            "value (NormPerfs)" => last_performance.0
        );
        let cpus_saturated = cpu_loads.iter().all(|l| PerformanceModel::cpu_load_is_saturated(*l));
        let performance_model =
            if cpus_saturated { Saturated } else { FixedValue(last_performance) };
        // Determine the next thermal state, updating if needed. We use the performance over the
        // last interval as an estimate of performance over the next interval; in principle a more
        // sophisticated estimate could be used.
        let (new_thermal_state_index, estimate) =
            self.select_thermal_state(available_power, performance_model);
        fuchsia_trace::counter!(
            "power_manager",
            "CpuManager new_thermal_state_index",
            0,
            "value" => new_thermal_state_index as u32
        );
        if let Err(e) = self.update_thermal_state(new_thermal_state_index).await {
            self.inspect.last_error.set(&e.to_string());
            return Err(e);
        }
        fuchsia_trace::counter!(
            "power_manager",
            "CpuManager projected_performance",
            0,
            "value (NormPerfs)" => estimate.performance.0
        );
        self.inspect.projected_performance.set(estimate.performance.0);
        fuchsia_trace::counter!(
            "power_manager",
            "CpuManager projected_power",
            0,
            "value (W)" => estimate.power.0
        );
        self.inspect.projected_power.set(estimate.power.0);
        // Bubble up any error that may have occurred while querying CPU load.
        match load_query_error {
            None => Ok(MessageReturn::SetMaxPowerConsumption(estimate.power)),
            Some(e) => Err(e.into()),
        }
    }
async fn handle_set_max_power_consumption ( & self , available_power : Watts ) -> MessageResult { fuchsia_trace :: duration ! ( " " " " " " available_power 0 ) ; self . inspect . available_power . set ( available_power . 0 ) ; // Gather CPU loads over the last time interval. In the unlikely event of an error, use the // worst-case CPU load of 1.0 for all CPUs and throttle accordingly before propagating the // error. let ( cpu_loads , load_query_error ) = match self . get_cpu_loads ( ) . await { Ok ( loads ) => ( loads , None ) , Err ( e ) => { log :: error ! ( " \n " e ) ; self . inspect . last_error . set ( & e . to_string ( ) ) ; ( vec ! [ 1.0 self num_cpus as usize ] , Some ( e ) ) } } ; // Determine the normalized performance over the last interval. let mut last_performance = NormPerfs ( 0.0 ) ; for cluster in self . clusters . iter ( ) { let ( load , performance ) = cluster . process_fractional_loads ( & cpu_loads ) ; last_performance += performance ; fuchsia_trace :: counter ! ( " " " " cluster cluster_index as u64 cluster name load as f64 ) ; self . inspect . last_cluster_loads [ cluster . cluster_index ] . set ( load as f64 ) ; } self . inspect . last_performance . set ( last_performance . 0 ) ; fuchsia_trace :: counter ! ( " " " " 0 " " last_performance 0 ) ; let cpus_saturated = cpu_loads . iter ( ) . all ( | l | PerformanceModel :: cpu_load_is_saturated ( * l ) ) ; let performance_model = if cpus_saturated { Saturated } else { FixedValue ( last_performance ) } ; // Determine the next thermal state, updating if needed. We use the performance over the // last interval as an estimate of performance over the next interval; in principle a more // sophisticated estimate could be used. let ( new_thermal_state_index , estimate ) = self . select_thermal_state ( available_power , performance_model ) ; fuchsia_trace :: counter ! ( " " " " 0 " " new_thermal_state_index as u32 ) ; if let Err ( e ) = self . update_thermal_state ( new_thermal_state_index ) . await { self . inspect . last_error . set ( & e . to_string ( ) ) ; return Err ( e ) ; } fuchsia_trace :: counter ! ( " " " " 0 " " estimate performance 0 ) ; self . inspect . projected_performance . set ( estimate . performance . 0 ) ; fuchsia_trace :: counter ! ( " " " " 0 " " estimate power 0 ) ; self . inspect . projected_power . set ( estimate . power . 0 ) ; // Bubble up any error that may have occurred while querying CPU load. match load_query_error { None => Ok ( MessageReturn :: SetMaxPowerConsumption ( estimate . power ) ) , Some ( e ) => Err ( e . into ( ) ) , } }
Handles a SetMaxPowerConsumption message.
Handles a SetMaxPowerConsumption message .
&self
available_power
Watts