// Carries out a P-state change for this cluster.
Carries out a P-state change for this cluster.
Carries out a P - state change for this cluster .
async fn update_pstate(
        &self,
        syscall_handler: &Rc<dyn Node>,
        index: usize,
    ) -> Result<(), PowerManagerError> {
        fuchsia_trace::counter!(
            "power_manager",
            "CpuManager P-state",
            self.cluster_index as u64,
            &self.name => index as u32
        );
        // If the current P-state is known and equal to the new one, no update is needed.
        if let RangedValue::Known(current) = self.current_pstate.get() {
            if current == index {
                return Ok(());
            }
        }
        // If the P-state is unknown, the lowest-possible frequency (highest-possible P-state index)
        // is what was used to inform the last `update_kernel_performance_info` call.
        let current_frequency = self.pstates[self.current_pstate.get().upper()].frequency;
        let target_pstate = &self.pstates[index];
        // If lowering frequency, we update the kernel before changing P-states. Otherwise, the
        // kernel will be updated after the change.
        let kernel_updated = if target_pstate.frequency < current_frequency {
            self.update_kernel_performance_info(&syscall_handler, target_pstate).await?;
            true
        } else {
            false
        };
        // If the current P-state is unknown or not equal to the new one, attempt an update.
        match self.handler.handle_message(&Message::SetPerformanceState(index as u32)).await {
            Ok(MessageReturn::SetPerformanceState) => {
                self.current_pstate.set(RangedValue::Known(index));
                if !kernel_updated {
                    self.update_kernel_performance_info(&syscall_handler, target_pstate).await?;
                }
                Ok(())
            }
            Ok(r) => {
                // Programming error
                panic!("Wrong response type for SetPerformanceState: {:?}", r);
            }
            Err(e) => {
                log::error!("SetPerformanceState failed: {:?}", e);
                // If the update failed, query the value, so at least the current state is known. If
                // that fails, too, record a range of possible values based on the previous and
                // desired values. Regardless, propagate the error from SetPerformanceState.
                match self.handler.handle_message(&Message::GetPerformanceState).await {
                    Ok(MessageReturn::GetPerformanceState(i)) => {
                        self.current_pstate.set(RangedValue::Known(i as usize));
                    }
                    result => {
                        log::error!("Unexpected result from GetPerformanceState: {:?}", result);
                        let range = Range {
                            lower: std::cmp::min(self.current_pstate.get().lower(), index),
                            upper: std::cmp::max(self.current_pstate.get().upper(), index),
                        };
                        self.current_pstate.set(RangedValue::InRange(range));
                    }
                }
                // If we already updated the kernel, make a new update using the lowest-possible
                // CPU frequency (highest-possbile P-state index) to provide a pessimistic estimate
                // of CPU performance.
                if kernel_updated {
                    let pstate = &self.pstates[self.current_pstate.get().upper()];
                    self.update_kernel_performance_info(&syscall_handler, pstate).await?;
                }
                Err(e)
            }
        }
    }
async fn update_pstate ( & self , syscall_handler : & Rc < dyn Node > , index : usize , ) -> Result < ( ) , PowerManagerError > { fuchsia_trace :: counter ! ( " " " " self cluster_index as u64 self name index as u32 ) ; // If the current P-state is known and equal to the new one, no update is needed. if let RangedValue :: Known ( current ) = self . current_pstate . get ( ) { if current == index { return Ok ( ( ) ) ; } } // If the P-state is unknown, the lowest-possible frequency (highest-possible P-state index) // is what was used to inform the last `update_kernel_performance_info` call. let current_frequency = self . pstates [ self . current_pstate . get ( ) . upper ( ) ] . frequency ; let target_pstate = & self . pstates [ index ] ; // If lowering frequency, we update the kernel before changing P-states. Otherwise, the // kernel will be updated after the change. let kernel_updated = if target_pstate . frequency < current_frequency { self . update_kernel_performance_info ( & syscall_handler , target_pstate ) . await ? ; true } else { false } ; // If the current P-state is unknown or not equal to the new one, attempt an update. match self . handler . handle_message ( & Message :: SetPerformanceState ( index as u32 ) ) . await { Ok ( MessageReturn :: SetPerformanceState ) => { self . current_pstate . set ( RangedValue :: Known ( index ) ) ; if ! kernel_updated { self . update_kernel_performance_info ( & syscall_handler , target_pstate ) . await ? ; } Ok ( ( ) ) } Ok ( r ) => { // Programming error panic ! ( " " r ) ; } Err ( e ) => { log :: error ! ( " " e ) ; // If the update failed, query the value, so at least the current state is known. If // that fails, too, record a range of possible values based on the previous and // desired values. Regardless, propagate the error from SetPerformanceState. match self . handler . handle_message ( & Message :: GetPerformanceState ) . await { Ok ( MessageReturn :: GetPerformanceState ( i ) ) => { self . current_pstate . set ( RangedValue :: Known ( i as usize ) ) ; } result => { log :: error ! ( " " result ) ; let range = Range { lower : std :: cmp :: min ( self . current_pstate . get ( ) . lower ( ) , index ) , upper : std :: cmp :: max ( self . current_pstate . get ( ) . upper ( ) , index ) , } ; self . current_pstate . set ( RangedValue :: InRange ( range ) ) ; } } // If we already updated the kernel, make a new update using the lowest-possible // CPU frequency (highest-possbile P-state index) to provide a pessimistic estimate // of CPU performance. if kernel_updated { let pstate = & self . pstates [ self . current_pstate . get ( ) . upper ( ) ] ; self . update_kernel_performance_info ( & syscall_handler , pstate ) . await ? ; } Err ( e ) } } }
Carries out a P-state change for this cluster.
Carries out a P - state change for this cluster .
&self
syscall_handler
&Rc<dyn Node>
index
usize