// SPDX-License-Identifier: GPL-2.0

//! So far the kernel's `Box` and `Vec` types can't be used by userspace test cases, since all users
//! of those types (e.g. `CString`) use kernel allocators for instantiation.
//!
//! In order to allow userspace test cases to make use of such types as well, implement the
//! `Cmalloc` allocator within the `allocator_test` module and type alias all kernel allocators to
//! `Cmalloc`. The `Cmalloc` allocator uses libc's `realloc()` function as allocator backend.

#![allow(missing_docs)]

use super::{flags::*, AllocError, Allocator, Flags};
use core::alloc::Layout;
use core::cmp;
use core::ptr;
use core::ptr::NonNull;

/// The userspace allocator based on libc.
pub struct Cmalloc;

pub type Kmalloc = Cmalloc;
pub type Vmalloc = Kmalloc;
pub type KVmalloc = Kmalloc;

impl Cmalloc {
    /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of
    /// `layout`.
    pub fn aligned_layout(layout: Layout) -> Layout {
        // Note that `layout.size()` (after padding) is guaranteed to be a multiple of
        // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return
        // a properly aligned object (see comments in `kmalloc()` for more information).
        layout.pad_to_align()
    }
}

extern "C" {
    #[link_name = "aligned_alloc"]
    fn libc_aligned_alloc(align: usize, size: usize) -> *mut crate::ffi::c_void;

    #[link_name = "free"]
    fn libc_free(ptr: *mut crate::ffi::c_void);
}

// SAFETY:
// - memory remains valid until it is explicitly freed,
// - passing a pointer to a valid memory allocation created by this `Allocator` is always OK,
// - `realloc` provides the guarantees as provided in the `# Guarantees` section.
unsafe impl Allocator for Cmalloc {
    unsafe fn realloc(
        ptr: Option<NonNull<u8>>,
        layout: Layout,
        old_layout: Layout,
        flags: Flags,
    ) -> Result<NonNull<[u8]>, AllocError> {
        let src = match ptr {
            Some(src) => {
                if old_layout.size() == 0 {
                    ptr::null_mut()
                } else {
                    src.as_ptr()
                }
            }
            None => ptr::null_mut(),
        };

        if layout.size() == 0 {
            // SAFETY: `src` is either NULL or was previously allocated with this `Allocator`
            unsafe { libc_free(src.cast()) };

            return Ok(NonNull::slice_from_raw_parts(
                crate::alloc::dangling_from_layout(layout),
                0,
            ));
        }

        // ISO C (ISO/IEC 9899:2011) defines `aligned_alloc`:
        //
        // > The value of alignment shall be a valid alignment supported by the implementation
        // [...].
        //
        // As an example of the "supported by the implementation" requirement, POSIX.1-2001 (IEEE
        // 1003.1-2001) defines `posix_memalign`:
        //
        // > The value of alignment shall be a power of two multiple of sizeof (void *).
        //
        // and POSIX-based implementations of `aligned_alloc` inherit this requirement. At the time
        // of writing, this is known to be the case on macOS (but not in glibc).
        //
        // Satisfy the stricter requirement to avoid spurious test failures on some platforms.
        let min_align = core::mem::size_of::<*const crate::ffi::c_void>();
        let layout = layout.align_to(min_align).map_err(|_| AllocError)?;
        let layout = layout.pad_to_align();

        // SAFETY: Returns either NULL or a pointer to a memory allocation that satisfies or
        // exceeds the given size and alignment requirements.
        let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) }.cast::<u8>();
        let dst = NonNull::new(dst).ok_or(AllocError)?;

        if flags.contains(__GFP_ZERO) {
            // SAFETY: The preceding calls to `libc_aligned_alloc` and `NonNull::new`
            // guarantee that `dst` points to memory of at least `layout.size()` bytes.
            unsafe { dst.as_ptr().write_bytes(0, layout.size()) };
        }

        if !src.is_null() {
            // SAFETY:
            // - `src` has previously been allocated with this `Allocator`; `dst` has just been
            //   newly allocated, hence the memory regions do not overlap.
            // - both` src` and `dst` are properly aligned and valid for reads and writes
            unsafe {
                ptr::copy_nonoverlapping(
                    src,
                    dst.as_ptr(),
                    cmp::min(layout.size(), old_layout.size()),
                )
            };
        }

        // SAFETY: `src` is either NULL or was previously allocated with this `Allocator`
        unsafe { libc_free(src.cast()) };

        Ok(NonNull::slice_from_raw_parts(dst, layout.size()))
    }
}
