From: Willy Tarreau Date: Sat, 9 Jul 2022 12:09:35 +0000 (+0200) Subject: MINOR: fd: add fd_get_running() to atomically return the running mask X-Git-Tag: v2.7-dev2~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ceffd17f52b6b1aa481365fc6f9b88e8efc436e8;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/haproxy/fd.h b/include/haproxy/fd.h index 9c085b79a4..601419e660 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. */