Track which CPUs are using any given AddrSpace.

This commit is contained in:
4lDO2
2024-02-09 14:15:20 +01:00
parent 0c6c857012
commit bb30530ea0
2 changed files with 21 additions and 10 deletions
+18 -9
View File
@@ -221,6 +221,8 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) {
);
}
let this_cpu = crate::cpu_id();
match next.addr_space {
// Since Arc essentially just wraps a pointer, in this case a regular pointer (as opposed
// to dyn or slice fat pointers), and NonNull optimization exists, map_or will hopefully be
@@ -231,18 +233,25 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) {
.as_ref()
.map_or(true, |prev_space| !Arc::ptr_eq(prev_space, next_space))
{
// Suppose we have two sibling threads A and B. A runs on CPU 0 and B on CPU 1. A
// recently called yield and is now here about to switch back. Meanwhile, B is
// currently creating a new mapping in their shared address space, for example a
// message on a channel.
//
// Unless we acquire this lock, it may be possible that the TLB will not contain new
// entries. While this can be caught and corrected in a page fault handler, this is not
// true when entries are removed from a page table!
next_space.read().table.utable.make_current();
if let Some(ref prev_space) = prev.addr_space {
prev_space.read().used_by.atomic_clear(this_cpu);
}
// This lock needs to be held, because if the address space is write-locked by some
// context that is e.g. unmapping memory, we either need to switch after its
// changes have been made, or it needs to know this context is potentially using
// this address space, at that time.
let next_space = next_space.read();
next_space.used_by.atomic_set(this_cpu);
next_space.table.utable.make_current();
}
}
None => {
// The next context is kernel-only, so switch to the page table without any user
// mappings.
if let Some(ref prev_space) = prev.addr_space {
prev_space.read().used_by.atomic_clear(this_cpu);
}
RmmA::set_table(TableKind::User, empty_cr3());
}
}
+3 -1
View File
@@ -15,7 +15,7 @@ use crate::{
mapper::{Flusher, InactiveFlusher, PageFlushAll},
Page, PageFlags, PageMapper, RmmA, TableKind, VirtualAddress,
},
scheme::{self, KernelSchemes},
scheme::{self, KernelSchemes}, cpu_set::LogicalCpuSet,
};
use super::{context::HardBlockedReason, file::FileDescription};
@@ -82,6 +82,7 @@ pub fn new_addrspace() -> Result<Arc<RwLock<AddrSpace>>> {
pub struct AddrSpace {
pub table: Table,
pub grants: UserGrants,
pub used_by: LogicalCpuSet,
/// Lowest offset for mmap invocations where the user has not already specified the offset
/// (using MAP_FIXED/MAP_FIXED_NOREPLACE). Cf. Linux's `/proc/sys/vm/mmap_min_addr`, but with
/// the exception that we have a memory safe kernel which doesn't have to protect itself
@@ -188,6 +189,7 @@ impl AddrSpace {
grants: UserGrants::new(),
table: setup_new_utable()?,
mmap_min: MMAP_MIN_DEFAULT,
used_by: LogicalCpuSet::empty(),
})
}
pub fn is_current(&self) -> bool {