summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2021-11-24 17:30:13 +0100
committerMaria Matejka <mq@jmq.cz>2021-11-24 19:42:52 +0000
commit644e9ca94e2d10ba0c2de45f94523da2414328e3 (patch)
tree51dfbcb9a41b7ea06970b65264f5934960c2e09f
parent9f24fef5e91fb4df301242ede91ee7ac1b46b8a8 (diff)
Directly mapped pages are kept for future use if temporarily not needed
-rw-r--r--lib/resource.h1
-rw-r--r--nest/cmds.c7
-rw-r--r--sysdep/unix/alloc.c53
3 files changed, 58 insertions, 3 deletions
diff --git a/lib/resource.h b/lib/resource.h
index e65455c8..76e3745f 100644
--- a/lib/resource.h
+++ b/lib/resource.h
@@ -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
/*
diff --git a/nest/cmds.c b/nest/cmds.c
index 18f39eb5..f58923a7 100644
--- a/nest/cmds.c
+++ b/nest/cmds.c
@@ -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, "");
}
diff --git a/sysdep/unix/alloc.c b/sysdep/unix/alloc.c
index c525f713..5dd70c99 100644
--- a/sysdep/unix/alloc.c
+++ b/sysdep/unix/alloc.c
@@ -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