use super::*;
impl SchedulerCore {
pub(super) fn finish_run(mut self) {
self.drain_pipeline();
let Self {
ctx: sched,
active,
prefilling,
swapped,
preempted,
mut session_manager,
prefill_stream,
..
} = self;
{
let freed_slots = session_manager.evict_expired();
if !freed_slots.is_empty() {
tracing::info!(
"Session eviction: freed {} SSM snapshot slot(s), {} sessions active",
freed_slots.len(),
session_manager.session_count()
);
}
}
for mut a in active {
finish_sequence(&sched.io, &mut a, sched.limits.max_seq_len);
}
shutdown_drain::abort_in_flight_on_shutdown(
sched.io.dev.model(),
&sched.io,
prefilling,
swapped,
preempted,
sched.io.spill.as_deref(),
);
let _ = sched.io.dev.apply(io::Effect::EpShutdown);
let streams = [
("default", sched.io.dev.model().default_stream()),
("prefill", prefill_stream),
];
let unsynced = teardown::quiesce_streams(&streams, |stream| {
sched
.io
.dev
.apply(io::Effect::Quiesce { stream })
.map(|_| ())
.map_err(io::DeviceError::into_inner)
});
for name in unsynced {
tracing::error!(
"could not synchronise the {name} stream before teardown — freeing \
anyway, but device memory may still be in use"
);
}
let dev = sched.io.dev;
if let Err(e) = dev.teardown() {
tracing::error!("model teardown reported a failure: {e:#}");
}
tracing::info!("Scheduler stopped");
}
}