//! A priority inheriting mutex for Fuchsia.
//!
//! This is a port of the [mutex in Fuchsia's libsync]. Contrary to the original,
//! it does not abort the process when reentrant locking is detected, but deadlocks.
//!
//! Priority inheritance is achieved by storing the owning thread's handle in an
//! atomic variable. Fuchsia's futex operations support setting an owner thread
//! for a futex, which can boost that thread's priority while the futex is waited
//! upon.
//!
//! libsync is licenced under the following BSD-style licence:
//!
//! Copyright 2016 The Fuchsia Authors.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions are
//! met:
//!
//!    * Redistributions of source code must retain the above copyright
//!      notice, this list of conditions and the following disclaimer.
//!    * Redistributions in binary form must reproduce the above
//!      copyright notice, this list of conditions and the following
//!      disclaimer in the documentation and/or other materials provided
//!      with the distribution.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//! A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
//! OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
//! LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//! DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//! THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//! (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//! OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//!
//! [mutex in Fuchsia's libsync]: https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/system/ulib/sync/mutex.c

use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::sync::atomic::{Atomic, AtomicU32};
use crate::sys::fuchsia::{
    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_futex_wait, zx_futex_wake_single_owner, zx_handle_t,
    zx_thread_self,
};

// The lowest two bits of a `zx_handle_t` are always set, so the lowest bit is used to mark the
// mutex as contested by clearing it.
const CONTESTED_BIT: u32 = 1;
// This can never be a valid `zx_handle_t`.
const UNLOCKED: u32 = 0;

pub struct Mutex {
    futex: Atomic<u32>,
}

#[inline]
fn to_state(owner: zx_handle_t) -> u32 {
    owner
}

#[inline]
fn to_owner(state: u32) -> zx_handle_t {
    state | CONTESTED_BIT
}

#[inline]
fn is_contested(state: u32) -> bool {
    state & CONTESTED_BIT == 0
}

#[inline]
fn mark_contested(state: u32) -> u32 {
    state & !CONTESTED_BIT
}

impl Mutex {
    #[inline]
    pub const fn new() -> Mutex {
        Mutex { futex: AtomicU32::new(UNLOCKED) }
    }

    #[inline]
    pub fn try_lock(&self) -> bool {
        let thread_self = zx_thread_self();
        self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed).is_ok()
    }

    #[inline]
    pub fn lock(&self) {
        let thread_self = zx_thread_self();
        if let Err(state) =
            self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed)
        {
            unsafe {
                self.lock_contested(state, thread_self);
            }
        }
    }

    /// # Safety
    /// `thread_self` must be the handle for the current thread.
    #[cold]
    unsafe fn lock_contested(&self, mut state: u32, thread_self: zx_handle_t) {
        let owned_state = mark_contested(to_state(thread_self));
        loop {
            // Mark the mutex as contested if it is not already.
            let contested = mark_contested(state);
            if is_contested(state)
                || self.futex.compare_exchange(state, contested, Relaxed, Relaxed).is_ok()
            {
                // The mutex has been marked as contested, wait for the state to change.
                unsafe {
                    match zx_futex_wait(
                        &self.futex,
                        AtomicU32::new(contested),
                        to_owner(state),
                        ZX_TIME_INFINITE,
                    ) {
                        ZX_OK | ZX_ERR_BAD_STATE | ZX_ERR_TIMED_OUT => (),
                        // Note that if a thread handle is reused after its associated thread
                        // exits without unlocking the mutex, 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 => {
                            panic!(
                                "either the current thread is trying to lock a mutex it has
                                already locked, or the previous owner did not unlock the mutex
                                before exiting"
                            )
                        }
                        error => panic!("unexpected error in zx_futex_wait: {error}"),
                    }
                }
            }

            // The state has changed or a wakeup occurred, try to lock the mutex.
            match self.futex.compare_exchange(UNLOCKED, owned_state, Acquire, Relaxed) {
                Ok(_) => return,
                Err(updated) => state = updated,
            }
        }
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        if is_contested(self.futex.swap(UNLOCKED, Release)) {
            // The woken thread will mark the mutex as contested again,
            // and return here, waking until there are no waiters left,
            // in which case this is a noop.
            self.wake();
        }
    }

    #[cold]
    fn wake(&self) {
        unsafe {
            zx_futex_wake_single_owner(&self.futex);
        }
    }
}
