Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmutex.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// Copyright (C) 2012 Olivier Goffart <ogoffart@woboq.com>
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5// Qt-Security score:significant reason:default
6
7#include "global/qglobal.h"
8#include "qplatformdefs.h"
9#include "qmutex.h"
10#include <qdebug.h>
11#include "qatomic.h"
12#include "qfutex_p.h"
13#include "qthread.h"
14#include "qmutex_p.h"
15
16#ifndef QT_ALWAYS_USE_FUTEX
17#include "private/qfreelist_p.h"
18#endif
19
21
22using namespace QtFutex;
23static inline QMutexPrivate *dummyFutexValue()
24{
25 return reinterpret_cast<QMutexPrivate *>(quintptr(3));
26}
27
28/*
29 \class QBasicMutex
30 \inmodule QtCore
31 \brief QMutex POD
32 \internal
33
34 \ingroup thread
35
36 - Can be used as global static object.
37 - Always non-recursive
38 - Do not use tryLock with timeout > 0, else you can have a leak (see the ~QMutex destructor)
39*/
40
41/*!
42 \class QMutex
43 \inmodule QtCore
44 \brief The QMutex class provides access serialization between threads.
45
46 \threadsafe
47
48 \ingroup thread
49
50 The purpose of a QMutex is to protect an object, data structure or
51 section of code so that only one thread can access it at a time
52 (this is similar to the Java \c synchronized keyword). It is
53 usually best to use a mutex with a QMutexLocker since this makes
54 it easy to ensure that locking and unlocking are performed
55 consistently.
56
57 For example, say there is a method that prints a message to the
58 user on two lines:
59
60 \snippet code/src_corelib_thread_qmutex.cpp 0
61
62 If these two methods are called in succession, the following happens:
63
64 \snippet code/src_corelib_thread_qmutex.cpp 1
65
66 If these two methods are called simultaneously from two threads then the
67 following sequence could result:
68
69 \snippet code/src_corelib_thread_qmutex.cpp 2
70
71 If we add a mutex, we should get the result we want:
72
73 \snippet code/src_corelib_thread_qmutex.cpp 3
74
75 Then only one thread can modify \c number at any given time and
76 the result is correct. This is a trivial example, of course, but
77 applies to any other case where things need to happen in a
78 particular sequence.
79
80 When you call lock() in a thread, other threads that try to call
81 lock() in the same place will block until the thread that got the
82 lock calls unlock(). A non-blocking alternative to lock() is
83 tryLock().
84
85 QMutex is optimized to be fast in the non-contended case. It
86 will not allocate memory if there is no contention on that mutex.
87 It is constructed and destroyed with almost no overhead,
88 which means it is fine to have many mutexes as part of other classes.
89
90 \sa QRecursiveMutex, QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
91*/
92
93/*!
94 \fn QMutex::QMutex()
95
96 Constructs a new mutex. The mutex is created in an unlocked state.
97*/
98
99/*! \fn QMutex::~QMutex()
100
101 Destroys the mutex.
102
103 \warning Destroying a locked mutex may result in undefined behavior.
104*/
105void QBasicMutex::destroyInternal(void *ptr)
106{
107 auto d = static_cast<QMutexPrivate *>(ptr);
108 if (!d)
109 return;
110 if (!futexAvailable()) {
111 if (d != dummyLocked() && d->possiblyUnlocked.loadRelaxed() && tryLock()) {
112 unlock();
113 return;
114 }
115 }
116 qWarning("QMutex: destroying locked mutex");
117}
118
119/*! \fn void QMutex::lock()
120
121 Locks the mutex. If another thread has locked the mutex then this
122 call will block until that thread has unlocked it.
123
124 If the mutex was already locked by the current thread, this call will
125 never return, causing a \e dead-lock.
126
127 \sa unlock()
128*/
129
130/*! \fn bool QMutex::tryLock(int timeout)
131
132 Attempts to lock the mutex. This function returns \c true if the lock
133 was obtained; otherwise it returns \c false. If another thread has
134 locked the mutex, this function will wait for at most \a timeout
135 milliseconds for the mutex to become available.
136
137 Note: Passing a negative number as the \a timeout is equivalent to
138 calling lock(), i.e. this function will wait forever until mutex
139 can be locked if \a timeout is negative.
140
141 If the lock was obtained, the mutex must be unlocked with unlock()
142 before another thread can successfully lock it.
143
144 \sa lock(), unlock()
145*/
146
147/*! \fn bool QMutex::tryLock(QDeadlineTimer timer)
148 \since 6.6
149
150 Attempts to lock the mutex. This function returns \c true if the lock
151 was obtained; otherwise it returns \c false. If another thread has
152 locked the mutex, this function will wait until \a timer expires
153 for the mutex to become available.
154
155 If the lock was obtained, the mutex must be unlocked with unlock()
156 before another thread can successfully lock it.
157
158 \sa lock(), unlock()
159*/
160
161/*! \fn bool QMutex::tryLock()
162 \overload
163
164 Attempts to lock the mutex. This function returns \c true if the lock
165 was obtained; otherwise it returns \c false.
166
167 If the lock was obtained, the mutex must be unlocked with unlock()
168 before another thread can successfully lock it.
169
170 \sa lock(), unlock()
171*/
172
173/*! \fn bool QMutex::try_lock()
174 \since 5.8
175
176 Attempts to lock the mutex. This function returns \c true if the lock
177 was obtained; otherwise it returns \c false.
178
179 This function is provided for compatibility with the Standard Library
180 concept \c Lockable. It is equivalent to tryLock().
181*/
182
183/*! \fn template <class Rep, class Period> bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
184 \since 5.8
185
186 Attempts to lock the mutex. This function returns \c true if the lock
187 was obtained; otherwise it returns \c false. If another thread has
188 locked the mutex, this function will wait for at least \a duration
189 for the mutex to become available.
190
191 Note: Passing a negative duration as the \a duration is equivalent to
192 calling try_lock(). This behavior differs from tryLock().
193
194 If the lock was obtained, the mutex must be unlocked with unlock()
195 before another thread can successfully lock it.
196
197 \sa lock(), unlock()
198*/
199
200/*! \fn template<class Clock, class Duration> bool QMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
201 \since 5.8
202
203 Attempts to lock the mutex. This function returns \c true if the lock
204 was obtained; otherwise it returns \c false. If another thread has
205 locked the mutex, this function will wait at least until \a timePoint
206 for the mutex to become available.
207
208 Note: Passing a \a timePoint which has already passed is equivalent
209 to calling try_lock(). This behavior differs from tryLock().
210
211 If the lock was obtained, the mutex must be unlocked with unlock()
212 before another thread can successfully lock it.
213
214 \sa lock(), unlock()
215*/
216
217/*! \fn void QMutex::unlock()
218
219 Unlocks the mutex. Attempting to unlock a mutex in a different
220 thread to the one that locked it results in an error. Unlocking a
221 mutex that is not locked results in undefined behavior.
222
223 \sa lock()
224*/
225
226/*!
227 \class QRecursiveMutex
228 \inmodule QtCore
229 \since 5.14
230 \brief The QRecursiveMutex class provides access serialization between threads.
231
232 \threadsafe
233
234 \ingroup thread
235
236 The QRecursiveMutex class is a mutex, like QMutex, with which it is
237 API-compatible. It differs from QMutex by accepting lock() calls from
238 the same thread any number of times. QMutex would deadlock in this situation.
239
240 QRecursiveMutex is much more expensive to construct and operate on, so
241 use a plain QMutex whenever you can. Sometimes, one public function,
242 however, calls another public function, and they both need to lock the
243 same mutex. In this case, you have two options:
244
245 \list
246 \li Factor the code that needs mutex protection into private functions,
247 which assume that the mutex is held when they are called, and lock a
248 plain QMutex in the public functions before you call the private
249 implementation ones.
250 \li Or use a recursive mutex, so it doesn't matter that the first public
251 function has already locked the mutex when the second one wishes to do so.
252 \endlist
253
254 \sa QMutex, QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition
255*/
256
257/*! \fn QRecursiveMutex::QRecursiveMutex()
258
259 Constructs a new recursive mutex. The mutex is created in an unlocked state.
260
261 \sa lock(), unlock()
262*/
263
264/*!
265 Destroys the mutex.
266
267 \warning Destroying a locked mutex may result in undefined behavior.
268*/
269QRecursiveMutex::~QRecursiveMutex()
270{
271}
272
273/*! \fn void QRecursiveMutex::lock()
274
275 Locks the mutex. If another thread has locked the mutex then this
276 call will block until that thread has unlocked it.
277
278 Calling this function multiple times on the same mutex from the
279 same thread is allowed.
280
281 \sa unlock()
282*/
283
284/*!
285 \fn QRecursiveMutex::tryLock(int timeout)
286
287 Attempts to lock the mutex. This function returns \c true if the lock
288 was obtained; otherwise it returns \c false. If another thread has
289 locked the mutex, this function will wait for at most \a timeout
290 milliseconds for the mutex to become available.
291
292 Note: Passing a negative number as the \a timeout is equivalent to
293 calling lock(), i.e. this function will wait forever until mutex
294 can be locked if \a timeout is negative.
295
296 If the lock was obtained, the mutex must be unlocked with unlock()
297 before another thread can successfully lock it.
298
299 Calling this function multiple times on the same mutex from the
300 same thread is allowed.
301
302 \sa lock(), unlock()
303*/
304
305/*!
306 \since 6.6
307
308 Attempts to lock the mutex. This function returns \c true if the lock
309 was obtained; otherwise it returns \c false. If another thread has
310 locked the mutex, this function will wait until \a timeout expires
311 for the mutex to become available.
312
313 If the lock was obtained, the mutex must be unlocked with unlock()
314 before another thread can successfully lock it.
315
316 Calling this function multiple times on the same mutex from the
317 same thread is allowed.
318
319 \sa lock(), unlock()
320*/
321bool QRecursiveMutex::tryLock(QDeadlineTimer timeout) noexcept(LockIsNoexcept)
322{
323 unsigned tsanFlags = QtTsan::MutexWriteReentrant | QtTsan::TryLock;
324 QtTsan::mutexPreLock(this, tsanFlags);
325
326 Qt::HANDLE self = QThread::currentThreadId();
327 if (owner.loadRelaxed() == self) {
328 ++count;
329 Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
330 QtTsan::mutexPostLock(this, tsanFlags, 0);
331 return true;
332 }
333 bool success = true;
334 if (timeout.isForever()) {
335 mutex.lock();
336 } else {
337 success = mutex.tryLock(timeout);
338 }
339
340 if (success)
341 owner.storeRelaxed(self);
342 else
343 tsanFlags |= QtTsan::TryLockFailed;
344
345 QtTsan::mutexPostLock(this, tsanFlags, 0);
346
347 return success;
348}
349
350/*! \fn bool QRecursiveMutex::try_lock()
351 \since 5.8
352
353 Attempts to lock the mutex. This function returns \c true if the lock
354 was obtained; otherwise it returns \c false.
355
356 This function is provided for compatibility with the Standard Library
357 concept \c Lockable. It is equivalent to tryLock().
358*/
359
360/*! \fn template <class Rep, class Period> bool QRecursiveMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
361 \since 5.8
362
363 Attempts to lock the mutex. This function returns \c true if the lock
364 was obtained; otherwise it returns \c false. If another thread has
365 locked the mutex, this function will wait for at least \a duration
366 for the mutex to become available.
367
368 Note: Passing a negative duration as the \a duration is equivalent to
369 calling try_lock(). This behavior differs from tryLock().
370
371 If the lock was obtained, the mutex must be unlocked with unlock()
372 before another thread can successfully lock it.
373
374 Calling this function multiple times on the same mutex from the
375 same thread is allowed.
376
377 \sa lock(), unlock()
378*/
379
380/*! \fn template<class Clock, class Duration> bool QRecursiveMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
381 \since 5.8
382
383 Attempts to lock the mutex. This function returns \c true if the lock
384 was obtained; otherwise it returns \c false. If another thread has
385 locked the mutex, this function will wait at least until \a timePoint
386 for the mutex to become available.
387
388 Note: Passing a \a timePoint which has already passed is equivalent
389 to calling try_lock(). This behavior differs from tryLock().
390
391 If the lock was obtained, the mutex must be unlocked with unlock()
392 before another thread can successfully lock it.
393
394 Calling this function multiple times on the same mutex from the
395 same thread is allowed.
396
397 \sa lock(), unlock()
398*/
399
400/*!
401 Unlocks the mutex. Attempting to unlock a mutex in a different
402 thread to the one that locked it results in an error. Unlocking a
403 mutex that is not locked results in undefined behavior.
404
405 \sa lock()
406*/
407void QRecursiveMutex::unlock() noexcept
408{
409 Q_ASSERT(owner.loadRelaxed() == QThread::currentThreadId());
410 QtTsan::mutexPreUnlock(this, 0u);
411
412 if (count > 0) {
413 count--;
414 } else {
415 owner.storeRelaxed(nullptr);
416 mutex.unlock();
417 }
418
419 QtTsan::mutexPostUnlock(this, 0u);
420}
421
422
423/*!
424 \class QMutexLocker
425 \inmodule QtCore
426 \brief The QMutexLocker class is a convenience class that simplifies
427 locking and unlocking mutexes.
428
429 \threadsafe
430
431 \ingroup thread
432
433 QMutexLocker is a template class where the template parameter \a Mutex
434 specifies the mutex type (such as QMutex or QRecursiveMutex) to be locked
435 and unlocked.
436
437 Locking and unlocking a QMutex or QRecursiveMutex in complex functions and
438 statements or in exception handling code is error-prone and
439 difficult to debug. QMutexLocker can be used in such situations
440 to ensure that the state of the mutex is always well-defined.
441
442 QMutexLocker should be created within a function where a
443 QMutex needs to be locked. The mutex is locked when QMutexLocker
444 is created. You can unlock and relock the mutex with \c unlock()
445 and \c relock(). If locked, the mutex will be unlocked when the
446 QMutexLocker is destroyed.
447
448 For example, this complex function locks a QMutex upon entering
449 the function and unlocks the mutex at all the exit points:
450
451 \snippet code/src_corelib_thread_qmutex.cpp 4
452
453 This example function will get more complicated as it is
454 developed, which increases the likelihood that errors will occur.
455
456 Using QMutexLocker greatly simplifies the code, and makes it more
457 readable:
458
459 \snippet code/src_corelib_thread_qmutex.cpp 5
460
461 Now, the mutex will always be unlocked when the QMutexLocker
462 object is destroyed (when the function returns since \c locker is
463 an auto variable).
464
465 The same principle applies to code that throws and catches
466 exceptions. An exception that is not caught in the function that
467 has locked the mutex has no way of unlocking the mutex before the
468 exception is passed up the stack to the calling function.
469
470 QMutexLocker also provides a \c mutex() member function that returns
471 the mutex on which the QMutexLocker is operating. This is useful
472 for code that needs access to the mutex, such as
473 QWaitCondition::wait(). For example:
474
475 \snippet code/src_corelib_thread_qmutex.cpp 6
476
477 \sa QReadLocker, QWriteLocker, QMutex
478*/
479
480/*!
481 \fn template <typename Mutex> QMutexLocker<Mutex>::QMutexLocker(Mutex *mutex) noexcept
482
483 Constructs a QMutexLocker and locks \a mutex. The mutex will be
484 unlocked when the QMutexLocker is destroyed. If \a mutex is \nullptr,
485 QMutexLocker does nothing.
486
487 \sa QMutex::lock()
488*/
489
490/*!
491 \fn template <typename Mutex> QMutexLocker<Mutex>::QMutexLocker(QMutexLocker &&other) noexcept
492 \since 6.4
493
494 Move-constructs a QMutexLocker from \a other. The mutex and the
495 state of \a other is transferred to the newly constructed instance.
496 After the move, \a other will no longer be managing any mutex.
497
498 \sa QMutex::lock()
499*/
500
501/*!
502 \fn template <typename Mutex> QMutexLocker<Mutex> &QMutexLocker<Mutex>::operator=(QMutexLocker &&other) noexcept
503 \since 6.4
504
505 Move-assigns \a other onto this QMutexLocker. If this QMutexLocker
506 was holding a locked mutex before the assignment, the mutex will be
507 unlocked. The mutex and the state of \a other is then transferred
508 to this QMutexLocker. After the move, \a other will no longer be
509 managing any mutex.
510
511 \sa QMutex::lock()
512*/
513
514/*!
515 \fn template <typename Mutex> void QMutexLocker<Mutex>::swap(QMutexLocker &other) noexcept
516 \since 6.4
517
518 Swaps the mutex and the state of this QMutexLocker with \a other.
519 This operation is very fast and never fails.
520
521 \sa QMutex::lock()
522*/
523
524/*!
525 \fn template <typename Mutex> QMutexLocker<Mutex>::~QMutexLocker() noexcept
526
527 Destroys the QMutexLocker and unlocks the mutex that was locked
528 in the constructor.
529
530 \sa QMutex::unlock()
531*/
532
533/*!
534 \fn template <typename Mutex> bool QMutexLocker<Mutex>::isLocked() const noexcept
535 \since 6.4
536
537 Returns true if this QMutexLocker is currently locking its associated
538 mutex, or false otherwise.
539*/
540
541/*!
542 \fn template <typename Mutex> void QMutexLocker<Mutex>::unlock() noexcept
543
544 Unlocks this mutex locker. You can use \c relock() to lock
545 it again. It does not need to be locked when destroyed.
546
547 \sa relock()
548*/
549
550/*!
551 \fn template <typename Mutex> void QMutexLocker<Mutex>::relock() noexcept
552
553 Relocks an unlocked mutex locker.
554
555 \sa unlock()
556*/
557
558/*!
559 \fn template <typename Mutex> QMutex *QMutexLocker<Mutex>::mutex() const
560
561 Returns the mutex on which the QMutexLocker is operating.
562
563*/
564
565/*
566 For a rough introduction on how this works, refer to
567 http://woboq.com/blog/internals-of-qmutex-in-qt5.html
568 which explains a slightly simplified version of it.
569 The differences are that here we try to work with timeout (requires the
570 possiblyUnlocked flag) and that we only wake one thread when unlocking
571 (requires maintaining the waiters count)
572 We also support recursive mutexes which always have a valid d_ptr.
573
574 The waiters flag represents the number of threads that are waiting or about
575 to wait on the mutex. There are two tricks to keep in mind:
576 We don't want to increment waiters after we checked no threads are waiting
577 (waiters == 0). That's why we atomically set the BigNumber flag on waiters when
578 we check waiters. Similarly, if waiters is decremented right after we checked,
579 the mutex would be unlocked (d->wakeUp() has (or will) be called), but there is
580 no thread waiting. This is only happening if there was a timeout in tryLock at the
581 same time as the mutex is unlocked. So when there was a timeout, we set the
582 possiblyUnlocked flag.
583*/
584
585/*
586 * QBasicMutex implementation with futexes (Linux, Windows 10, FreeBSD)
587 *
588 * QBasicMutex contains one pointer value, which can contain one of four
589 * different values:
590 * 0x0 unlocked
591 * 0x1 locked, no waiters
592 * 0x3 locked, at least one waiter
593 *
594 * LOCKING:
595 *
596 * A starts in the 0x0 state, indicating that it's unlocked. When the first
597 * thread attempts to lock it, it will perform a testAndSetAcquire
598 * from 0x0 to 0x1. If that succeeds, the caller concludes that it
599 * successfully locked the mutex. That happens in fastTryLock().
600 *
601 * If that testAndSetAcquire fails, QBasicMutex::lockInternal is called.
602 *
603 * lockInternal will examine the value of the pointer. Otherwise, it will use
604 * futexes to sleep and wait for another thread to unlock. To do that, it needs
605 * to set a pointer value of 0x3, which indicates that thread is waiting. It
606 * does that by a simple fetchAndStoreAcquire operation.
607 *
608 * If the pointer value was 0x0, it means we succeeded in acquiring the mutex.
609 * For other values, it will then call FUTEX_WAIT and with an expected value of
610 * 0x3.
611 *
612 * If the pointer value changed before futex(2) managed to sleep, it will
613 * return -1 / EWOULDBLOCK, in which case we have to start over. And even if we
614 * are woken up directly by a FUTEX_WAKE, we need to acquire the mutex, so we
615 * start over again.
616 *
617 * UNLOCKING:
618 *
619 * To unlock, we need to set a value of 0x0 to indicate it's unlocked.
620 *
621 * For systems that always use futexes, we immediately unlock the mutex in
622 * inline code. If the mutex was contended before the unlock (had value 0x3),
623 * we call unlockInternalFutex() to FUTEX_WAKE a waiting thread.
624 *
625 * For systems that may or may not use futexes, we can only unlock the mutex in
626 * inline code if it is not contended. If it was, then we call unlockInternal()
627 * to complete the unlocking, in case that futexes were not available.
628 */
629
630/*!
631 \internal helper for lock()
632 */
633Q_NEVER_INLINE
634void QBasicMutex::lockInternal() noexcept(FutexAlwaysAvailable)
635{
636 if (futexAvailable()) {
637 // note we must set to dummyFutexValue because there could be other threads
638 // also waiting
639 while (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) != nullptr) {
640 // successfully set the waiting bit, now sleep
641 futexWait(d_ptr, dummyFutexValue());
642
643 // we got woken up, so try to acquire the mutex
644 }
645 Q_ASSERT(d_ptr.loadRelaxed());
646 } else {
647 lockInternal(QDeadlineTimer::Forever);
648 }
649}
650
651/*!
652 \internal helper for lock(int)
653 */
654#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
655bool QBasicMutex::lockInternal(int timeout) noexcept(FutexAlwaysAvailable)
656{
657 if (timeout == 0)
658 return false;
659
660 return lockInternal(QDeadlineTimer(timeout));
661}
662#endif
663
664/*!
665 \internal helper for tryLock(QDeadlineTimer)
666 */
667Q_NEVER_INLINE
668bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) noexcept(FutexAlwaysAvailable)
669{
670 if (deadlineTimer.hasExpired())
671 return false;
672
673 if (futexAvailable()) {
674 if (Q_UNLIKELY(deadlineTimer.isForever())) {
675 lockInternal();
676 return true;
677 }
678
679 // The mutex is already locked, set a bit indicating we're waiting.
680 // Note we must set to dummyFutexValue because there could be other threads
681 // also waiting.
682 if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
683 return true;
684
685 for (;;) {
686 if (!futexWait(d_ptr, dummyFutexValue(), deadlineTimer))
687 return false;
688
689 // We got woken up, so must try to acquire the mutex. We must set
690 // to dummyFutexValue() again because there could be other threads
691 // waiting.
692 if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
693 return true;
694
695 if (deadlineTimer.hasExpired())
696 return false;
697 }
698 }
699
700#if !defined(QT_ALWAYS_USE_FUTEX)
701 while (!fastTryLock()) {
702 QMutexPrivate *copy = d_ptr.loadAcquire();
703 if (!copy) // if d is 0, the mutex is unlocked
704 continue;
705
706 if (copy == dummyLocked()) {
707 if (deadlineTimer.hasExpired())
708 return false;
709 // The mutex is locked but does not have a QMutexPrivate yet.
710 // we need to allocate a QMutexPrivate
711 QMutexPrivate *newD = QMutexPrivate::allocate();
712 if (!d_ptr.testAndSetOrdered(dummyLocked(), newD)) {
713 //Either the mutex is already unlocked, or another thread already set it.
714 newD->deref();
715 continue;
716 }
717 copy = newD;
718 //the d->refCount is already 1 the deref will occurs when we unlock
719 }
720
721 QMutexPrivate *d = static_cast<QMutexPrivate *>(copy);
722 if (deadlineTimer.hasExpired() && !d->possiblyUnlocked.loadRelaxed())
723 return false;
724
725 // At this point we have a pointer to a QMutexPrivate. But the other thread
726 // may unlock the mutex at any moment and release the QMutexPrivate to the pool.
727 // We will try to reference it to avoid unlock to release it to the pool to make
728 // sure it won't be released. But if the refcount is already 0 it has been released.
729 if (!d->ref())
730 continue; //that QMutexPrivate was already released
731
732 // We now hold a reference to the QMutexPrivate. It won't be released and re-used.
733 // But it is still possible that it was already re-used by another QMutex right before
734 // we did the ref(). So check if we still hold a pointer to the right mutex.
735 if (d != d_ptr.loadAcquire()) {
736 //Either the mutex is already unlocked, or relocked with another mutex
737 d->deref();
738 continue;
739 }
740
741 // In this part, we will try to increment the waiters count.
742 // We just need to take care of the case in which the old_waiters
743 // is set to the BigNumber magic value set in unlockInternal()
744 int old_waiters;
745 do {
746 old_waiters = d->waiters.loadAcquire();
747 if (old_waiters == -QMutexPrivate::BigNumber) {
748 // we are unlocking, and the thread that unlocks is about to change d to 0
749 // we try to acquire the mutex by changing to dummyLocked()
750 if (d_ptr.testAndSetAcquire(d, dummyLocked())) {
751 // Mutex acquired
752 d->deref();
753 return true;
754 } else {
755 Q_ASSERT(d != d_ptr.loadRelaxed()); //else testAndSetAcquire should have succeeded
756 // Mutex is likely to bo 0, we should continue the outer-loop,
757 // set old_waiters to the magic value of BigNumber
758 old_waiters = QMutexPrivate::BigNumber;
759 break;
760 }
761 }
762 } while (!d->waiters.testAndSetRelaxed(old_waiters, old_waiters + 1));
763
764 if (d != d_ptr.loadAcquire()) {
765 // The mutex was unlocked before we incremented waiters.
766 if (old_waiters != QMutexPrivate::BigNumber) {
767 //we did not break the previous loop
768 Q_ASSERT(d->waiters.loadRelaxed() >= 1);
769 d->waiters.deref();
770 }
771 d->deref();
772 continue;
773 }
774
775 if (d->wait(deadlineTimer)) {
776 // reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
777 if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
778 d->deref();
779 d->derefWaiters(1);
780 //we got the lock. (do not deref)
781 Q_ASSERT(d == d_ptr.loadRelaxed());
782 return true;
783 } else {
784 // timed out
785 d->derefWaiters(1);
786 //There may be a race in which the mutex is unlocked right after we timed out,
787 // and before we deref the waiters, so maybe the mutex is actually unlocked.
788 // Set the possiblyUnlocked flag to indicate this possibility.
789 if (!d->possiblyUnlocked.testAndSetRelaxed(false, true)) {
790 // We keep a reference when possiblyUnlocked is true.
791 // but if possiblyUnlocked was already true, we don't need to keep the reference.
792 d->deref();
793 }
794 return false;
795 }
796 }
797 Q_ASSERT(d_ptr.loadRelaxed() != 0);
798 return true;
799#else
800 Q_UNREACHABLE();
801#endif
802}
803
804#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
805// not in removed_api.cpp because we need futexAvailable()
806/*!
807 \internal
808 */
809void QBasicMutex::unlockInternal() noexcept
810{
811 QMutexPrivate *copy = d_ptr.loadAcquire();
812 if (futexAvailable()) {
813 d_ptr.storeRelease(nullptr);
814 unlockInternalFutex(copy);
815 } else {
816 unlockInternal(copy);
817 }
818}
819#endif
820
821/*!
822 \internal
823 \since 6.10
824 Complete unlocking when user code knows we use a futex and has thus already
825 unlocked the mutex. The difference from unlockInternal() in futex mode is
826 we only have one atomic operation (the fetchAndStore in inline code) instead
827 of two (a testAndSet followed by the storeRelease).
828*/
829Q_NEVER_INLINE
830void QBasicMutex::unlockInternalFutex(void *copy) noexcept
831{
832 Q_ASSERT(copy == dummyFutexValue()); // was contended
833 if (!futexAvailable())
834 Q_UNREACHABLE();
835 futexWakeOne(d_ptr);
836 Q_UNUSED(copy);
837}
838
839
840/*!
841 \internal
842 Common unlock code for when user code isn't sure that futexes are available.
843*/
844Q_NEVER_INLINE
845void QBasicMutex::unlockInternal(void *copy) noexcept
846{
847 Q_ASSERT(copy); //we must be locked
848 Q_ASSERT(copy != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
849
850# if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) || defined(Q_OS_WIN)
851 // these platforms always have futex and have never called this function
852 // from inline code
853 Q_UNREACHABLE();
854# endif
855
856 if (futexAvailable()) {
857 d_ptr.storeRelease(nullptr);
858 return unlockInternalFutex(copy);
859 }
860
861#if !defined(QT_ALWAYS_USE_FUTEX)
862 static_assert(!FutexAlwaysAvailable, "mismatch with QT_ALWAYS_USE_FUTEX");
863 QMutexPrivate *d = reinterpret_cast<QMutexPrivate *>(copy);
864
865 // If no one is waiting for the lock anymore, we should reset d to 0x0.
866 // Using fetchAndAdd, we atomically check that waiters was equal to 0, and add a flag
867 // to the waiters variable (BigNumber). That way, we avoid the race in which waiters is
868 // incremented right after we checked, because we won't increment waiters if is
869 // equal to -BigNumber
870 if (d->waiters.fetchAndAddRelease(-QMutexPrivate::BigNumber) == 0) {
871 //there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0)
872 if (d_ptr.testAndSetRelease(d, 0)) {
873 // reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
874 if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
875 d->deref();
876 }
877 d->derefWaiters(0);
878 } else {
879 d->derefWaiters(0);
880 //there are thread waiting, transfer the lock.
881 d->wakeUp();
882 }
883 d->deref();
884#else
885 static_assert(FutexAlwaysAvailable, "mismatch with QT_ALWAYS_USE_FUTEX");
886 Q_UNUSED(copy);
887#endif
888}
889
890#if !defined(QT_ALWAYS_USE_FUTEX)
891//The freelist management
892namespace {
893struct FreeListConstants : QFreeListDefaultConstants {
894 enum { BlockCount = 4, MaxIndex=0xffff };
895 static const int Sizes[BlockCount];
896};
897Q_CONSTINIT const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
898 16,
899 128,
900 1024,
901 FreeListConstants::MaxIndex - (16 + 128 + 1024)
902};
903
904typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList;
905// We cannot use Q_GLOBAL_STATIC because it uses QMutex
906Q_CONSTINIT static FreeList freeList_;
907FreeList *freelist()
908{
909 return &freeList_;
910}
911}
912
913QMutexPrivate *QMutexPrivate::allocate()
914{
915 int i = freelist()->next();
916 QMutexPrivate *d = &(*freelist())[i];
917 d->id = i;
918 Q_ASSERT(d->refCount.loadRelaxed() == 0);
919 Q_ASSERT(!d->possiblyUnlocked.loadRelaxed());
920 Q_ASSERT(d->waiters.loadRelaxed() == 0);
921 d->refCount.storeRelaxed(1);
922 return d;
923}
924
925void QMutexPrivate::release()
926{
927 Q_ASSERT(refCount.loadRelaxed() == 0);
928 Q_ASSERT(!possiblyUnlocked.loadRelaxed());
929 Q_ASSERT(waiters.loadRelaxed() == 0);
930 freelist()->release(id);
931}
932
933// atomically subtract "value" to the waiters, and remove the QMutexPrivate::BigNumber flag
934void QMutexPrivate::derefWaiters(int value) noexcept
935{
936 int old_waiters;
937 int new_waiters;
938 do {
939 old_waiters = waiters.loadRelaxed();
940 new_waiters = old_waiters;
941 if (new_waiters < 0) {
942 new_waiters += QMutexPrivate::BigNumber;
943 }
944 new_waiters -= value;
945 } while (!waiters.testAndSetRelaxed(old_waiters, new_waiters));
946}
947#endif
948
949QT_END_NAMESPACE
950
951#if defined(QT_ALWAYS_USE_FUTEX)
952// nothing
953#elif defined(Q_OS_DARWIN)
954# include "qmutex_mac.cpp"
955#else
956# include "qmutex_unix.cpp"
957#endif
\inmodule QtCore
Definition qmutex.h:342
Combined button and popup list for selecting options.
static QMutexPrivate * dummyFutexValue()
Definition qmutex.cpp:23
QMutex QBasicMutex
Definition qmutex.h:360