//! Thread implementation backed by μITRON tasks. Assumes `acre_tsk` and
//! `exd_tsk` are available.

use crate::cell::UnsafeCell;
use crate::mem::ManuallyDrop;
use crate::ptr::NonNull;
use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
use crate::sys::pal::itron::error::{ItronError, expect_success, expect_success_aborting};
use crate::sys::pal::itron::time::dur2reltims;
use crate::sys::pal::itron::{abi, task};
use crate::thread::ThreadInit;
use crate::time::Duration;
use crate::{hint, io};

pub struct Thread {
    p_inner: NonNull<ThreadInner>,

    /// The ID of the underlying task.
    task: abi::ID,
}

// Safety: There's nothing in `Thread` that ties it to the original creator. It
//         can be dropped by any threads.
unsafe impl Send for Thread {}
// Safety: `Thread` provides no methods that take `&self`.
unsafe impl Sync for Thread {}

/// State data shared between a parent thread and child thread. It's dropped on
/// a transition to one of the final states.
struct ThreadInner {
    /// This field is used on thread creation to pass initialization data from
    /// `Thread::new` to the created task.
    init: UnsafeCell<ManuallyDrop<Box<ThreadInit>>>,

    /// A state machine. Each transition is annotated with `[...]` in the
    /// source code.
    ///
    /// ```text
    ///
    ///    <P>: parent, <C>: child, (?): don't-care
    ///
    ///       DETACHED (-1)  -------------------->  EXITED (?)
    ///                        <C>finish/exd_tsk
    ///          ^
    ///          |
    ///          | <P>detach
    ///          |
    ///
    ///       INIT (0)  ----------------------->  FINISHED (-1)
    ///                        <C>finish
    ///          |                                    |
    ///          | <P>join/slp_tsk                    | <P>join/del_tsk
    ///          |                                    | <P>detach/del_tsk
    ///          v                                    v
    ///
    ///       JOINING                              JOINED (?)
    ///     (parent_tid)
    ///                                            ^
    ///             \                             /
    ///              \  <C>finish/wup_tsk        / <P>slp_tsk-complete/ter_tsk
    ///               \                         /                      & del_tsk
    ///                \                       /
    ///                 '--> JOIN_FINALIZE ---'
    ///                          (-1)
    ///
    lifecycle: Atomic<usize>,
}

// Safety: The only `!Sync` field, `ThreadInner::init`, is only touched by
//         the task represented by `ThreadInner`.
unsafe impl Sync for ThreadInner {}

const LIFECYCLE_INIT: usize = 0;
const LIFECYCLE_FINISHED: usize = usize::MAX;
const LIFECYCLE_DETACHED: usize = usize::MAX;
const LIFECYCLE_JOIN_FINALIZE: usize = usize::MAX;
const LIFECYCLE_DETACHED_OR_JOINED: usize = usize::MAX;
const LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE: usize = usize::MAX;
// there's no single value for `JOINING`

// 64KiB for 32-bit ISAs, 128KiB for 64-bit ISAs.
pub const DEFAULT_MIN_STACK_SIZE: usize = 0x4000 * size_of::<usize>();

impl Thread {
    /// # Safety
    ///
    /// See `thread::Builder::spawn_unchecked` for safety requirements.
    pub unsafe fn new(stack: usize, init: Box<ThreadInit>) -> io::Result<Thread> {
        let inner = Box::new(ThreadInner {
            init: UnsafeCell::new(ManuallyDrop::new(init)),
            lifecycle: AtomicUsize::new(LIFECYCLE_INIT),
        });

        unsafe extern "C" fn trampoline(exinf: isize) {
            let p_inner: *mut ThreadInner = crate::ptr::with_exposed_provenance_mut(exinf as usize);
            // Safety: `ThreadInner` is alive at this point
            let inner = unsafe { &*p_inner };

            // Safety: Since `trampoline` is called only once for each
            //         `ThreadInner` and only `trampoline` touches `init`,
            //         `init` contains contents and is safe to mutably borrow.
            let init = unsafe { ManuallyDrop::take(&mut *inner.init.get()) };
            let rust_start = init.init();
            rust_start();

            // Fix the current thread's state just in case, so that the
            // destructors won't abort
            // Safety: Not really unsafe
            let _ = unsafe { abi::unl_cpu() };
            let _ = unsafe { abi::ena_dsp() };

            // Run TLS destructors now because they are not
            // called automatically for terminated tasks.
            unsafe { crate::sys::thread_local::destructors::run() };

            let old_lifecycle = inner
                .lifecycle
                .swap(LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE, Ordering::AcqRel);

            match old_lifecycle {
                LIFECYCLE_DETACHED => {
                    // [DETACHED → EXITED]
                    // No one will ever join, so we'll ask the collector task to
                    // delete the task.

                    // In this case, `*p_inner`'s ownership has been moved to
                    // us, and we are responsible for dropping it. The acquire
                    // ordering ensures that the swap operation that wrote
                    // `LIFECYCLE_DETACHED` happens-before `Box::from_raw(
                    // p_inner)`.
                    // Safety: See above.
                    let _ = unsafe { Box::from_raw(p_inner) };

                    // Safety: There are no pinned references to the stack
                    unsafe { terminate_and_delete_current_task() };
                }
                LIFECYCLE_INIT => {
                    // [INIT → FINISHED]
                    // The parent hasn't decided whether to join or detach this
                    // thread yet. Whichever option the parent chooses,
                    // it'll have to delete this task.
                    // Since the parent might drop `*inner` as soon as it sees
                    // `FINISHED`, the release ordering must be used in the
                    // above `swap` call.
                }
                parent_tid => {
                    // Since the parent might drop `*inner` and terminate us as
                    // soon as it sees `JOIN_FINALIZE`, the release ordering
                    // must be used in the above `swap` call.
                    //
                    // To make the task referred to by `parent_tid` visible, we
                    // must use the acquire ordering in the above `swap` call.

                    // [JOINING → JOIN_FINALIZE]
                    // Wake up the parent task.
                    expect_success(
                        unsafe {
                            let mut er = abi::wup_tsk(parent_tid as _);
                            if er == abi::E_QOVR {
                                // `E_QOVR` indicates there's already
                                // a parking token
                                er = abi::E_OK;
                            }
                            er
                        },
                        &"wup_tsk",
                    );
                }
            }
        }

        let p_inner = Box::into_non_null(inner);

        let new_task = ItronError::err_if_negative(unsafe {
            abi::acre_tsk(&abi::T_CTSK {
                // Activate this task immediately
                tskatr: abi::TA_ACT,
                exinf: p_inner.as_ptr().expose_provenance() as abi::EXINF,
                // The entry point
                task: Some(trampoline),
                // Inherit the calling task's base priority
                itskpri: abi::TPRI_SELF,
                stksz: stack,
                // Let the kernel allocate the stack,
                stk: crate::ptr::null_mut(),
            })
        })
        .map_err(|e| e.as_io_error())?;

        Ok(Self { p_inner, task: new_task })
    }

    pub fn join(self) {
        // Safety: `ThreadInner` is alive at this point
        let inner = unsafe { self.p_inner.as_ref() };
        // Get the current task ID. Panicking here would cause a resource leak,
        // so just abort on failure.
        let current_task = task::current_task_id_aborting();
        debug_assert!(usize::try_from(current_task).is_ok());
        debug_assert_ne!(current_task as usize, LIFECYCLE_INIT);
        debug_assert_ne!(current_task as usize, LIFECYCLE_DETACHED);

        let current_task = current_task as usize;

        match inner.lifecycle.swap(current_task, Ordering::AcqRel) {
            LIFECYCLE_INIT => {
                // [INIT → JOINING]
                // The child task will transition the state to `JOIN_FINALIZE`
                // and wake us up.
                //
                // To make the task referred to by `current_task` visible from
                // the child task's point of view, we must use the release
                // ordering in the above `swap` call.
                loop {
                    expect_success_aborting(unsafe { abi::slp_tsk() }, &"slp_tsk");
                    // To synchronize with the child task's memory accesses to
                    // `inner` up to the point of the assignment of
                    // `JOIN_FINALIZE`, `Ordering::Acquire` must be used for the
                    // `load`.
                    if inner.lifecycle.load(Ordering::Acquire) == LIFECYCLE_JOIN_FINALIZE {
                        break;
                    }
                }

                // [JOIN_FINALIZE → JOINED]
            }
            LIFECYCLE_FINISHED => {
                // [FINISHED → JOINED]
                // To synchronize with the child task's memory accesses to
                // `inner` up to the point of the assignment of `FINISHED`,
                // `Ordering::Acquire` must be used for the above `swap` call.
            }
            _ => unsafe { hint::unreachable_unchecked() },
        }

        // Terminate and delete the task
        // Safety: `self.task` still represents a task we own (because this
        //         method or `detach_inner` is called only once for each
        //         `Thread`). The task indicated that it's safe to delete by
        //         entering the `FINISHED` or `JOIN_FINALIZE` state.
        unsafe { terminate_and_delete_task(self.task) };

        // In either case, we are responsible for dropping `inner`.
        // Safety: The contents of `*p_inner` will not be accessed hereafter
        let _inner = unsafe { Box::from_raw(self.p_inner.as_ptr()) };

        // Skip the destructor (because it would attempt to detach the thread)
        crate::mem::forget(self);
    }
}

impl Drop for Thread {
    fn drop(&mut self) {
        // Safety: `ThreadInner` is alive at this point
        let inner = unsafe { self.p_inner.as_ref() };

        // Detach the thread.
        match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::AcqRel) {
            LIFECYCLE_INIT => {
                // [INIT → DETACHED]
                // When the time comes, the child will figure out that no
                // one will ever join it.
                // The ownership of `*p_inner` is moved to the child thread.
                // The release ordering ensures that the above swap operation on
                // `lifecycle` happens-before the child thread's
                // `Box::from_raw(p_inner)`.
            }
            LIFECYCLE_FINISHED => {
                // [FINISHED → JOINED]
                // The task has already decided that we should delete the task.
                // To synchronize with the child task's memory accesses to
                // `inner` up to the point of the assignment of `FINISHED`,
                // the acquire ordering is required for the above `swap` call.

                // Terminate and delete the task
                // Safety: `self.task` still represents a task we own (because
                //         this method or `join_inner` is called only once for
                //         each `Thread`). The task indicated that it's safe to
                //         delete by entering the `FINISHED` state.
                unsafe { terminate_and_delete_task(self.task) };

                // Wwe are responsible for dropping `*p_inner`.
                // Safety: The contents of `*p_inner` will not be accessed hereafter
                let _ = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
            }
            _ => unsafe { hint::unreachable_unchecked() },
        }
    }
}

/// Terminates and deletes the specified task.
///
/// This function will abort if `deleted_task` refers to the calling task.
///
/// It is assumed that the specified task is solely managed by the caller -
/// i.e., other threads must not "resuscitate" the specified task or delete it
/// prematurely while this function is still in progress. It is allowed for the
/// specified task to exit by its own.
///
/// # Safety
///
/// The task must be safe to terminate. This is in general not true
/// because there might be pinned references to the task's stack.
unsafe fn terminate_and_delete_task(deleted_task: abi::ID) {
    // Terminate the task
    // Safety: Upheld by the caller
    match unsafe { abi::ter_tsk(deleted_task) } {
        // Indicates the task is already dormant, ignore it
        abi::E_OBJ => {}
        er => {
            expect_success_aborting(er, &"ter_tsk");
        }
    }

    // Delete the task
    // Safety: Upheld by the caller
    expect_success_aborting(unsafe { abi::del_tsk(deleted_task) }, &"del_tsk");
}

/// Terminates and deletes the calling task.
///
/// Atomicity is not required - i.e., it can be assumed that other threads won't
/// `ter_tsk` the calling task while this function is still in progress. (This
/// property makes it easy to implement this operation on μITRON-derived kernels
/// that don't support `exd_tsk`.)
///
/// # Safety
///
/// The task must be safe to terminate. This is in general not true
/// because there might be pinned references to the task's stack.
unsafe fn terminate_and_delete_current_task() -> ! {
    expect_success_aborting(unsafe { abi::exd_tsk() }, &"exd_tsk");
    // Safety: `exd_tsk` never returns on success
    unsafe { crate::hint::unreachable_unchecked() };
}

pub fn yield_now() {
    expect_success(unsafe { abi::rot_rdq(abi::TPRI_SELF) }, &"rot_rdq");
}

pub fn sleep(dur: Duration) {
    for timeout in dur2reltims(dur) {
        expect_success(unsafe { abi::dly_tsk(timeout) }, &"dly_tsk");
    }
}
