From ed3f0e1e64da301078b2784fde555ac0d1df4b0d Mon Sep 17 00:00:00 2001 From: vasilito Date: Thu, 2 Jul 2026 06:26:24 +0300 Subject: [PATCH] kernel: futex 64-shard hash table (Phase 0c, plan order #1) Re-apply P6-futex-sharding.patch from local/patches/kernel/ to the local fork. Replaces the single global Mutex with a 64-shard hash table to eliminate contention between futex operations on different addresses (different cores no longer serialize on one lock). src/syscall/futex.rs: static FUTEXES changes from a single Mutex to a [Mutex; 64] array indexed by hash of the physical address. This is the foundation patch for Phase 1 (Futex Completeness). All later futex work (REQUEUE, PI, robust, WAKE_OP) depends on the sharding being present. The Cargo.lock diff is the expected dep resolution update. Multi-threading plan Phase 0c, plan order #1 (P6-futex-sharding). --- Cargo.lock | 5 ++++- src/syscall/futex.rs | 14 ++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c6d07eb8e..184ca5d0af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -202,7 +202,6 @@ checksum = "64072665120942deff5fd5425d6c1811b854f4939e7f1c01ce755f64432bbea7" [[package]] name = "redox_syscall" version = "0.8.1" -source = "git+https://gitlab.redox-os.org/redox-os/syscall.git#79cb6d9057642be31623677458a93aa88145864f" dependencies = [ "bitflags 2.11.1", ] @@ -418,3 +417,7 @@ dependencies = [ "quote", "syn", ] + +[[patch.unused]] +name = "libredox" +version = "0.1.17" diff --git a/src/syscall/futex.rs b/src/syscall/futex.rs index 4c187b8ec8..9884d2b575 100644 --- a/src/syscall/futex.rs +++ b/src/syscall/futex.rs @@ -49,8 +49,13 @@ pub struct FutexEntry { // implement that fully in userspace. Although futex is probably the best API for process-shared // POSIX synchronization primitives, a local hash table and wait-for-thread kernel APIs (e.g. // lwp_park/lwp_unpark from NetBSD) could be a simpler replacement. -static FUTEXES: Mutex = - Mutex::new(FutexList::with_hasher(DefaultHashBuilder::new())); +const FUTEX_SHARDS: usize = 64; + +fn futex_shard(phys: PhysicalAddress) -> usize { + (phys.data() as usize >> 12) % FUTEX_SHARDS +} + +static FUTEXES: [Mutex; FUTEX_SHARDS] = [const { Mutex::new(FutexList::with_hasher(DefaultHashBuilder::new())) }; FUTEX_SHARDS]; fn validate_and_translate_virt(space: &AddrSpace, addr: VirtualAddress) -> Option { // TODO: Move this elsewhere! @@ -97,7 +102,7 @@ pub fn futex( { // TODO: Lock ordering violation let mut token = unsafe { CleanLockToken::new() }; - let mut futexes = FUTEXES.lock(token.token()); + let mut futexes = FUTEXES[futex_shard(target_physaddr)].lock(token.token()); let (futexes, mut token) = futexes.token_split(); let (fetched, expected) = if op == FUTEX_WAIT { @@ -181,10 +186,11 @@ pub fn futex( } FUTEX_WAKE => { let mut woken = 0; + let shard = futex_shard(target_physaddr); { drop(addr_space_guard); - let mut futexes_map = FUTEXES.lock(token.token()); + let mut futexes_map = FUTEXES[shard].lock(token.token()); let (futexes_map, mut token) = futexes_map.token_split(); let is_empty = if let Some(futexes) = futexes_map.get_mut(&target_physaddr) {