From ceffd17f52b6b1aa481365fc6f9b88e8efc436e8 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sat, 9 Jul 2022 14:09:35 +0200 Subject: [PATCH] MINOR: fd: add fd_get_running() to atomically return the running mask The running mask is only valid if the tgid is the expected one. This function takes a reference on the tgid before reading the running mask, so that both are checked at once. It returns either the mask or zero if the tgid differs, thus providing a simple way for a caller to check if it still holds the FD. --- include/haproxy/fd.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/haproxy/fd.h b/include/haproxy/fd.h index 9c085b79a..601419e66 100644 --- a/include/haproxy/fd.h +++ b/include/haproxy/fd.h @@ -387,6 +387,27 @@ static inline void fd_claim_tgid(int fd, uint desired_tgid) } } +/* atomically read the running mask if the tgid matches, or returns zero if it + * does not match. This is meant for use in code paths where the bit is expected + * to be present and will be sufficient to protect against a short-term group + * migration (e.g. takss and return from iocb). + */ +static inline ulong fd_get_running(int fd, uint desired_tgid) +{ + ulong ret = 0; + uint old; + + /* TODO: may also be checked using an atomic double-load from a DWCAS + * on compatible architectures, which wouldn't require to modify nor + * restore the original value. + */ + old = _HA_ATOMIC_ADD_FETCH(&fdtab[fd].refc_tgid, 0x10000); + if (likely((old & 0xffff) == desired_tgid)) + ret = _HA_ATOMIC_LOAD(&fdtab[fd].running_mask); + _HA_ATOMIC_SUB(&fdtab[fd].refc_tgid, 0x10000); + return ret; +} + /* remove tid_bit from the fd's running mask and returns the bits that remain * after the atomic operation. */