]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Locking subsystem: Just a global BIRD lock to begin with.
authorMaria Matejka <mq@ucw.cz>
Thu, 4 Feb 2021 14:52:42 +0000 (15:52 +0100)
committerMaria Matejka <mq@ucw.cz>
Mon, 22 Nov 2021 18:05:43 +0000 (19:05 +0100)
lib/birdlib.h
lib/lists.c
lib/locking.h [new file with mode: 0644]
sysdep/unix/Makefile
sysdep/unix/coroutine.c [new file with mode: 0644]
sysdep/unix/io.c
sysdep/unix/main.c

index dc8bd00fcf9eaef34974841f0f14ac4c13000b11..3dc39d192f89aca36b87052a2a7bbf26934ab82a 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _BIRD_BIRDLIB_H_
 #define _BIRD_BIRDLIB_H_
 
+#include "sysdep/config.h"
 #include "lib/alloca.h"
 
 /* Ugly structure offset handling macros */
index 58d5107396820c04df5a753301f13790afdab170..dc2e4cbb9d6fdc0115b3bdf9b6657acb357a4071 100644 (file)
@@ -26,7 +26,7 @@
 
 #define _BIRD_LISTS_C_
 
-#include "nest/bird.h"
+#include "lib/birdlib.h"
 #include "lib/lists.h"
 
 LIST_INLINE int
diff --git a/lib/locking.h b/lib/locking.h
new file mode 100644 (file)
index 0000000..eb1bc8f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *     BIRD Library -- Locking
+ *
+ *     (c) 2020--2021 Maria Matejka <mq@jmq.cz>
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_LOCKING_H_
+#define _BIRD_LOCKING_H_
+
+struct domain_generic;
+
+/* Here define the global lock order; first to last. */
+struct lock_order {
+  struct domain_generic *the_bird;
+};
+
+#define LOCK_ORDER_DEPTH  (sizeof(struct lock_order) / sizeof(struct domain_generic *))
+
+extern _Thread_local struct lock_order locking_stack;
+extern _Thread_local struct domain_generic **last_locked;
+
+#define DOMAIN(type) struct domain__##type
+#define DEFINE_DOMAIN(type) DOMAIN(type) { struct domain_generic *type; }
+
+#define DOMAIN_NEW(type, name)  (DOMAIN(type)) { .type = domain_new(name) }
+struct domain_generic *domain_new(const char *name);
+
+#define DOMAIN_NULL(type)   (DOMAIN(type)) {}
+
+#define LOCK_DOMAIN(type, d)   do_lock(((d).type), &(locking_stack.type))
+#define UNLOCK_DOMAIN(type, d)  do_unlock(((d).type), &(locking_stack.type))
+
+/* Internal for locking */
+void do_lock(struct domain_generic *dg, struct domain_generic **lsp);
+void do_unlock(struct domain_generic *dg, struct domain_generic **lsp);
+
+/* Use with care. To be removed in near future. */
+DEFINE_DOMAIN(the_bird);
+extern DOMAIN(the_bird) the_bird_domain;
+
+#define the_bird_lock()                LOCK_DOMAIN(the_bird, the_bird_domain)
+#define the_bird_unlock()      UNLOCK_DOMAIN(the_bird, the_bird_domain)
+
+#endif
index d0d36b5f7cdbe404c6a64a35220a3345ac504ab3..69cf8131e1241444071ef002b120a77aded7bb7f 100644 (file)
@@ -1,4 +1,4 @@
-src := alloc.c io.c krt.c log.c main.c random.c
+src := alloc.c io.c krt.c log.c main.c random.c coroutine.c
 obj := $(src-o-files)
 $(all-daemon)
 $(cf-local)
diff --git a/sysdep/unix/coroutine.c b/sysdep/unix/coroutine.c
new file mode 100644 (file)
index 0000000..05f101f
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *     BIRD Coroutines
+ *
+ *     (c) 2017 Martin Mares <mj@ucw.cz>
+ *     (c) 2020 Maria Matejka <mq@jmq.cz>
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#undef LOCAL_DEBUG
+
+#undef DEBUG_LOCKING
+
+#include "lib/birdlib.h"
+#include "lib/locking.h"
+#include "lib/resource.h"
+
+/*
+ *     Implementation of coroutines based on POSIX threads
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdatomic.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ *     Locking subsystem
+ */
+
+#define ASSERT_NO_LOCK ASSERT_DIE(last_locked == NULL)
+
+struct domain_generic {
+  pthread_mutex_t mutex;
+  struct domain_generic **prev;
+  struct lock_order *locked_by;
+  const char *name;
+};
+
+#define DOMAIN_INIT(_name) { .mutex = PTHREAD_MUTEX_INITIALIZER, .name = _name }
+
+static struct domain_generic the_bird_domain_gen = DOMAIN_INIT("The BIRD");
+
+DOMAIN(the_bird) the_bird_domain = { .the_bird = &the_bird_domain_gen };
+
+struct domain_generic *
+domain_new(const char *name)
+{
+  struct domain_generic *dg = xmalloc(sizeof(struct domain_generic));
+  *dg = (struct domain_generic) DOMAIN_INIT(name);
+  return dg;
+}
+
+void
+domain_free(struct domain_generic *dg)
+{
+  pthread_mutex_destroy(&dg->mutex);
+  xfree(dg);
+}
+
+_Thread_local struct lock_order locking_stack = {};
+_Thread_local struct domain_generic **last_locked = NULL;
+
+void do_lock(struct domain_generic *dg, struct domain_generic **lsp)
+{
+  if (lsp <= last_locked)
+    bug("Trying to lock in a bad order");
+  if (*lsp)
+    bug("Inconsistent locking stack state on lock");
+
+  pthread_mutex_lock(&dg->mutex);
+
+  if (dg->prev || dg->locked_by)
+    bug("Previous unlock not finished correctly");
+  dg->prev = last_locked;
+  *lsp = dg;
+  last_locked = lsp;
+  dg->locked_by = &locking_stack;
+}
+
+void do_unlock(struct domain_generic *dg, struct domain_generic **lsp)
+{
+  if (dg->locked_by != &locking_stack)
+    bug("Inconsistent domain state on unlock");
+  if ((last_locked != lsp) || (*lsp != dg))
+    bug("Inconsistent locking stack state on unlock");
+  dg->locked_by = NULL;
+  last_locked = dg->prev;
+  *lsp = NULL;
+  dg->prev = NULL;
+  pthread_mutex_unlock(&dg->mutex);
+}
+
index 3d67d0a7a8f07e6baf45d14470af3c5d897a05de..2946786795a4beffe83dc8dafc07fd0124d33e8b 100644 (file)
@@ -36,6 +36,7 @@
 #include "lib/resource.h"
 #include "lib/socket.h"
 #include "lib/event.h"
+#include "lib/locking.h"
 #include "lib/timer.h"
 #include "lib/string.h"
 #include "nest/iface.h"
@@ -2263,7 +2264,9 @@ io_loop(void)
 
       /* And finally enter poll() to find active sockets */
       watchdog_stop();
+      the_bird_unlock();
       pout = poll(pfd, nfds, poll_tout);
+      the_bird_lock();
       watchdog_start();
 
       if (pout < 0)
index 7e8ea0dc550b2eba77100bc5eb5288b357757623..dabfc5546c7238e3cc462178d876d52487cc4a59 100644 (file)
@@ -28,6 +28,7 @@
 #include "lib/resource.h"
 #include "lib/socket.h"
 #include "lib/event.h"
+#include "lib/locking.h"
 #include "lib/timer.h"
 #include "lib/string.h"
 #include "nest/route.h"
@@ -959,6 +960,8 @@ main(int argc, char **argv)
       dup2(0, 2);
     }
 
+  the_bird_lock();
+
   main_thread_init();
 
   write_pid_file();