]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Refactored the deferring framework into a separate structure
authorMaria Matejka <mq@ucw.cz>
Tue, 23 Apr 2024 15:35:00 +0000 (17:35 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 22 May 2024 09:34:34 +0000 (11:34 +0200)
lib/Makefile
lib/defer.c [new file with mode: 0644]
lib/defer.h [new file with mode: 0644]
lib/lockfree.c
lib/lockfree.h
sysdep/unix/io-loop.c

index f620f484ec706108a66d755a78ee8a3ed907f1a2..5c106e2a4905139553ce30c553f20e59ee85d14c 100644 (file)
@@ -1,4 +1,4 @@
-src := a-path.c a-set.c bitmap.c bitops.c blake2s.c blake2b.c checksum.c event.c flowspec.c idm.c ip.c lists.c lockfree.c mac.c md5.c mempool.c net.c netindex.c patmatch.c printf.c rcu.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
+src := a-path.c a-set.c bitmap.c bitops.c blake2s.c blake2b.c checksum.c defer.c event.c flowspec.c idm.c ip.c lists.c lockfree.c mac.c md5.c mempool.c net.c netindex.c patmatch.c printf.c rcu.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
 obj := $(src-o-files)
 $(all-daemon)
 
diff --git a/lib/defer.c b/lib/defer.c
new file mode 100644 (file)
index 0000000..3d51534
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *     BIRD -- Deferring calls to the end of the task
+ *
+ *     (c) 2024       Maria Matejka <mq@jmq.cz>
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include "lib/defer.h"
+
+_Thread_local struct deferred local_deferred = {};
+
+static void
+defer_execute(void *_ld)
+{
+  ASSERT_DIE(_ld == &local_deferred);
+
+  /* Run */
+  for (struct deferred_call *call = local_deferred.first; call; call = call->next)
+    call->hook(call);
+
+  /* Cleanup */
+  local_deferred.first = NULL;
+  local_deferred.last = &local_deferred.first;
+
+  lp_flush(local_deferred.lp);
+}
+
+void
+defer_init(linpool *lp)
+{
+  local_deferred = (struct deferred) {
+    .e = {
+      .hook = defer_execute,
+      .data = &local_deferred,
+    },
+    .lp = lp,
+    .last = &local_deferred.first,
+  };
+}
diff --git a/lib/defer.h b/lib/defer.h
new file mode 100644 (file)
index 0000000..b53d1ef
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *     BIRD -- Deferring calls to the end of the task
+ *
+ *     (c) 2024       Maria Matejka <mq@jmq.cz>
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+/**
+ * There are cases when we need to just run something multiple times after the
+ * current task ends, mostly for cleanup reasons, and it doesn't need the
+ * full-blown event list overhead. Therefore, one just can use this tool
+ * instead. */
+
+#include "lib/birdlib.h"
+#include "lib/event.h"
+#include "lib/resource.h"
+#include "lib/io-loop.h"
+
+struct deferred_call {
+  struct deferred_call *next;
+  void (*hook)(struct deferred_call *);
+};
+
+struct deferred {
+  event e;
+  linpool *lp;
+  struct deferred_call *first, **last;
+};
+
+extern _Thread_local struct deferred local_deferred;
+void defer_init(linpool *lp);
+
+static inline void defer_call(struct deferred_call *call, size_t actual_size) {
+  /* Reallocate the call to the appropriate linpool */
+  ASSERT_DIE(actual_size < 128);
+  struct deferred_call *a = lp_alloc(local_deferred.lp, actual_size);
+  memcpy(a, call, actual_size);
+
+  /* If first, send the actual event to the local thread */
+  if (local_deferred.last == &local_deferred.first)
+    ev_send_this_thread(&local_deferred.e);
+
+  /* Add to list */
+  a->next = NULL;
+  *local_deferred.last = a;
+  local_deferred.last = &a->next;
+}
index 11d9871524d383bd958a2e22303dae67812b0844..ff205f95c0d02ffb93242d61f700962473dde752 100644 (file)
 
 #define LOCAL_DEBUG
 
-_Thread_local struct lfuc_unlock_queue *lfuc_unlock_queue;
-
-void lfuc_unlock_deferred(void *_q)
+void lfuc_unlock_deferred(struct deferred_call *dc)
 {
-  struct lfuc_unlock_queue *q = _q;
-  for (u32 i = 0; i < q->pos; i++)
-    lfuc_unlock_immediately(q->block[i].c, q->block[i].el, q->block[i].ev);
-
-  free_page(q);
-  lfuc_unlock_queue = NULL;
+  struct lfuc_unlock_queue_item *luqi = SKIP_BACK(struct lfuc_unlock_queue_item, dc, dc);
+  lfuc_unlock_immediately(luqi->c, luqi->el, luqi->ev);
 }
 
 #if 0
index 15b45010334f430624586934a2b4e1b5c0314dee..0553aac124e67ad8cfb62a403f3dec2c816ee498 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef _BIRD_LOCKFREE_H_
 #define _BIRD_LOCKFREE_H_
 
+#include "lib/defer.h"
 #include "lib/event.h"
 #include "lib/rcu.h"
 #include "lib/settle.h"
@@ -108,46 +109,25 @@ static inline void lfuc_unlock_immediately(struct lfuc *c, event_list *el, event
 //  return uc - LFUC_IN_PROGRESS - 1;
 }
 
-extern _Thread_local struct lfuc_unlock_queue {
-  event e;
-  u32 pos;
-  struct lfuc_unlock_queue_block {
-    struct lfuc *c;
-    event_list *el;
-    event *ev;
-  } block[0];
-} *lfuc_unlock_queue;
+struct lfuc_unlock_queue_item {
+  struct deferred_call dc;
+  struct lfuc *c;
+  event_list *el;
+  event *ev;
+};
 
-void lfuc_unlock_deferred(void *queue);
+void lfuc_unlock_deferred(struct deferred_call *dc);
 
 static inline void lfuc_unlock(struct lfuc *c, event_list *el, event *ev)
 {
-  static u32 queue_items = 0;
-  if (queue_items == 0)
-  {
-    ASSERT_DIE((u64) page_size > sizeof(struct lfuc_unlock_queue) + sizeof(struct lfuc_unlock_queue_block));
-    queue_items = (page_size - OFFSETOF(struct lfuc_unlock_queue, block))
-      / sizeof lfuc_unlock_queue->block[0];
-  }
-
-  if (!lfuc_unlock_queue || (lfuc_unlock_queue->pos >= queue_items))
-  {
-    lfuc_unlock_queue = alloc_page();
-    *lfuc_unlock_queue = (struct lfuc_unlock_queue) {
-      .e = {
-       .hook = lfuc_unlock_deferred,
-       .data = lfuc_unlock_queue,
-      },
-    };
-
-    ev_send_this_thread(&lfuc_unlock_queue->e);
-  }
-
-  lfuc_unlock_queue->block[lfuc_unlock_queue->pos++] = (struct lfuc_unlock_queue_block) {
+  struct lfuc_unlock_queue_item luqi = {
+    .dc.hook = lfuc_unlock_deferred,
     .c = c,
     .el = el,
     .ev = ev,
   };
+
+  defer_call(&luqi.dc, sizeof luqi);
 }
 
 /**
index 76865a85af3ce50afc381f119739967c6624d826..fd0d9a2530b27233d67fca52f9138bef7b84b70f 100644 (file)
@@ -17,6 +17,7 @@
 #include "nest/bird.h"
 
 #include "lib/buffer.h"
+#include "lib/defer.h"
 #include "lib/lists.h"
 #include "lib/locking.h"
 #include "lib/resource.h"
@@ -794,6 +795,8 @@ bird_thread_main(void *arg)
   tmp_init(thr->pool, birdloop_domain(thr->meta));
   init_list(&thr->loops);
 
+  defer_init(lp_new(thr->pool));
+
   thr->sock_changed = 1;
 
   struct pfd pfd;
@@ -1377,6 +1380,8 @@ birdloop_init(void)
   birdloop_enter_locked(&main_birdloop);
   this_birdloop = &main_birdloop;
   this_thread = &main_thread;
+
+  defer_init(lp_new(&root_pool));
 }
 
 static void