#include "pls/internal/base/stack_allocator.h"

#include "pls/internal/base/alignment.h"
#include "pls/internal/base/system_details.h"

namespace pls::internal::base {
char *mmap_stack_allocator::allocate_stack(size_t size) {
  const size_t page_size = system_details::get_page_size();

  const size_t stack_size = alignment::next_alignment(size, page_size);
  const size_t guard_size = page_size;

  const size_t mmap_size = stack_size + guard_size;
  char *const memory_range = reinterpret_cast<char *>(system_details::memory_map_range(mmap_size));

  char *const stack_block = memory_range + guard_size;
  char *const guard_block = memory_range;
  system_details::memory_protect_range(guard_block, guard_size);

  return stack_block;
}

void mmap_stack_allocator::free_stack(size_t size, char *stack) {
  const size_t page_size = system_details::get_page_size();
  const size_t guard_size = page_size;

  const size_t mmap_size = size + guard_size;
  char *const memory_range = stack - guard_size;

  system_details::memory_unmap_range(memory_range, mmap_size);
}
}
