diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-05-24 19:18:04 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-05-30 18:07:28 +0200 |
commit | 672b76a098b99102a46712b1d982f550f97806f2 (patch) | |
tree | 98ac9dc6bf827df3a5d19086818264b4b6c8b181 /src/peer.h | |
parent | fd1e80d9f4bad1805d801fc4501d86807c93a9ec (diff) |
peer: use iterator macro instead of callback
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src/peer.h')
-rw-r--r-- | src/peer.h | 31 |
1 files changed, 28 insertions, 3 deletions
@@ -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 |