From 7827cb6c78562eaeda0c9cc91540ae21c6dff88f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Apr 2026 21:09:02 +0200 Subject: [PATCH] Unify context list again now that we have a run queue This simplifies code and ensures that exiting a context will properly remove it from the list of contexts. --- src/context/mod.rs | 27 ++--- src/context/switch.rs | 30 +---- src/debugger.rs | 247 +++++++++++++++++++------------------- src/percpu.rs | 24 +--- src/scheme/sys/block.rs | 7 +- src/scheme/sys/context.rs | 9 +- src/scheme/sys/fdstat.rs | 7 +- src/scheme/sys/iostat.rs | 6 +- src/scheme/sys/stat.rs | 17 ++- src/scheme/sys/syscall.rs | 6 +- src/syscall/process.rs | 2 +- 11 files changed, 176 insertions(+), 206 deletions(-) diff --git a/src/context/mod.rs b/src/context/mod.rs index d024f06b63..40bac5190b 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -72,13 +72,7 @@ pub use self::arch::empty_cr3; // Set of weak references to all contexts available for scheduling. The only strong references are // the context file descriptors. -static CONTEXTS: Mutex> = Mutex::new(BTreeSet::new()); -/// Try to get the global free contexts -pub fn free_contexts_try( - token: LockToken<'_, L1>, -) -> Option>> { - CONTEXTS.try_lock(token) -} +static CONTEXTS: RwLock> = RwLock::new(BTreeSet::new()); // Actual context store for the scheduler static RUN_CONTEXTS: Mutex = Mutex::new(RunContextData::new()); @@ -97,15 +91,13 @@ impl RunContextData { } /// Get the global schemes list, const -pub fn contexts(token: LockToken<'_, L0>) -> RwLockReadGuard<'_, L1, BTreeSet> { - let percpu = PercpuBlock::current(); - percpu.contexts.read(token) +pub fn contexts(token: LockToken<'_, L1>) -> RwLockReadGuard<'_, L2, BTreeSet> { + CONTEXTS.read(token) } /// Get per cpu contexts, mutable -pub fn contexts_mut(token: LockToken<'_, L0>) -> RwLockWriteGuard<'_, L1, BTreeSet> { - let percpu = PercpuBlock::current(); - percpu.contexts.write(token) +pub fn contexts_mut(token: LockToken<'_, L1>) -> RwLockWriteGuard<'_, L2, BTreeSet> { + CONTEXTS.write(token) } pub fn run_contexts(token: LockToken<'_, L0>) -> MutexGuard<'_, L1, RunContextData> { @@ -128,10 +120,12 @@ pub fn init(token: &mut CleanLockToken) { context.cpu_id = Some(crate::cpu_id()); context.enqueued = false; + let priority = context.prio; + let context_lock = Arc::new(ContextLock::new(context)); let context_ref = ContextRef(Arc::clone(&context_lock)); - contexts_mut(token.token()).insert(context_ref); + contexts_mut(token.token().downgrade()).insert(context_ref.clone()); unsafe { let percpu = PercpuBlock::current(); @@ -139,6 +133,8 @@ pub fn init(token: &mut CleanLockToken) { .switch_internals .set_current_context(Arc::clone(&context_lock)); } + + run_contexts(token.downgrade()).set[priority].push_back(context_ref); } pub fn wakeup_context(context_lock: &Arc>, mut token: LockToken) { @@ -176,6 +172,7 @@ pub fn is_current(context: &Arc) -> bool { .with_context(|current| Arc::ptr_eq(context, current)) } +#[derive(Clone)] pub struct ContextRef(pub Arc); impl ContextRef { pub fn upgrade(&self) -> Option> { @@ -224,7 +221,7 @@ pub fn spawn( let run_ref = ContextRef(Arc::clone(&context_lock)); run_contexts(token.token()).set[20].push_back(run_ref); - contexts_mut(token.token()).insert(context_ref); + contexts_mut(token.token().downgrade()).insert(context_ref); context_lock.write(token.token()).enqueued = true; Ok(context_lock) diff --git a/src/context/switch.rs b/src/context/switch.rs index 8988478a0f..601991f6e5 100644 --- a/src/context/switch.rs +++ b/src/context/switch.rs @@ -3,10 +3,7 @@ //! handling process states and synchronization. use crate::{ - context::{ - self, arch, contexts, contexts_mut, free_contexts_try, run_contexts, - ArcContextLockWriteGuard, Context, ContextLock, - }, + context::{self, arch, contexts, run_contexts, ArcContextLockWriteGuard, Context, ContextLock}, cpu_set::LogicalCpuId, cpu_stats::{self, CpuState}, percpu::PercpuBlock, @@ -176,12 +173,12 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult { } // Alarm (previously in update_runnable) - // TODO: Optimise this somehow + // TODO: Optimise this somehow. Perhaps using a separate timer queue? let mut wakeups = Vec::new(); { let current_context = context::current(); - let mut contexts_guard = contexts(token.token()); + let mut contexts_guard = contexts(token.downgrade()); let (context, mut token) = contexts_guard.token_split(); for context_ref in context.iter().filter_map(|r| r.upgrade()) { if Arc::ptr_eq(&context_ref, ¤t_context) { @@ -214,7 +211,7 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult { let was_idle = percpu.stats.add_time(percpu_ms) == CpuState::Idle as u8; percpu.switch_internals.switch_time.set(switch_time); - let mut switch_context_opt = match select_next_context( + let switch_context_opt = match select_next_context( token, percpu, cpu_id, @@ -226,25 +223,6 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult { Err(early_ret) => return early_ret, }; - if switch_context_opt.is_none() { - let mut this_contexts = contexts_mut(token.token()); - let (this_contexts, mut token) = this_contexts.token_split(); - if let Some(mut free_contexts) = free_contexts_try(token.token()) - && let Some(context) = free_contexts.pop_last() - { - // Check if we can run this free context immediately - if let Some(next_context) = context.upgrade() { - let mut next_context_guard = unsafe { next_context.write_arc() }; - if let UpdateResult::CanSwitch = - unsafe { update_runnable(&mut next_context_guard, cpu_id, switch_time) } - { - switch_context_opt = Some(next_context_guard); - } - } - this_contexts.insert(context); - } - } - // Switch process states, TSS stack pointer, and store new context ID match switch_context_opt { Some(mut next_context_guard) => { diff --git a/src/debugger.rs b/src/debugger.rs index cfc6e83817..8e6c7e0e93 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -1,5 +1,5 @@ use crate::{ - context::{context::SyscallFrame, Context, ContextLock}, + context::{context::SyscallFrame, contexts, Context, ContextLock}, memory::{ get_page_info, the_zeroed_frame, Frame, RefCount, RmmA, RmmArch, TableKind, PAGE_SIZE, }, @@ -20,154 +20,157 @@ pub unsafe fn debugger(target_id: Option<*const ContextLock>, token: &mut CleanL let old_table = RmmA::table(TableKind::User); - let contexts = crate::percpu::get_all_contexts(token.downgrade()); - for context_arc in contexts.iter() { - if target_id.map_or(false, |target_id| Arc::as_ptr(&context_arc) != target_id) { - continue; - } - let context = context_arc.read(token.token()); - println!("{:p}: {}", Arc::as_ptr(&context_arc), context.name); + { + let mut contexts = contexts(token.downgrade()); + let (contexts, mut token) = contexts.token_split(); + for context_arc in contexts.iter().filter_map(|x| x.upgrade()) { + if target_id.map_or(false, |target_id| Arc::as_ptr(&context_arc) != target_id) { + continue; + } + let context = context_arc.read(token.token()); + println!("{:p}: {}", Arc::as_ptr(&context_arc), context.name); - let mut mark_frame_use = |frame| { - tree.entry(frame).or_insert((0, false)).0 += 1; - }; + let mut mark_frame_use = |frame| { + tree.entry(frame).or_insert((0, false)).0 += 1; + }; - match &context.syscall_head { - SyscallFrame::Free(head) => mark_frame_use(head.get()), - SyscallFrame::Used { _frame: head } => mark_frame_use(*head), - SyscallFrame::Dummy => {} - } - match &context.syscall_tail { - SyscallFrame::Free(tail) => mark_frame_use(tail.get()), - SyscallFrame::Used { _frame: tail } => mark_frame_use(*tail), - SyscallFrame::Dummy => {} - } + match &context.syscall_head { + SyscallFrame::Free(head) => mark_frame_use(head.get()), + SyscallFrame::Used { _frame: head } => mark_frame_use(*head), + SyscallFrame::Dummy => {} + } + match &context.syscall_tail { + SyscallFrame::Free(tail) => mark_frame_use(tail.get()), + SyscallFrame::Used { _frame: tail } => mark_frame_use(*tail), + SyscallFrame::Dummy => {} + } - if let Some(sig) = &context.sig { - mark_frame_use(sig.proc_control.get()); - mark_frame_use(sig.thread_control.get()); - } + if let Some(sig) = &context.sig { + mark_frame_use(sig.proc_control.get()); + mark_frame_use(sig.thread_control.get()); + } - // TODO: Lock ordering violation - let mut token = unsafe { CleanLockToken::new() }; + // TODO: Lock ordering violation + let mut token = unsafe { CleanLockToken::new() }; - // Switch to context page table to ensure syscall debug and stack dump will work - if let Some(ref space) = context.addr_space { - let was_new = spaces.insert( - space - .acquire_read(token.downgrade()) - .table - .utable - .table() - .phys() - .data(), - ); - unsafe { - RmmA::set_table( - TableKind::User, + // Switch to context page table to ensure syscall debug and stack dump will work + if let Some(ref space) = context.addr_space { + let was_new = spaces.insert( space .acquire_read(token.downgrade()) .table .utable .table() - .phys(), + .phys() + .data(), ); - #[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] - check_page_table_consistency( - &mut space.acquire_write(token.downgrade()), - was_new, - &mut tree, + unsafe { + RmmA::set_table( + TableKind::User, + space + .acquire_read(token.downgrade()) + .table + .utable + .table() + .phys(), + ); + #[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] + check_page_table_consistency( + &mut space.acquire_write(token.downgrade()), + was_new, + &mut tree, + ); + } + } + + println!("status: {:?}", context.status); + if !context.status_reason.is_empty() { + println!("reason: {}", context.status_reason); + } + if let Some([a, b, c, d, e, f, g]) = context.current_syscall() { + println!( + "syscall: {}", + crate::syscall::debug::format_call(a, b, c, d, e, f, g) ); } - } + if let Some(ref addr_space) = context.addr_space { + let addr_space = addr_space.acquire_read(token.downgrade()); + if !addr_space.grants.is_empty() { + println!("grants:"); + for (base, info) in addr_space.grants.iter() { + let size = info.page_count() * PAGE_SIZE; - println!("status: {:?}", context.status); - if !context.status_reason.is_empty() { - println!("reason: {}", context.status_reason); - } - if let Some([a, b, c, d, e, f, g]) = context.current_syscall() { - println!( - "syscall: {}", - crate::syscall::debug::format_call(a, b, c, d, e, f, g) - ); - } - if let Some(ref addr_space) = context.addr_space { - let addr_space = addr_space.acquire_read(token.downgrade()); - if !addr_space.grants.is_empty() { - println!("grants:"); - for (base, info) in addr_space.grants.iter() { - let size = info.page_count() * PAGE_SIZE; + let flags = format_args!( + "{}{}{}{}", + if info.flags().has_user() { "u" } else { "k" }, + if info.flags().has_present() { "r" } else { "-" }, + if info.flags().has_write() { "w" } else { "-" }, + if info.flags().has_execute() { "x" } else { "-" }, + ); - let flags = format_args!( - "{}{}{}{}", - if info.flags().has_user() { "u" } else { "k" }, - if info.flags().has_present() { "r" } else { "-" }, - if info.flags().has_write() { "w" } else { "-" }, - if info.flags().has_execute() { "x" } else { "-" }, - ); + #[cfg(target_arch = "aarch64")] + println!( + " virt 0x{:016x}:0x{:016x} {} size 0x{:08x} {:?}", + base.start_address().data(), + base.next_by(info.page_count() - 1).start_address().data() + 0xFFF, + flags, + size, + info.provider, + ); - #[cfg(target_arch = "aarch64")] - println!( - " virt 0x{:016x}:0x{:016x} {} size 0x{:08x} {:?}", - base.start_address().data(), - base.next_by(info.page_count() - 1).start_address().data() + 0xFFF, - flags, - size, - info.provider, - ); + // FIXME riscv64 implementation - // FIXME riscv64 implementation + #[cfg(target_arch = "x86")] + println!( + " virt 0x{:08x}:0x{:08x} {} size 0x{:08x} {:?}", + base.start_address().data(), + base.next_by(info.page_count()).start_address().data() + 0xFFF, + flags, + size, + info.provider, + ); - #[cfg(target_arch = "x86")] - println!( - " virt 0x{:08x}:0x{:08x} {} size 0x{:08x} {:?}", - base.start_address().data(), - base.next_by(info.page_count()).start_address().data() + 0xFFF, - flags, - size, - info.provider, - ); - - #[cfg(target_arch = "x86_64")] - println!( - " virt 0x{:016x}:0x{:016x} {} size 0x{:08x} {:?}", - base.start_address().data(), - base.start_address().data() + size - 1, - flags, - size, - info.provider, - ); + #[cfg(target_arch = "x86_64")] + println!( + " virt 0x{:016x}:0x{:016x} {} size 0x{:08x} {:?}", + base.start_address().data(), + base.start_address().data() + size - 1, + flags, + size, + info.provider, + ); + } } } - } - if let Some(regs) = context.regs() { - println!("regs:"); - regs.dump(); + if let Some(regs) = context.regs() { + println!("regs:"); + regs.dump(); - #[cfg(target_arch = "aarch64")] - dump_stack(&*context, regs.iret.sp_el0); + #[cfg(target_arch = "aarch64")] + dump_stack(&*context, regs.iret.sp_el0); - // FIXME riscv64 implementation + // FIXME riscv64 implementation - #[cfg(target_arch = "x86")] - dump_stack(&*context, regs.iret.esp); + #[cfg(target_arch = "x86")] + dump_stack(&*context, regs.iret.esp); - #[cfg(target_arch = "x86_64")] - { - unsafe { - x86::bits64::rflags::stac(); - } - dump_stack(&*context, regs.iret.rsp); - unsafe { - x86::bits64::rflags::clac(); + #[cfg(target_arch = "x86_64")] + { + unsafe { + x86::bits64::rflags::stac(); + } + dump_stack(&*context, regs.iret.rsp); + unsafe { + x86::bits64::rflags::clac(); + } } } + + // Switch to original page table + unsafe { RmmA::set_table(TableKind::User, old_table) }; + + println!(); } - - // Switch to original page table - unsafe { RmmA::set_table(TableKind::User, old_table) }; - - println!(); } #[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] crate::scheme::proc::foreach_addrsp(token, |addrsp, mut token| { diff --git a/src/percpu.rs b/src/percpu.rs index f3c4c3ee6d..f4ad5e66e6 100644 --- a/src/percpu.rs +++ b/src/percpu.rs @@ -1,5 +1,4 @@ use alloc::{ - collections::BTreeSet, sync::{Arc, Weak}, vec::Vec, }; @@ -13,13 +12,11 @@ use syscall::PtraceFlags; use crate::{ arch::device::ArchPercpuMisc, - context::{ - empty_cr3, memory::AddrSpaceWrapper, switch::ContextSwitchPercpu, ContextLock, ContextRef, - }, + context::{empty_cr3, memory::AddrSpaceWrapper, switch::ContextSwitchPercpu}, cpu_set::{LogicalCpuId, MAX_CPU_COUNT}, cpu_stats::{CpuStats, CpuStatsData}, ptrace::Session, - sync::{CleanLockToken, LockToken, RwLock, L1}, + sync::CleanLockToken, syscall::debug::SyscallDebugInfo, }; @@ -50,7 +47,6 @@ pub struct PercpuBlock { pub misc_arch_info: crate::arch::device::ArchPercpuMisc, pub stats: CpuStats, - pub contexts: RwLock>, } static ALL_PERCPU_BLOCKS: [AtomicPtr; MAX_CPU_COUNT as usize] = @@ -74,21 +70,6 @@ pub fn get_all_stats() -> Vec<(LogicalCpuId, CpuStatsData)> { res } -/// Get copy of all cpu ref contexts -pub fn get_all_contexts(mut token: LockToken<'_, L1>) -> Vec> { - let mut all_contexts = Vec::new(); - for block in ALL_PERCPU_BLOCKS - .iter() - .filter_map(|block| unsafe { block.load(Ordering::Relaxed).as_ref() }) - { - // TODO: When load balancer implemented, contexts need to be locked altogether - // TODO: Lock token violation, downgrade this to L2 later - let contexts = unsafe { &block.contexts.reupgradeable_read(token.token()) }; - all_contexts.extend(contexts.iter().filter_map(|x| x.upgrade())); - } - all_contexts -} - // PercpuBlock::current() is implemented somewhere in the arch-specific modules pub fn shootdown_tlb_ipi(target: Option) { @@ -219,7 +200,6 @@ impl PercpuBlock { misc_arch_info: ArchPercpuMisc::default(), stats: CpuStats::default(), - contexts: RwLock::new(BTreeSet::new()), } } } diff --git a/src/scheme/sys/block.rs b/src/scheme/sys/block.rs index 7e9683daa5..7ca46c8d4a 100644 --- a/src/scheme/sys/block.rs +++ b/src/scheme/sys/block.rs @@ -1,7 +1,7 @@ use alloc::{string::String, vec::Vec}; use core::fmt::Write; -use crate::{percpu, sync::CleanLockToken, syscall::error::Result}; +use crate::{context::contexts, sync::CleanLockToken, syscall::error::Result}; pub fn resource(token: &mut CleanLockToken) -> Result> { let mut string = String::new(); @@ -9,8 +9,9 @@ pub fn resource(token: &mut CleanLockToken) -> Result> { { let mut rows = Vec::new(); { - let contexts = percpu::get_all_contexts(token.downgrade()); - for context_lock in contexts { + let mut contexts = contexts(token.downgrade()); + let (contexts, mut token) = contexts.token_split(); + for context_lock in contexts.iter().filter_map(|x| x.upgrade()) { let context = context_lock.read(token.token()); rows.push((context.pid, context.name, context.status_reason)); } diff --git a/src/scheme/sys/context.rs b/src/scheme/sys/context.rs index f5b42f5b96..8ed3ce926e 100644 --- a/src/scheme/sys/context.rs +++ b/src/scheme/sys/context.rs @@ -5,7 +5,7 @@ use alloc::{ }; use core::fmt::Write; -use crate::{context, percpu, sync::CleanLockToken, syscall::error::Result}; +use crate::{context, context::contexts, sync::CleanLockToken, syscall::error::Result}; pub fn resource(token: &mut CleanLockToken) -> Result> { let mut string = format!( @@ -15,8 +15,9 @@ pub fn resource(token: &mut CleanLockToken) -> Result> { let mut rows = Vec::new(); { - let contexts = percpu::get_all_contexts(token.downgrade()); - for context_ref in contexts { + let mut contexts = contexts(token.downgrade()); + let (contexts, mut token) = contexts.token_split(); + for context_ref in contexts.iter().filter_map(|x| x.upgrade()) { let context = context_ref.read(token.token()); let addr_space = context.addr_space().map(|a| a.clone()); @@ -35,7 +36,7 @@ pub fn resource(token: &mut CleanLockToken) -> Result> { let heap = match addr_space { Ok(addr_space) => { - let addr_space_guard = addr_space.acquire_read(token.downgrade()); + let addr_space_guard = addr_space.acquire_read(token.token()); let mut private_memory = 0; let mut shared_memory = 0; // TODO: All user programs must have some grant in order for executable memory to even diff --git a/src/scheme/sys/fdstat.rs b/src/scheme/sys/fdstat.rs index 63c56beb61..304306b397 100644 --- a/src/scheme/sys/fdstat.rs +++ b/src/scheme/sys/fdstat.rs @@ -1,7 +1,6 @@ use crate::{ alloc::string::ToString, - context::{file::LockedFileDescription, memory::AddrSpaceWrapper}, - percpu, + context::{contexts, file::LockedFileDescription, memory::AddrSpaceWrapper}, scheme::{self, handles, KernelSchemes}, sync::CleanLockToken, syscall::error::Result, @@ -37,7 +36,9 @@ pub fn resource(token: &mut CleanLockToken) -> Result> { let mut schemes_guard = handles().read(token.token()); let (schemes, mut token) = schemes_guard.token_split(); - 'contexts: for context in percpu::get_all_contexts(token.token()) { + let mut contexts = contexts(token.token()); + let (contexts, mut token) = contexts.token_split(); + 'contexts: for context in contexts.iter().filter_map(|x| x.upgrade()) { let mut context_guard = context.read(token.token()); let (context, token) = context_guard.token_split(); let mut files_guard = context.files.read(token); diff --git a/src/scheme/sys/iostat.rs b/src/scheme/sys/iostat.rs index ae4d9d6bae..468d40dd93 100644 --- a/src/scheme/sys/iostat.rs +++ b/src/scheme/sys/iostat.rs @@ -4,7 +4,7 @@ use crate::{ memory::{Grant, PageSpan}, }, memory::PAGE_SIZE, - percpu, scheme, + scheme, sync::CleanLockToken, syscall::{ error::Result, @@ -22,7 +22,9 @@ fn inner(fpath_user: UserSliceRw, token: &mut CleanLockToken) -> Result> { let mut rows = Vec::new(); { - for context_ref in percpu::get_all_contexts(token.downgrade()) { + let mut contexts = context::contexts(token.downgrade()); + let (contexts, mut token) = contexts.token_split(); + for context_ref in contexts.iter().filter_map(|x| x.upgrade()) { let mut current = context_ref.read(token.token()); let (context, mut token) = current.token_split(); rows.push(( diff --git a/src/scheme/sys/stat.rs b/src/scheme/sys/stat.rs index 3381ed2caf..4149d673a1 100644 --- a/src/scheme/sys/stat.rs +++ b/src/scheme/sys/stat.rs @@ -1,9 +1,9 @@ use core::fmt::Write as _; use crate::{ - context::Status, + context::{contexts, Status}, cpu_stats::{get_context_switch_count, get_contexts_count, irq_counts}, - percpu::{self, get_all_stats}, + percpu::get_all_stats, sync::CleanLockToken, syscall::error::Result, time::START, @@ -76,10 +76,15 @@ fn get_contexts_stats(token: &mut CleanLockToken) -> (u64, u64) { let mut running = 0; let mut blocked = 0; - let statuses = percpu::get_all_contexts(token.downgrade()) - .iter() - .map(|context| context.read(token.token()).status.clone()) - .collect::>(); + let statuses = { + let mut contexts = contexts(token.downgrade()); + let (contexts, mut token) = contexts.token_split(); + contexts + .iter() + .filter_map(|x| x.upgrade()) + .map(|context| context.read(token.token()).status.clone()) + .collect::>() + }; for status in statuses { if matches!(status, Status::Runnable) { diff --git a/src/scheme/sys/syscall.rs b/src/scheme/sys/syscall.rs index ba83278315..f4b42f0a41 100644 --- a/src/scheme/sys/syscall.rs +++ b/src/scheme/sys/syscall.rs @@ -2,7 +2,7 @@ use alloc::{string::String, vec::Vec}; use core::fmt::Write; use crate::{ - percpu, + context::contexts, sync::CleanLockToken, syscall::{self, error::Result}, }; @@ -13,7 +13,9 @@ pub fn resource(token: &mut CleanLockToken) -> Result> { { let mut rows = Vec::new(); { - for context_ref in percpu::get_all_contexts(token.downgrade()) { + let mut contexts = contexts(token.downgrade()); + let (contexts, mut token) = contexts.token_split(); + for context_ref in contexts.iter().filter_map(|x| x.upgrade()) { let context = context_ref.read(token.token()); rows.push((context.pid, context.name, context.current_syscall())); } diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 0ed78ce673..e83da427b4 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -68,7 +68,7 @@ pub fn exit_this_context(excp: Option, token: &mut CleanLock ); } { - if !context::contexts_mut(token.token()).remove(&ContextRef(context_lock)) { + if !context::contexts_mut(token.downgrade()).remove(&ContextRef(context_lock)) { #[cfg(feature = "drop_panic")] { panic!("This context is not in the cpu")