Commit 644e9ca9 authored by Maria Matejka's avatar Maria Matejka Committed by Maria Matejka
Browse files

Directly mapped pages are kept for future use if temporarily not needed

parent 9f24fef5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ void buffer_realloc(void **buf, unsigned *size, unsigned need, unsigned item_siz
u64 get_page_size(void);
void *alloc_page(void);
void free_page(void *);
extern uint pages_kept;

#ifdef HAVE_LIBDMALLOC
/*
+6 −1
Original line number Diff line number Diff line
@@ -91,7 +91,12 @@ cmd_show_memory(void)
  print_size("Routing tables:", rmemsize(rt_table_pool));
  print_size("Route attributes:", rmemsize(rta_pool));
  print_size("Protocols:", rmemsize(proto_pool));
  print_size("Total:", rmemsize(&root_pool));
  size_t total = rmemsize(&root_pool);
#ifdef HAVE_MMAP
  print_size("Standby memory:", get_page_size() * pages_kept);
  total += get_page_size() * pages_kept;
#endif
  print_size("Total:", total);
  cli_msg(0, "");
}

+51 −2
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@

#include "nest/bird.h"
#include "lib/resource.h"
#include "lib/lists.h"
#include "lib/event.h"

#include <stdlib.h>
#include <unistd.h>
@@ -17,8 +19,17 @@
#endif

#ifdef HAVE_MMAP
#define KEEP_PAGES  512

static u64 page_size = 0;
static _Bool use_fake = 0;

uint pages_kept = 0;
static list pages_list;

static void cleanup_pages(void *data);
static event page_cleanup_event = { .hook = cleanup_pages };

#else
static const u64 page_size = 4096; /* Fake page size */
#endif
@@ -48,6 +59,15 @@ void *
alloc_page(void)
{
#ifdef HAVE_MMAP
  if (pages_kept)
  {
    node *page = TAIL(pages_list);
    rem_node(page);
    pages_kept--;
    memset(page, 0, get_page_size());
    return page;
  }

  if (!use_fake)
  {
    void *ret = mmap(NULL, get_page_size(), PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -71,10 +91,39 @@ free_page(void *ptr)
#ifdef HAVE_MMAP
  if (!use_fake)
  {
    if (munmap(ptr, get_page_size()) < 0)
      bug("munmap(%p) failed: %m", ptr);
    if (!pages_kept)
      init_list(&pages_list);

    memset(ptr, 0, sizeof(node));
    add_tail(&pages_list, ptr);

    if (++pages_kept > KEEP_PAGES)
      ev_schedule(&page_cleanup_event);
  }
  else
#endif
    free(ptr);
}

#ifdef HAVE_MMAP
static void
cleanup_pages(void *data UNUSED)
{
  for (uint seen = 0; (pages_kept > KEEP_PAGES) && (seen < KEEP_PAGES); seen++)
  {
    void *ptr = HEAD(pages_list);
    rem_node(ptr);
    if (munmap(ptr, get_page_size()) == 0)
      pages_kept--;
#ifdef ENOMEM
    else if (errno == ENOMEM)
      add_tail(&pages_list, ptr);
#endif
    else
      bug("munmap(%p) failed: %m", ptr);
  }

  if (pages_kept > KEEP_PAGES)
    ev_schedule(&page_cleanup_event);
}
#endif