@@ -112,8 +112,8 @@ use {
112
112
compute_budget_processor:: process_compute_budget_instructions,
113
113
invoke_context:: BuiltinFunctionWithContext ,
114
114
loaded_programs:: {
115
- ExtractedPrograms , LoadProgramMetrics , LoadedProgram , LoadedProgramMatchCriteria ,
116
- LoadedProgramType , LoadedPrograms , LoadedProgramsForTxBatch , ProgramRuntimeEnvironment ,
115
+ LoadProgramMetrics , LoadedProgram , LoadedProgramMatchCriteria , LoadedProgramType ,
116
+ LoadedPrograms , LoadedProgramsForTxBatch , ProgramRuntimeEnvironment ,
117
117
ProgramRuntimeEnvironments , WorkingSlot , DELAY_VISIBILITY_SLOT_OFFSET ,
118
118
} ,
119
119
log_collector:: LogCollector ,
@@ -5068,50 +5068,43 @@ impl Bank {
5068
5068
. collect ( )
5069
5069
} ;
5070
5070
5071
- let ExtractedPrograms {
5072
- loaded : mut loaded_programs_for_txs,
5073
- missing,
5074
- unloaded,
5075
- } = {
5071
+ let extracted = {
5076
5072
// Lock the global cache to figure out which programs need to be loaded
5077
- let loaded_programs_cache = self . loaded_programs_cache . read ( ) . unwrap ( ) ;
5073
+ let mut loaded_programs_cache = self . loaded_programs_cache . write ( ) . unwrap ( ) ;
5078
5074
loaded_programs_cache. extract ( self , programs_and_slots. into_iter ( ) )
5079
5075
} ;
5080
5076
5081
- // Load missing programs while global cache is unlocked
5082
- let missing_programs: Vec < ( Pubkey , Arc < LoadedProgram > ) > = missing
5083
- . iter ( )
5084
- . map ( |( key, count) | {
5085
- let program = self . load_program ( key, false , None ) ;
5086
- program. tx_usage_counter . store ( * count, Ordering :: Relaxed ) ;
5087
- ( * key, program)
5088
- } )
5089
- . collect ( ) ;
5090
-
5091
- // Reload unloaded programs while global cache is unlocked
5092
- let unloaded_programs: Vec < ( Pubkey , Arc < LoadedProgram > ) > = unloaded
5093
- . iter ( )
5094
- . map ( |( key, count) | {
5095
- let program = self . load_program ( key, true , None ) ;
5096
- program. tx_usage_counter . store ( * count, Ordering :: Relaxed ) ;
5097
- ( * key, program)
5098
- } )
5099
- . collect ( ) ;
5100
-
5101
- // Lock the global cache again to replenish the missing programs
5102
- let mut loaded_programs_cache = self . loaded_programs_cache . write ( ) . unwrap ( ) ;
5103
- for ( key, program) in missing_programs {
5104
- let entry = loaded_programs_cache. assign_program ( key, program) ;
5105
- // Use the returned entry as that might have been deduplicated globally
5106
- loaded_programs_for_txs. assign_program ( key, entry) ;
5107
- }
5108
- for ( key, program) in unloaded_programs {
5109
- let entry = loaded_programs_cache. assign_program ( key, program) ;
5110
- // Use the returned entry as that might have been deduplicated globally
5111
- loaded_programs_for_txs. assign_program ( key, entry) ;
5077
+ // Cooperative loading phase
5078
+ let mut finished_task = None ;
5079
+ loop {
5080
+ // Critical section for global coordination
5081
+ let ( key, loading, reload) = {
5082
+ let mut loaded_programs_cache = self . loaded_programs_cache . write ( ) . unwrap ( ) ;
5083
+ if let Some ( ( key, loading, loaded) ) = finished_task. take ( ) {
5084
+ loaded_programs_cache. cooperative_loading_task_complete ( key, loading, loaded) ;
5085
+ }
5086
+ if Arc :: strong_count ( & extracted) == 1 {
5087
+ // All the missing entries for this batch have been loaded
5088
+ break ;
5089
+ }
5090
+ if let Some ( task) = loaded_programs_cache. next_cooperative_loading_task ( & extracted)
5091
+ {
5092
+ task
5093
+ } else {
5094
+ // Waiting for some other TX batch to complete loading the programs needed by this TX batch
5095
+ // TODO: Use a Condvar here
5096
+ continue ;
5097
+ }
5098
+ } ;
5099
+ // Load, verify and compile the program outside of the critical section
5100
+ let loaded = self . load_program ( & key, reload, None ) ;
5101
+ finished_task = Some ( ( key, loading, loaded) ) ;
5112
5102
}
5113
5103
5114
- loaded_programs_for_txs
5104
+ // When we get here we should be the only remaining owner
5105
+ std:: sync:: Mutex :: into_inner ( Arc :: into_inner ( extracted) . unwrap ( ) )
5106
+ . unwrap ( )
5107
+ . loaded
5115
5108
}
5116
5109
5117
5110
/// Returns a hash map of executable program accounts (program accounts that are not writable
0 commit comments