]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Locking: forcefully unwinding locks to a previously stored state
authorMaria Matejka <mq@ucw.cz>
Wed, 3 Apr 2024 07:45:40 +0000 (09:45 +0200)
committerMaria Matejka <mq@ucw.cz>
Mon, 13 May 2024 06:52:48 +0000 (08:52 +0200)
lib/locking.h

index 86cbf72d9a95e10e2c53d28439db838f0b8d95c4..e79730f1d2de2396b0ead6f13ffa6584efcaa599 100644 (file)
@@ -81,6 +81,54 @@ extern DOMAIN(the_bird) the_bird_domain;
 
 #define ASSERT_THE_BIRD_LOCKED ({ if (!the_bird_locked()) bug("The BIRD lock must be locked here: %s:%d", __FILE__, __LINE__); })
 
+/* Unwind stored lock state helpers */
+struct locking_unwind_status {
+  struct lock_order *desired;
+  enum {
+    LOCKING_UNWIND_SAME,
+    LOCKING_UNWIND_UNLOCK,
+  } state;
+};
+
+static inline struct locking_unwind_status locking_unwind_helper(struct locking_unwind_status status, uint order)
+{
+  struct domain_generic **lsp = ((void *) &locking_stack) + order;
+  struct domain_generic **dp = ((void *) status.desired) + order;
+
+  if (!status.state)
+  {
+    /* Just checking that the rest of the stack is consistent */
+    if (*lsp != *dp)
+      bug("Mangled lock unwind state at order %d", order);
+  }
+  else if (*dp)
+    /* Stored state expects locked */
+    if (*lsp == *dp)
+      /* Indeed is locked, switch to check mode */
+      status.state = 0;
+    else
+      /* Not locked or locked elsewhere */
+      bug("Mangled lock unwind state at order %d", order);
+  else if (*lsp)
+    /* Stored state expects unlocked but we're locked */
+    DG_UNLOCK(*lsp);
+
+  return status;
+}
+
+static inline void locking_unwind(struct lock_order *desired)
+{
+  struct locking_unwind_status status = {
+    .desired = desired,
+    .state = LOCKING_UNWIND_UNLOCK,
+  };
+
+#define LOCK_ORDER_POS_HELPER(x)       DOMAIN_ORDER(x),
+#define LOCK_ORDER_POS                 MACRO_FOREACH(LOCK_ORDER_POS_HELPER, LOCK_ORDER)
+  MACRO_RPACK(locking_unwind_helper, status, LOCK_ORDER_POS);
+#undef LOCK_ORDER_POS_HELPER
+}
+
 /**
  *  Objects bound with domains
  *