aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/peer.h
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-05-24 19:18:04 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2017-05-30 18:07:28 +0200
commit6e6986e17d0dc99903c5134c7c0c8e78fbec7831 (patch)
treef1a571f1c04e021113abb3572dc31b44401a7634 /src/peer.h
parentnoise: precompute static-static ECDH operation (diff)
downloadwireguard-monolithic-historical-6e6986e17d0dc99903c5134c7c0c8e78fbec7831.tar.xz
wireguard-monolithic-historical-6e6986e17d0dc99903c5134c7c0c8e78fbec7831.zip
peer: use iterator macro instead of callback
Diffstat (limited to 'src/peer.h')
-rw-r--r--src/peer.h31
1 files changed, 28 insertions, 3 deletions
diff --git a/src/peer.h b/src/peer.h
index 8cb759a..d12c3c8 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -67,9 +67,34 @@ void peer_remove_all(struct wireguard_device *wg);
struct wireguard_peer *peer_lookup_by_index(struct wireguard_device *wg, u32 index);
-int peer_for_each_unlocked(struct wireguard_device *wg, int (*fn)(struct wireguard_peer *peer, void *ctx), void *data);
-int peer_for_each(struct wireguard_device *wg, int (*fn)(struct wireguard_peer *peer, void *ctx), void *data);
-
unsigned int peer_total_count(struct wireguard_device *wg);
+/* This is a macro iterator of essentially this:
+ *
+ * if (__should_lock)
+ * mutex_lock(&(__wg)->device_update_lock);
+ * else
+ * lockdep_assert_held(&(__wg)->device_update_lock)
+ * list_for_each_entry_safe (__peer, __temp, &(__wg)->peer_list, peer_list) {
+ * __peer = peer_rcu_get(__peer);
+ * if (!__peer)
+ * continue;
+ * ITERATOR_BODY
+ * peer_put(__peer);
+ * }
+ * if (__should_lock)
+ * mutex_unlock(&(__wg)->device_update_lock);
+ *
+ * While it's really ugly to look at, the code gcc produces from it is actually perfect.
+ */
+#define pfe_label(n) __PASTE(__PASTE(pfe_label_, n ## _), __LINE__)
+#define peer_for_each(__wg, __peer, __temp, __should_lock) \
+ if (1) { if (__should_lock) mutex_lock(&(__wg)->device_update_lock); else lockdep_assert_held(&(__wg)->device_update_lock); goto pfe_label(1); } else pfe_label(1): \
+ if (1) goto pfe_label(2); else while (1) if (1) { if (__should_lock) mutex_unlock(&(__wg)->device_update_lock); break; } else pfe_label(2): \
+ list_for_each_entry_safe (__peer, __temp, &(__wg)->peer_list, peer_list) \
+ if (0) pfe_label(3): break; else \
+ if (0); else for (__peer = peer_rcu_get(peer); __peer;) if (1) { goto pfe_label(4); pfe_label(5): break; } else while (1) if (1) goto pfe_label(5); else pfe_label(4): \
+ if (1) { goto pfe_label(6); pfe_label(7):; } else while (1) if (1) goto pfe_label(3); else while (1) if (1) goto pfe_label(7); else pfe_label(6): \
+ if (1) { goto pfe_label(8); pfe_label(9): peer_put(__peer); break; pfe_label(10): peer_put(__peer); } else while (1) if (1) goto pfe_label(9); else while (1) if (1) goto pfe_label(10); else pfe_label(8):
+
#endif