From 4a43149d7b1ba10a96826a2bb38f1d5d608b6cb0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 7 Jul 2023 11:16:00 -0700 Subject: [PATCH] QThreadPipe & QEvent: use a simpler atomic operation This causes modern compilers (i.e., not MSVC) to emit a single bit-test-and-set instruction instead of a cmpxchg. It's still an atomic operation, so it's not that much faster (if at all), but it has simpler encoding. Previous: 000000000026bca0 : 26bca0: mov 0x8(%rdi),%rdx 26bca4: xor %eax,%eax 26bca6: mov $0x1,%ecx 26bcab: lock cmpxchg %ecx,0x98(%rdx) 26bcb3: jne 26bcc5 26bcb5: mov 0x90(%rdx),%edi 26bcbb: mov $0x1,%esi 26bcc0: jmp c01d0 26bcc5: ret Now: 26b3a0: mov 0x8(%rdi),%rax 26b3a4: lock btsl $0x0,0x98(%rax) 26b3ad: jae 26b3b0 26b3af: ret 26b3b0: mov 0x90(%rax),%edi 26b3b6: mov $0x1,%esi 26b3bb: jmp c11d0 Change-Id: I53335f845a1345299031fffd176fa8ac1de3ad13 Reviewed-by: Fabian Kosmale --- src/corelib/kernel/qcoreevent.cpp | 5 +++-- src/corelib/kernel/qeventdispatcher_unix.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index 46398872f7..838c90fce7 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -433,8 +433,9 @@ struct QBasicAtomicBitField { QBasicAtomicInteger &entry = data[which / BitsPerInt]; const uint old = entry.loadRelaxed(); const uint bit = 1U << (which % BitsPerInt); - return !(old & bit) // wasn't taken - && entry.testAndSetRelaxed(old, old | bit); // still wasn't taken + if (old & bit) + return false; // already taken + return (entry.fetchAndOrRelaxed(bit) & bit) == 0; // don't update 'next' here - it's unlikely that it will need // to be updated, in the general case, and having 'next' diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index dc87a9cd63..12603d77f0 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -123,7 +123,7 @@ pollfd QThreadPipe::prepare() const void QThreadPipe::wakeUp() { - if (wakeUps.testAndSetAcquire(0, 1)) { + if ((wakeUps.fetchAndOrAcquire(1) & 1) == 0) { #if QT_CONFIG(eventfd) eventfd_write(fds[0], 1); return;