diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-07-07 11:16:00 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2023-07-24 20:24:36 +0000 |
commit | 4a43149d7b1ba10a96826a2bb38f1d5d608b6cb0 (patch) | |
tree | 1061ae9b9085e241a925c2ac9df12052548ebbdb | |
parent | 41f41393067080223422122b8ae1a0dcfe9e5f8f (diff) |
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 <QEventDispatcherUNIX::wakeUp()>:
26bca0: mov 0x8(%rdi),%rdx
26bca4: xor %eax,%eax
26bca6: mov $0x1,%ecx
26bcab: lock cmpxchg %ecx,0x98(%rdx)
26bcb3: jne 26bcc5 <QEventDispatcherUNIX::wakeUp()+0x25>
26bcb5: mov 0x90(%rdx),%edi
26bcbb: mov $0x1,%esi
26bcc0: jmp c01d0 <eventfd_write@plt>
26bcc5: ret
Now:
26b3a0: mov 0x8(%rdi),%rax
26b3a4: lock btsl $0x0,0x98(%rax)
26b3ad: jae 26b3b0 <QEventDispatcherUNIX::wakeUp()+0x10>
26b3af: ret
26b3b0: mov 0x90(%rax),%edi
26b3b6: mov $0x1,%esi
26b3bb: jmp c11d0 <eventfd_write@plt>
Change-Id: I53335f845a1345299031fffd176fa8ac1de3ad13
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/corelib/kernel/qcoreevent.cpp | 5 | ||||
-rw-r--r-- | 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<uint> &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; |