Skip to content

Commit d3e4c3d

Browse files
committed
perf(executor): Catch up on network work before returning
When the point in time that smoltcp thinks the interface should be polled again is in the past, we should try to poll it immediately to avoid lagging behind. Signed-off-by: Jens Reidel <[email protected]>
1 parent 61b14a6 commit d3e4c3d

File tree

1 file changed

+32
-30
lines changed

1 file changed

+32
-30
lines changed

src/executor/mod.rs

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,36 @@ where
143143
}
144144
}
145145

146+
fn maybe_set_network_timer(now: u64) {
147+
if let Some(mut guard) = crate::executor::network::NIC.try_lock() {
148+
let delay = if let Ok(nic) = guard.as_nic_mut() {
149+
let mut delay_micros = nic
150+
.poll_delay(Instant::from_micros_const(now.try_into().unwrap()))
151+
.map(|d| d.total_micros());
152+
153+
// Under heavy workloads, we may be lagging behind, in which case we
154+
// need to try to catch up immediately
155+
while delay_micros == Some(0) {
156+
nic.poll_common(crate::executor::network::now());
157+
delay_micros = nic
158+
.poll_delay(crate::executor::network::now())
159+
.map(|d| d.total_micros());
160+
}
161+
162+
// We will yield back to userspace and may not have an opportunity to handle
163+
// network traffic unless we enable interrupts
164+
nic.set_polling_mode(false);
165+
166+
delay_micros
167+
} else {
168+
None
169+
};
170+
171+
core_local::core_scheduler()
172+
.add_network_timer(delay.map(|d| crate::arch::processor::get_timer_ticks() + d));
173+
}
174+
}
175+
146176
/// Blocks the current thread on `f`, running the executor when idling.
147177
pub(crate) fn block_on<F, T>(future: F, timeout: Option<Duration>) -> io::Result<T>
148178
where
@@ -166,21 +196,7 @@ where
166196
if let Poll::Ready(t) = result {
167197
// allow network interrupts
168198
#[cfg(feature = "net")]
169-
{
170-
if let Some(mut guard) = crate::executor::network::NIC.try_lock() {
171-
let delay = if let Ok(nic) = guard.as_nic_mut() {
172-
nic.set_polling_mode(false);
173-
174-
nic.poll_delay(Instant::from_micros_const(now.try_into().unwrap()))
175-
.map(|d| d.total_micros())
176-
} else {
177-
None
178-
};
179-
core_local::core_scheduler().add_network_timer(
180-
delay.map(|d| crate::arch::processor::get_timer_ticks() + d),
181-
);
182-
}
183-
}
199+
maybe_set_network_timer(now);
184200

185201
return t;
186202
}
@@ -190,21 +206,7 @@ where
190206
{
191207
// allow network interrupts
192208
#[cfg(feature = "net")]
193-
{
194-
if let Some(mut guard) = crate::executor::network::NIC.try_lock() {
195-
let delay = if let Ok(nic) = guard.as_nic_mut() {
196-
nic.set_polling_mode(false);
197-
198-
nic.poll_delay(Instant::from_micros_const(now.try_into().unwrap()))
199-
.map(|d| d.total_micros())
200-
} else {
201-
None
202-
};
203-
core_local::core_scheduler().add_network_timer(
204-
delay.map(|d| crate::arch::processor::get_timer_ticks() + d),
205-
);
206-
}
207-
}
209+
maybe_set_network_timer(now);
208210

209211
return Err(Errno::Time);
210212
}

0 commit comments

Comments
 (0)