Skip to content

Commit 3710841

Browse files
committed
Limit blocked PeerManager::process_events waiters to two
Only one instance of PeerManager::process_events can run at a time, and each run always finishes all available work before returning. Thus, having several threads blocked on the process_events lock doesn't accomplish anything but blocking more threads. Here we limit the number of blocked calls on process_events to two - one processing events and one blocked at the top which will process all available events after the first completes.
1 parent 63d1d1b commit 3710841

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed

lightning/src/ln/peer_handler.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,11 @@ pub struct PeerManager<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, L: De
400400
/// `peers` write lock to do so, so instead we block on this empty mutex when entering
401401
/// `process_events`.
402402
event_processing_lock: Mutex<()>,
403+
/// Because event processing is global and always does all available work before returning,
404+
/// there is no reason for us to have many event processors waiting on the lock at once.
405+
/// Instead, we limit the total blocked event processors to always exactly one using this
406+
/// counter.
407+
blocked_event_processors: AtomicUsize,
403408
our_node_secret: SecretKey,
404409
ephemeral_key_midstate: Sha256Engine,
405410
custom_message_handler: CMH,
@@ -494,6 +499,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, L: Deref, CMH: Deref> P
494499
}),
495500
node_id_to_descriptor: Mutex::new(HashMap::new()),
496501
event_processing_lock: Mutex::new(()),
502+
blocked_event_processors: AtomicUsize::new(0),
497503
our_node_secret,
498504
ephemeral_key_midstate,
499505
peer_counter_low: AtomicUsize::new(0),
@@ -1213,7 +1219,22 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, L: Deref, CMH: Deref> P
12131219
/// [`ChannelManager::process_pending_htlc_forwards`]: crate::ln::channelmanager::ChannelManager::process_pending_htlc_forwards
12141220
/// [`send_data`]: SocketDescriptor::send_data
12151221
pub fn process_events(&self) {
1216-
let _single_processor_lock = self.event_processing_lock.lock().unwrap();
1222+
let mut _single_processor_lock = self.event_processing_lock.try_lock();
1223+
if _single_processor_lock.is_err() {
1224+
// While we could wake the older sleeper here with a CV and make more even waiting
1225+
// times, that would be a lot of overengineering for a simple "reduce total waiter
1226+
// count" goal.
1227+
if self.blocked_event_processors.fetch_add(1, Ordering::AcqRel) != 0 {
1228+
self.blocked_event_processors.fetch_sub(1, Ordering::AcqRel);
1229+
return;
1230+
} else {
1231+
// We're the only waiter, as the running process_events may have emptied the
1232+
// pending events "long" ago and there are new events for us to process, wait until
1233+
// its done and process any leftover events before returning.
1234+
_single_processor_lock = Ok(self.event_processing_lock.lock().unwrap());
1235+
self.blocked_event_processors.fetch_sub(1, Ordering::Release);
1236+
}
1237+
}
12171238

12181239
let mut disconnect_peers = HashMap::new();
12191240
let mut events_generated = self.message_handler.chan_handler.get_and_clear_pending_msg_events();

0 commit comments

Comments
 (0)