core: rewrite panic sites as explicit match+panic
Replace implicit unwrap()/expect() in the lock-ordered core with explicit
match arms. Lock-poison sites use one uniform message
("smarm: <lock> lock poisoned (core corrupt): {e}"); invariant sites panic
with a descriptive message naming the violated invariant. No behaviour
change: each rewrite preserves the prior panic-on-bad-arm semantics. Also
clears the accompanying clippy hygiene in these files (redundant_closure,
len_without_is_empty, too_many_arguments, unnecessary_sort_by,
missing_safety_doc, nonminimal_bool/unnecessary_unwrap).
This commit is contained in:
+89
-26
@@ -64,7 +64,10 @@ impl MutexCore {
|
||||
impl TimerTarget for MutexCore {
|
||||
fn on_timeout(&self, pid: Pid, epoch: u32) {
|
||||
let unpark = {
|
||||
let mut st = self.state.lock().unwrap();
|
||||
let mut st = match self.state.lock() {
|
||||
Ok(g) => g,
|
||||
Err(e) => panic!("smarm: mutex state lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
// Remove from waiters only if still there with matching epoch.
|
||||
// If the lock was already granted (holder == Some(pid)), the
|
||||
// timer fired after the grant — treat as no-op; the actor
|
||||
@@ -72,12 +75,12 @@ impl TimerTarget for MutexCore {
|
||||
if st.holder == Some(pid) {
|
||||
return;
|
||||
}
|
||||
let pos = st.waiters.iter().position(|w| w.pid == pid && w.epoch == epoch);
|
||||
if pos.is_some() {
|
||||
st.waiters.remove(pos.unwrap());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
match st.waiters.iter().position(|w| w.pid == pid && w.epoch == epoch) {
|
||||
Some(pos) => {
|
||||
st.waiters.remove(pos);
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
};
|
||||
if unpark {
|
||||
@@ -105,11 +108,17 @@ impl<T> Mutex<T> {
|
||||
}
|
||||
|
||||
pub fn set_default_timeout(&self, timeout: Duration) {
|
||||
self.core.state.lock().unwrap().default_timeout = timeout;
|
||||
match self.core.state.lock() {
|
||||
Ok(mut st) => st.default_timeout = timeout,
|
||||
Err(e) => panic!("smarm: mutex state lock poisoned (core corrupt): {e}"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lock(&self) -> Result<MutexGuard<'_, T>, LockTimeout> {
|
||||
let timeout = self.core.state.lock().unwrap().default_timeout;
|
||||
let timeout = match self.core.state.lock() {
|
||||
Ok(st) => st.default_timeout,
|
||||
Err(e) => panic!("smarm: mutex state lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
self.lock_timeout(timeout)
|
||||
}
|
||||
|
||||
@@ -122,12 +131,21 @@ impl<T> Mutex<T> {
|
||||
|
||||
// Fast path: nobody holds it.
|
||||
{
|
||||
let mut st = self.core.state.lock().unwrap();
|
||||
let mut st = match self.core.state.lock() {
|
||||
Ok(g) => g,
|
||||
Err(e) => panic!("smarm: mutex state lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
if st.holder.is_none() {
|
||||
st.holder = Some(me);
|
||||
drop(st);
|
||||
let value = self.value.lock().unwrap().take()
|
||||
.expect("Mutex: value missing on free fast path");
|
||||
let taken = match self.value.lock() {
|
||||
Ok(mut g) => g.take(),
|
||||
Err(e) => panic!("smarm: mutex value lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
let value = match taken {
|
||||
Some(v) => v,
|
||||
None => panic!("smarm: Mutex value missing on free fast path (core corrupt)"),
|
||||
};
|
||||
return Ok(MutexGuard { mutex: self, value: Some(value) });
|
||||
}
|
||||
}
|
||||
@@ -135,7 +153,10 @@ impl<T> Mutex<T> {
|
||||
// Slow path: register as a waiter, set timeout, park.
|
||||
let _np = scheduler::NoPreempt::enter();
|
||||
let epoch = {
|
||||
let mut st = self.core.state.lock().unwrap();
|
||||
let mut st = match self.core.state.lock() {
|
||||
Ok(g) => g,
|
||||
Err(e) => panic!("smarm: mutex state lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
// begin_wait is lock-free — legal under the state lock; this
|
||||
// makes the epoch atomic with the registration's visibility to
|
||||
// grants and timeouts.
|
||||
@@ -153,10 +174,19 @@ impl<T> Mutex<T> {
|
||||
// wait (both epoch-stamped; a stop wake unwinds out of
|
||||
// park_current). The one-shot interpretation below is therefore
|
||||
// exhaustive. Are we the holder?
|
||||
let is_holder = self.core.state.lock().unwrap().holder == Some(me);
|
||||
let is_holder = match self.core.state.lock() {
|
||||
Ok(st) => st.holder == Some(me),
|
||||
Err(e) => panic!("smarm: mutex state lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
if is_holder {
|
||||
let value = self.value.lock().unwrap().take()
|
||||
.expect("Mutex: value missing after grant");
|
||||
let taken = match self.value.lock() {
|
||||
Ok(mut g) => g.take(),
|
||||
Err(e) => panic!("smarm: mutex value lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
let value = match taken {
|
||||
Some(v) => v,
|
||||
None => panic!("smarm: Mutex value missing after grant (core corrupt)"),
|
||||
};
|
||||
Ok(MutexGuard { mutex: self, value: Some(value) })
|
||||
} else {
|
||||
Err(LockTimeout)
|
||||
@@ -165,14 +195,23 @@ impl<T> Mutex<T> {
|
||||
|
||||
pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
|
||||
let me = crate::actor::current_pid()?;
|
||||
let mut st = self.core.state.lock().unwrap();
|
||||
let mut st = match self.core.state.lock() {
|
||||
Ok(g) => g,
|
||||
Err(e) => panic!("smarm: mutex state lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
if st.holder.is_some() {
|
||||
return None;
|
||||
}
|
||||
st.holder = Some(me);
|
||||
drop(st);
|
||||
let value = self.value.lock().unwrap().take()
|
||||
.expect("Mutex: value missing on try_lock free path");
|
||||
let taken = match self.value.lock() {
|
||||
Ok(mut g) => g.take(),
|
||||
Err(e) => panic!("smarm: mutex value lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
let value = match taken {
|
||||
Some(v) => v,
|
||||
None => panic!("smarm: Mutex value missing on try_lock free path (core corrupt)"),
|
||||
};
|
||||
Some(MutexGuard { mutex: self, value: Some(value) })
|
||||
}
|
||||
|
||||
@@ -183,7 +222,10 @@ impl<T> Mutex<T> {
|
||||
// tracking and just grab the value mutex directly. This is safe because
|
||||
// outside the runtime there are no green threads competing.
|
||||
let value = loop {
|
||||
let v = self.value.lock().unwrap().take();
|
||||
let v = match self.value.lock() {
|
||||
Ok(mut g) => g.take(),
|
||||
Err(e) => panic!("smarm: mutex value lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
if let Some(v) = v { break v; }
|
||||
std::thread::yield_now();
|
||||
};
|
||||
@@ -212,30 +254,51 @@ pub struct MutexGuard<'a, T> {
|
||||
|
||||
impl<T> std::ops::Deref for MutexGuard<'_, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T { self.value.as_ref().expect("MutexGuard: value missing") }
|
||||
fn deref(&self) -> &T {
|
||||
match self.value.as_ref() {
|
||||
Some(v) => v,
|
||||
None => panic!("smarm: MutexGuard value missing (core corrupt)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::DerefMut for MutexGuard<'_, T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
self.value.as_mut().expect("MutexGuard: value missing")
|
||||
match self.value.as_mut() {
|
||||
Some(v) => v,
|
||||
None => panic!("smarm: MutexGuard value missing (core corrupt)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: std::fmt::Debug> std::fmt::Debug for MutexGuard<'_, T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let value = match self.value.as_ref() {
|
||||
Some(v) => v,
|
||||
None => panic!("smarm: MutexGuard value missing (core corrupt)"),
|
||||
};
|
||||
f.debug_tuple("MutexGuard")
|
||||
.field(self.value.as_ref().expect("MutexGuard: value missing"))
|
||||
.field(value)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for MutexGuard<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
let v = self.value.take().expect("MutexGuard: double drop");
|
||||
*self.mutex.value.lock().unwrap() = Some(v);
|
||||
let v = match self.value.take() {
|
||||
Some(v) => v,
|
||||
None => panic!("smarm: MutexGuard double drop (core corrupt)"),
|
||||
};
|
||||
match self.mutex.value.lock() {
|
||||
Ok(mut g) => *g = Some(v),
|
||||
Err(e) => panic!("smarm: mutex value lock poisoned (core corrupt): {e}"),
|
||||
}
|
||||
|
||||
let next = {
|
||||
let mut st = self.mutex.core.state.lock().unwrap();
|
||||
let mut st = match self.mutex.core.state.lock() {
|
||||
Ok(g) => g,
|
||||
Err(e) => panic!("smarm: mutex state lock poisoned (core corrupt): {e}"),
|
||||
};
|
||||
match st.waiters.pop_front() {
|
||||
Some(w) => {
|
||||
st.holder = Some(w.pid);
|
||||
|
||||
Reference in New Issue
Block a user