<commit_before>#include <stdlib.h>
#include <sys/mman.h>
#include "safe.h"
#include "sync.h"
#include "param.h"
#include "stack.h"

static void * stack_alloc()
{
  const size_t align = PARAM_PAGE_SIZE;
  const size_t size = PARAM_STACK_SIZE;

  void * addr;
  SAFE_RZCALL(posix_memalign(&addr, align, size));
  SAFE_ASSERT(addr != NULL && PAGE_ALIGNED(addr));

  DEBUG_DUMP(3, "stack_alloc:", (addr, "%p"));
  return addr;
}

void stack_init(int id)
{
  if (id == 0) {
    fibrili_deq.stack = PARAM_STACK_ADDR;
  } else {
    fibrili_deq.stack = stack_alloc();
  }
}

void * stack_setup(struct _fibril_t * frptr)
{
  void ** rsp = fibrili_deq.stack + PARAM_STACK_SIZE;

  /** Reserve 128 byte at the bottom. */
  rsp -= 16;

  return rsp;
}

void stack_uninstall(struct _fibril_t * frptr)
{
  DEBUG_ASSERT(frptr != NULL);
  if (frptr->stack.ptr != fibrili_deq.stack) return;

  void * addr = frptr->stack.ptr;
  void * top  = frptr->stack.top;
  size_t size = PAGE_ALIGN_DOWN(top) - addr;

  DEBUG_DUMP(3, "munmap:", (frptr, "%p"), (addr, "%p"), (size, "0x%lx"));
  DEBUG_ASSERT(addr != NULL && addr < top && top < addr + PARAM_STACK_SIZE);
  SAFE_NNCALL(munmap(addr, size));

  /** Mark current stack as lost. */
  fibrili_deq.stack = stack_alloc();
}

void stack_reinstall(struct _fibril_t * frptr)
{
  DEBUG_ASSERT(frptr != NULL);
  void * stack = fibrili_deq.stack;

  if (frptr->stack.ptr == stack) return;

  free(stack);
  fibrili_deq.stack = frptr->stack.ptr;

  static int prot = PROT_READ | PROT_WRITE;
  static int flag = MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS;

  void * addr = frptr->stack.ptr;
  void * top  = frptr->stack.top;
  size_t size = PAGE_ALIGN_DOWN(top) - addr;

  DEBUG_DUMP(3, "mmap:", (frptr, "%p"), (addr, "%p"), (size, "0x%lx"));
  DEBUG_ASSERT(addr != NULL && addr < top && top < addr + PARAM_STACK_SIZE);
  SAFE_NNCALL(mmap(addr, size, prot, flag, -1, 0));
}
<commit_msg>[OP] Use mremap to reduce syscalls.<commit_after>#define _GNU_SOURCE
#include <stdlib.h>
#include <sys/mman.h>
#include "safe.h"
#include "sync.h"
#include "param.h"
#include "stack.h"

typedef struct _stack_t {
  struct _stack_t * next;
  void * addr;
} stack_t;

static __thread stack_t * _stacks;

static void stack_move(void * dest, size_t dest_len, void * src, size_t src_len)
{
  static const int prot = PROT_READ | PROT_WRITE;
  static const int remap_flags = MREMAP_MAYMOVE | MREMAP_FIXED;
  static const int map_flags = MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS
    | MAP_STACK | MAP_NORESERVE | MAP_GROWSDOWN;

  if (MAP_FAILED == mremap(src, src_len, dest_len, remap_flags, dest)) {
    SAFE_NNCALL(munmap(src, src_len));
    SAFE_NNCALL(mmap(dest, dest_len, prot, map_flags, -1, 0));
  }
}

static void * stack_alloc(void * src, size_t len)
{
  const size_t size = PARAM_STACK_SIZE;

  void * addr;
  stack_t * stack;

  if (NULL != (stack = _stacks)) {
    _stacks = stack->next;
    addr = stack->addr;
    free(stack);
    stack_move(addr, size, src, len);
  } else {
    const size_t align = PARAM_PAGE_SIZE;

    SAFE_RZCALL(posix_memalign(&addr, align, size));
    SAFE_ASSERT(addr != NULL && PAGE_ALIGNED(addr));
    DEBUG_DUMP(3, "stack_alloc:", (addr, "%p"));
  }

  return addr;
}

static void stack_free(void * addr, void * dest, size_t len)
{
  stack_move(dest, len, addr, PARAM_STACK_SIZE);

  stack_t * stack;
  SAFE_NZCALL(stack = malloc(sizeof(stack_t)));

  stack->next = _stacks;
  stack->addr = addr;

  _stacks = stack;
}

void stack_init(int id)
{
  if (id == 0) {
    fibrili_deq.stack = PARAM_STACK_ADDR;
  } else {
    fibrili_deq.stack = stack_alloc(NULL, 0);
  }
}

void * stack_setup(struct _fibril_t * frptr)
{
  void ** rsp = fibrili_deq.stack + PARAM_STACK_SIZE;

  /** Reserve 128 byte at the bottom. */
  rsp -= 16;
  return rsp;
}

void stack_uninstall(struct _fibril_t * frptr)
{
  DEBUG_ASSERT(frptr != NULL);
  if (frptr->stack.ptr != fibrili_deq.stack) return;

  void * addr = frptr->stack.ptr;
  void * top  = frptr->stack.top;
  size_t size = PAGE_ALIGN_DOWN(top) - addr;

  DEBUG_DUMP(3, "install:", (frptr, "%p"), (addr, "%p"), (size, "0x%lx"));
  DEBUG_ASSERT(addr != NULL && addr < top && top < addr + PARAM_STACK_SIZE);
  fibrili_deq.stack = stack_alloc(addr, size);
}

void stack_reinstall(struct _fibril_t * frptr)
{
  DEBUG_ASSERT(frptr != NULL);
  if (frptr->stack.ptr == fibrili_deq.stack) return;

  void * addr = frptr->stack.ptr;
  void * top  = frptr->stack.top;
  size_t size = PAGE_ALIGN_DOWN(top) - addr;

  DEBUG_DUMP(3, "reinstall:", (frptr, "%p"), (addr, "%p"), (size, "0x%lx"));
  DEBUG_ASSERT(addr != NULL && addr < top && top < addr + PARAM_STACK_SIZE);

  stack_free(fibrili_deq.stack, addr, size);
  fibrili_deq.stack = frptr->stack.ptr;
}

{'fraction_non_alphanumeric': 0.15384615384615385, 'fraction_numerical': 0.00572155117609663, 'mean_word_length': 4.005302226935313, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '286154', 'n_tokens_mistral': 1964, 'n_tokens_neox': 1895, 'n_words': 421}