]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Directly mapped pages are kept for future use if temporarily not needed
authorMaria Matejka <mq@ucw.cz>
Wed, 24 Nov 2021 16:30:13 +0000 (17:30 +0100)
committerMaria Matejka <mq@jmq.cz>
Wed, 24 Nov 2021 19:42:52 +0000 (19:42 +0000)
lib/resource.h
nest/cmds.c
sysdep/unix/alloc.c

index e65455c8ed1dc1908f53064a1773517aaa450ba2..76e3745fee0dcb4deedd4ec20a11f69078eb7be9 100644 (file)
@@ -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
 /*
index 18f39eb56c10de0b9cad38410ea78368aede9c3e..f58923a76e3f983c40f8f6604ab8bd670e26a957 100644 (file)
@@ -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, "");
 }
 
index c525f713d56f87520ed206718da79636f7687ea9..5dd70c990c923f3f46eeb3dd41a5457dc9f4d622 100644 (file)
@@ -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>
 #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