summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qyieldcpu.qdoc
blob: c55b2c8a735456e7cc0ae391bf3c61c3645515c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Copyright (C) 2023 The Qt Company Ltd.
// Copyright (C) 2023 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \fn qYieldCpu()
    \inmodule QtCore
    \ingroup thread
    \relates QAtomicInteger
    //! \relatesalso QAtomicPointer
    \since 6.7

    Pauses the execution of the current thread for an unspecified time, using
    hardware instructions, without de-scheduling this thread. This function is
    meant to be used in high-throughput loops where the code expects another
    thread to modify an atomic variable. This is completely different from
    QThread::yieldCurrentThread(), which is an OS-level operation that may take
    the whole thread off the CPU and allow other threads (possibly belonging to
    other processes) to run.

    So, instead of
    \code
        while (!condition)
            ;
    \endcode

    one should write
    \code
        while (!condition)
            qYieldCpu();
    \endcode

    This is useful both with and without hardware multithreading on the same
    core. In the case of hardware threads, it serves to prevent further
    speculative execution filling up the pipeline, which could starve the
    sibling thread of resources. Across cores and higher levels of separation,
    it allows the cache coherency protocol to allocate the cache line being
    modified and inspected to the logical processor whose result this code is
    expecting.

    It is also recommended to loop around code that does not modify the global
    variable, to avoid contention in exclusively obtaining the memory location.
    Therefore, an atomic modification loop such as a spinlock acquisition
    should be:

    \code
        while (true) {
            while (!readOnlyCondition(atomic))
                qYieldCpu();
            if (modify(atomic))
                break;
        }
    \endcode

    On x86 processors and on RISC-V processors with the \c{Zihintpause}
    extension, this will emit the \c PAUSE instruction, which is ignored on
    processors that don't support it; on ARMv7 or later ARM processors, it will
    emit the \c{YIELD} instruction.
*/