ax_task/sync/
local_lock.rs1use alloc::vec::Vec;
4use core::ops::{Deref, DerefMut};
5
6use super::{MigrationGuard, SpinLock, SpinLockGuard};
7use crate::{
8 sched::{CpuId, cpu_topology_len},
9 thread::TaskError,
10};
11
12pub struct LocalLock<T> {
17 cpus: Vec<SpinLock<T>>,
18}
19
20#[must_use]
22pub struct LocalLockGuard<'a, T> {
23 owner: SpinLockGuard<'a, T>,
24 migration: MigrationGuard,
25}
26
27impl<T> LocalLock<T> {
28 pub fn new(mut init: impl FnMut(CpuId) -> T) -> Result<Self, TaskError> {
30 let cpus = (0..cpu_topology_len()?)
31 .map(|cpu| SpinLock::new(init(CpuId::new(cpu as u32))))
32 .collect();
33 Ok(Self { cpus })
34 }
35
36 pub fn lock(&self) -> LocalLockGuard<'_, T> {
38 let migration = MigrationGuard::new().expect("local lock requires task context");
39 let owner = self.cpus[migration.cpu().as_usize()].lock();
40 LocalLockGuard { owner, migration }
41 }
42
43 pub fn try_lock(&self) -> Option<LocalLockGuard<'_, T>> {
45 let migration = MigrationGuard::new().ok()?;
46 let owner = self.cpus[migration.cpu().as_usize()].try_lock()?;
47 Some(LocalLockGuard { owner, migration })
48 }
49
50 pub fn lock_irqsave(&self) -> LocalLockGuard<'_, T> {
52 self.lock()
53 }
54 pub fn try_lock_irqsave(&self) -> Option<LocalLockGuard<'_, T>> {
56 self.try_lock()
57 }
58}
59
60impl<T> LocalLockGuard<'_, T> {
61 pub fn cpu(&self) -> CpuId {
63 self.migration.cpu()
64 }
65}
66impl<T> Deref for LocalLockGuard<'_, T> {
67 type Target = T;
68 fn deref(&self) -> &T {
69 &self.owner
70 }
71}
72impl<T> DerefMut for LocalLockGuard<'_, T> {
73 fn deref_mut(&mut self) -> &mut T {
74 &mut self.owner
75 }
76}