std: fix issue with perma-locked mutexes on Fuchsia

This commit is contained in:
joboet 2022-07-12 12:25:43 +02:00
parent f7ae92c6bd
commit 0d91b08970
No known key found for this signature in database
GPG Key ID: 704E0149B0194B3C
2 changed files with 20 additions and 9 deletions

View File

@ -251,6 +251,9 @@ pub mod zircon {
pub const ZX_TIME_INFINITE: zx_time_t = zx_time_t::MAX; pub const ZX_TIME_INFINITE: zx_time_t = zx_time_t::MAX;
pub const ZX_OK: zx_status_t = 0; pub const ZX_OK: zx_status_t = 0;
pub const ZX_ERR_INVALID_ARGS: zx_status_t = -10;
pub const ZX_ERR_BAD_HANDLE: zx_status_t = -11;
pub const ZX_ERR_WRONG_TYPE: zx_status_t = -12;
pub const ZX_ERR_BAD_STATE: zx_status_t = -20; pub const ZX_ERR_BAD_STATE: zx_status_t = -20;
pub const ZX_ERR_TIMED_OUT: zx_status_t = -21; pub const ZX_ERR_TIMED_OUT: zx_status_t = -21;
@ -264,6 +267,7 @@ pub mod zircon {
) -> zx_status_t; ) -> zx_status_t;
pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t; pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t;
pub fn zx_futex_wake_single_owner(value_ptr: *const zx_futex_t) -> zx_status_t; pub fn zx_futex_wake_single_owner(value_ptr: *const zx_futex_t) -> zx_status_t;
pub fn zx_nanosleep(deadline: zx_time_t) -> zx_status_t;
pub fn zx_thread_self() -> zx_handle_t; pub fn zx_thread_self() -> zx_handle_t;
} }
} }

View File

@ -42,8 +42,9 @@ use crate::sync::atomic::{
Ordering::{Acquire, Relaxed, Release}, Ordering::{Acquire, Relaxed, Release},
}; };
use crate::sys::futex::zircon::{ use crate::sys::futex::zircon::{
zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t, zx_thread_self, ZX_ERR_BAD_STATE, zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t, zx_nanosleep, zx_thread_self,
ZX_OK, ZX_TIME_INFINITE, ZX_ERR_BAD_HANDLE, ZX_ERR_BAD_STATE, ZX_ERR_INVALID_ARGS, ZX_ERR_TIMED_OUT, ZX_ERR_WRONG_TYPE,
ZX_OK, ZX_TIME_INFINITE, ZX_TIME_INFINITE,
}; };
// The lowest two bits of a `zx_handle_t` are always set, so the lowest bit is used to mark the // The lowest two bits of a `zx_handle_t` are always set, so the lowest bit is used to mark the
@ -120,13 +121,19 @@ impl Mutex {
to_owner(state), to_owner(state),
ZX_TIME_INFINITE, ZX_TIME_INFINITE,
) { ) {
ZX_OK | ZX_ERR_BAD_STATE => (), ZX_OK | ZX_ERR_BAD_STATE | ZX_ERR_TIMED_OUT => (),
// Deadlock even in the case of reentrant locking, as leaking a guard // Either the current thread is trying to lock a mutex it has already locked,
// could lead to the same condition if the thread id is reused, but // or the previous owner did not unlock the mutex before exiting. Since it is
// panicking is not expected in that situation. This makes things // not possible to reliably detect which is the case, the current thread is
// quite a bit harder to debug, but encourages portable programming. // deadlocked. This makes debugging these cases quite a bit harder, but encourages
_ if to_owner(state) == thread_self => loop {}, // portable programming, since all other platforms do the same.
error => panic!("futex operation failed with error code {error}"), //
// Note that if the thread handle is reused, an arbitrary thread's priority could
// be boosted by the wait, but there is currently no way to prevent that.
ZX_ERR_INVALID_ARGS | ZX_ERR_BAD_HANDLE | ZX_ERR_WRONG_TYPE => loop {
zx_nanosleep(ZX_TIME_INFINITE);
},
error => unreachable!("unexpected error code in futex wait: {error}"),
} }
} }
} }