]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
alloc.c, mempool.c, netindex.c: before rc lock make sure we will be able to allocate...
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Wed, 11 Dec 2024 14:24:32 +0000 (15:24 +0100)
committerKaterina Kubecova <katerina.kubecova@nic.cz>
Wed, 11 Dec 2024 14:24:32 +0000 (15:24 +0100)
lib/defer.h
lib/lockfree.h
lib/mempool.c
lib/netindex.c
lib/resource.h
nest/cmds.c
nest/rt-table.c
sysdep/unix/alloc.c

index 6fed60241ebf8cedd2c70118e555dc1a8c1fbada..220a3281cf9d7bd10875da0ad39f5f12d4ca74dd 100644 (file)
@@ -54,4 +54,10 @@ defer_call(struct deferred_call *call, size_t actual_size)
   return a;
 }
 
+static inline void
+defer_expect(size_t size)
+{
+  lp_prealloc(local_deferred.lp, size);
+}
+
 #endif
index 8dc8f82dc1246bc8d71b13b681bee5e4e8e20d6f..b696bfb93307ae2e17f2b111dfcd47ed3edfb3a6 100644 (file)
@@ -130,6 +130,11 @@ static inline void lfuc_unlock(struct lfuc *c, event_list *el, event *ev)
   defer_call(&luqi.dc, sizeof luqi);
 }
 
+static inline void lfuc_unlock_expected(uint count)
+{
+  defer_expect(count * sizeof (struct lfuc_unlock_queue_item));
+}
+
 /**
  * lfuc_finished - auxiliary routine for prune event
  * @c: usecount structure
index 5940e57128638254adfa81195cf51b179e3c8966..b2628031bc7e721302835424fe0fcb5e705da6b7 100644 (file)
@@ -141,6 +141,23 @@ lp_alloc_slow(linpool *m, uint size)
       return c->data;
     }
 
+void
+lp_prealloc(linpool *m, uint size)
+{
+  ASSERT_DIE(DG_IS_LOCKED(resource_parent(&m->r)->domain));
+
+  if (size > LP_DATA_SIZE)
+    bug("Requested block size is too big to prealloc");
+
+  byte *a = (byte *) BIRD_ALIGN((unsigned long) m->ptr, CPU_STRUCT_ALIGN);
+  byte *e = a + size;
+
+  if (e <= m->end)
+    return;
+
+  lp_alloc_slow(m, size);
+}
+
 /**
  * lp_allocu - allocate unaligned memory from a &linpool
  * @m: linear memory pool
index 1bc43377e0cab514e75cff261b8ee36cea616747..5e9321c3afb834cba7935fbd32660e94099c3ca5 100644 (file)
@@ -302,6 +302,8 @@ void net_unlock_index(netindex_hash *h, struct netindex *i)
 struct netindex *
 net_find_index(netindex_hash *h, const net_addr *n)
 {
+  lfuc_unlock_expected(1);
+
   RCU_ANCHOR(u);
   struct netindex *ni = net_find_index_fragile(h, n);
   return (ni && net_validate_index(h, ni)) ? net_lock_revive_unlock(h, ni) : NULL;
index df5509e3b4c6551c6c8574bbe6661ae3c2c6eaa7..4cfee819cde969e6f4e5fb9dee395898dd947658 100644 (file)
@@ -103,6 +103,7 @@ void *lp_allocz(linpool *, unsigned size) ALLOC_SIZE(2);    /* With clear */
 void lp_flush(linpool *);                      /* Free everything, but leave linpool */
 lp_state *lp_save(linpool *m);                 /* Save state */
 void lp_restore(linpool *m, lp_state *p);      /* Restore state */
+void lp_prealloc(linpool *m, uint size);        /* Make sure we will be able to allocate the memory without requesting new blocks */
 
 static inline void lp_saved_cleanup(struct lp_state **lps)
 {
@@ -150,6 +151,7 @@ extern _Atomic int pages_kept;
 extern _Atomic int pages_kept_locally;
 extern _Atomic int pages_kept_cold;
 extern _Atomic int pages_kept_cold_index;
+extern _Atomic int cold_memory_failed_to_use;
 void *alloc_page(void);
 void free_page(void *);
 void flush_local_pages(void);
index a596773c9641b9f3cf50ae2b6630af4ad9968d7e..9c55d6fb001b3584dc4276341d24d754f3cf6baa 100644 (file)
@@ -136,6 +136,7 @@ cmd_show_memory(void)
   struct size_args cold = get_size_args(atomic_load_explicit(&pages_kept_cold, memory_order_relaxed) * page_size);
   cli_msg(-1018, "%-23s " SIZE_FORMAT, "Cold memory:", SIZE_ARGS(cold));
 #endif
+  cli_msg(-1028, "Failed to use cold memory: %i times", atomic_load_explicit(&cold_memory_failed_to_use, memory_order_relaxed));
   cli_msg(0, "");
 }
 
index cd37d94780c5e2be4d74fb8180594e6826ebbc8a..ab207497d0bbfe44d78ba02622fa86af2123e512 100644 (file)
@@ -750,6 +750,8 @@ enum aspa_result aspa_check(rtable *tab, const adata *path, bool force_upstream)
    * and check allowed directions */
   uint max_up = 0, min_up = 0, max_down = 0, min_down = 0;
 
+  lfuc_unlock_expected(5); /* Deferring linpool memory reservation to avoid skipping cold memory */
+
   RT_READ(tab, tr);
 
   for (uint ap=0; ap<nsz; ap++)
@@ -2269,6 +2271,8 @@ rte_import(struct rt_import_request *req, const net_addr *n, rte *new, struct rt
     return;
   }
 
+  lfuc_unlock_expected(5); /* Deferring linpool memory reservation to avoid skipping cold memory */
+
   RT_LOCKED(hook->table, tab)
   {
     u32 bs = atomic_load_explicit(&tab->routes_block_size, memory_order_acquire);
@@ -2481,6 +2485,8 @@ rt_net_feed_internal(struct rtable_reading *tr, u32 index, bool (*prefilter)(str
 struct rt_export_feed *
 rt_net_feed(rtable *t, const net_addr *a, const struct rt_pending_export *first)
 {
+  lfuc_unlock_expected(5); /* Deferring linpool memory reservation to avoid skipping cold memory */
+
   RT_READ(t, tr);
   const struct netindex *ni = net_find_index(tr->t->netindex, a);
   return ni ? rt_net_feed_internal(tr, ni->index, NULL, NULL, first) : NULL;
@@ -2498,6 +2504,8 @@ rt_net_best(rtable *t, const net_addr *a)
 {
   rte rt = {};
 
+  lfuc_unlock_expected(5); /* Deferring linpool memory reservation to avoid skipping cold memory */
+
   RT_READ(t, tr);
 
   struct netindex *i = net_find_index(t->netindex, a);
index 0432b9e265113546804ba6928cff41a9c69bada9..d7b3f095e01bee9813a7b9362e7e3234fd1af098 100644 (file)
@@ -126,6 +126,7 @@ long page_size = 0;
   static struct empty_pages *empty_pages = NULL;
   _Atomic int pages_kept_cold = 0;
   _Atomic int pages_kept_cold_index = 0;
+  _Atomic int cold_memory_failed_to_use = 0;
 
   static struct free_page * _Atomic page_stack = NULL;
   static _Thread_local struct free_page * local_page_stack = NULL;
@@ -219,6 +220,7 @@ alloc_page(void)
   {
     /* We can't lock and we actually shouldn't alloc either when rcu is active
      * but that's a quest for another day. */
+    atomic_fetch_add_explicit(&cold_memory_failed_to_use, 1, memory_order_relaxed);
   }
   else
   {