diff --git a/program-runtime/src/loaded_programs.rs b/program-runtime/src/loaded_programs.rs index bdd9dc7f2600ed..829e3dc001f6a3 100644 --- a/program-runtime/src/loaded_programs.rs +++ b/program-runtime/src/loaded_programs.rs @@ -143,7 +143,7 @@ pub struct LoadedProgram { /// How often this entry was used by an instruction pub ix_usage_counter: AtomicU64, /// Latest slot in which the entry was used - pub latest_access_slot: RwLock, + pub latest_access_slot: AtomicU64, } #[derive(Debug, Default)] @@ -363,7 +363,7 @@ impl LoadedProgram { tx_usage_counter: AtomicU64::new(0), program, ix_usage_counter: AtomicU64::new(0), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::new(0), }) } @@ -376,7 +376,7 @@ impl LoadedProgram { maybe_expiration_slot: self.maybe_expiration_slot, tx_usage_counter: AtomicU64::new(self.tx_usage_counter.load(Ordering::Relaxed)), ix_usage_counter: AtomicU64::new(self.ix_usage_counter.load(Ordering::Relaxed)), - latest_access_slot: RwLock::new(*self.latest_access_slot.read().unwrap()), + latest_access_slot: AtomicU64::new(self.latest_access_slot.load(Ordering::Relaxed)), }) } @@ -398,7 +398,7 @@ impl LoadedProgram { tx_usage_counter: AtomicU64::new(0), program: LoadedProgramType::Builtin(BuiltinProgram::new_builtin(function_registry)), ix_usage_counter: AtomicU64::new(0), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::new(0), } } @@ -413,7 +413,7 @@ impl LoadedProgram { maybe_expiration_slot, tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::new(0), }; debug_assert!(tombstone.is_tombstone()); tombstone @@ -437,15 +437,24 @@ impl LoadedProgram { } pub fn update_access_slot(&self, slot: Slot) { - let mut current_slot = self.latest_access_slot.write().unwrap(); - if slot > *current_slot { - *current_slot = slot; + let mut last_access = self.latest_access_slot.load(Ordering::Relaxed); + while last_access < slot { + if let Err(updated_last_access) = self.latest_access_slot.compare_exchange( + last_access, + slot, + Ordering::Relaxed, + Ordering::Relaxed, + ) { + last_access = updated_last_access; + } else { + last_access = slot; + } } } fn decayed_usage_counter(&self, now: Slot) -> u64 { - let last_access = self.latest_access_slot.read().unwrap(); - let decaying_for = now.saturating_sub(*last_access); + let last_access = self.latest_access_slot.load(Ordering::Relaxed); + let decaying_for = now.saturating_sub(last_access); self.tx_usage_counter.load(Ordering::Relaxed) >> decaying_for } } @@ -1002,8 +1011,15 @@ impl LoadedPrograms { .entry(*id) .and_modify(|c| saturating_add_assign!(*c, 1)) .or_insert(1); + } else { + error!( + "Failed to create an unloaded cache entry for a program type {:?}", + entry.program + ); } } + } else { + error!("Failed to find a cached entry for program {}", id); } } @@ -1025,8 +1041,20 @@ impl LoadedPrograms { .and_modify(|c| saturating_add_assign!(*c, 1)) .or_insert(1); *candidate = Arc::new(unloaded); + } else { + error!( + "Failed to create an unloaded cache entry for a program type {:?}", + candidate.program + ); } + } else { + error!( + "Failed to find the cache entry for program {} that was to be unloaded", + program + ); } + } else { + error!("Failed to find a cached entry for program {}", program); } } @@ -1133,7 +1161,7 @@ mod tests { maybe_expiration_slot: expiry, tx_usage_counter: usage_counter, ix_usage_counter: AtomicU64::default(), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::default(), }) } @@ -1146,7 +1174,7 @@ mod tests { maybe_expiration_slot: None, tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::default(), }) } @@ -1175,7 +1203,7 @@ mod tests { maybe_expiration_slot: None, tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::default(), } .to_unloaded() .expect("Failed to unload the program"), @@ -1762,7 +1790,7 @@ mod tests { maybe_expiration_slot: None, tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::default(), }); let (existing, program) = cache.replenish(program1, updated_program.clone()); assert!(!existing); @@ -2087,7 +2115,7 @@ mod tests { maybe_expiration_slot: Some(21), tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::default(), }); assert!(!cache.replenish(program4, test_program).0); @@ -2451,7 +2479,7 @@ mod tests { maybe_expiration_slot: Some(15), tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::default(), }); assert!(!cache.replenish(program1, test_program).0); diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index a7987b7dd70c79..fd5c28fc7b332b 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -1705,12 +1705,7 @@ mod tests { rent::Rent, system_program, sysvar, }, - std::{ - fs::File, - io::Read, - ops::Range, - sync::{atomic::AtomicU64, RwLock}, - }, + std::{fs::File, io::Read, ops::Range, sync::atomic::AtomicU64}, }; struct TestContextObject { @@ -4053,7 +4048,7 @@ mod tests { maybe_expiration_slot: None, tx_usage_counter: AtomicU64::new(100), ix_usage_counter: AtomicU64::new(100), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::new(0), }; invoke_context .programs_modified_by_tx @@ -4094,7 +4089,7 @@ mod tests { maybe_expiration_slot: None, tx_usage_counter: AtomicU64::new(100), ix_usage_counter: AtomicU64::new(100), - latest_access_slot: RwLock::new(0), + latest_access_slot: AtomicU64::new(0), }; invoke_context .programs_modified_by_tx