/// Helper macro to implement "split" locks. This may be needed when a very specific storage
/// layout for the locked type is required.
// pub macro split_spinlock(
// ) {
#[macro_export]
macro_rules! split_spinlock {
    (
        $(use $use:path;)*

        $(#[$meta:meta])*
        static $name:ident: $ty:ty = $init:expr;
    ) => {
        pub use $name::$name;

        #[allow(non_snake_case)]
        pub mod $name {
            $(use $use;)*

            use core::cell::UnsafeCell;
            use core::marker::PhantomData;
            use core::sync::atomic::{AtomicU32, Ordering};

            #[repr(transparent)]
            pub struct __Wrapper {
                inner: UnsafeCell<$ty>
            }

            $(#[$meta])*
            pub static $name: __Wrapper = __Wrapper {
                inner: UnsafeCell::new($init)
            };

            static __LOCK: AtomicU32 = AtomicU32::new(0);
            pub struct __Guard($crate::guard::IrqGuard<ArchitectureImpl>);
            pub struct __UnsafeGuard($crate::guard::IrqGuard<ArchitectureImpl>);

            impl __Wrapper {
                #[inline(never)]
                pub fn lock(&self) -> __Guard {
                    let irq = $crate::guard::IrqGuard::acquire();

                    while __LOCK.compare_exchange(0, 1, Ordering::Acquire, Ordering::Relaxed).is_err() {
                        core::hint::spin_loop();
                    }

                    __Guard(irq)
                }

                #[inline(never)]
                pub unsafe fn grab(&self) -> __UnsafeGuard {
                    let irq = $crate::guard::IrqGuard::acquire();
                    __UnsafeGuard(irq)
                }
            }

            unsafe impl Sync for __Wrapper {}

            impl core::ops::Deref for __Guard {
                type Target = $ty;

                fn deref(&self) -> &Self::Target {
                    unsafe { &*$name.inner.get() }
                }
            }

            impl core::ops::DerefMut for __Guard {
                fn deref_mut(&mut self) -> &mut Self::Target {
                    unsafe { &mut *$name.inner.get() }
                }
            }

            impl core::ops::Deref for __UnsafeGuard {
                type Target = $ty;

                fn deref(&self) -> &Self::Target {
                    unsafe { &*$name.inner.get() }
                }
            }
            impl core::ops::DerefMut for __UnsafeGuard {
                fn deref_mut(&mut self) -> &mut Self::Target {
                    unsafe { &mut *$name.inner.get() }
                }
            }

            impl Drop for __Guard {
                fn drop(&mut self) {
                    __LOCK.store(0, Ordering::Release)
                }
            }
        }
    };
}
