gem5 v24.0.0.0
Loading...
Searching...
No Matches
uncontended_mutex.hh
Go to the documentation of this file.
1/*
2 * Copyright 2020 Google, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef __BASE_UNCONTENDED_MUTEX_HH__
29#define __BASE_UNCONTENDED_MUTEX_HH__
30
31#include <atomic>
32#include <condition_variable>
33#include <mutex>
34
35namespace gem5
36{
37
38/*
39 * The std::mutex implementation is slower than expected because of many mode
40 * checking and legacy support.
41 *
42 * The UncontendedMutex uses an atomic flag to check if we really need to
43 * obtain a mutex lock. For most cases without multi-threads event queues,
44 * e.g. non-KVM simulation, this avoid the usage of mutex and speed up the
45 * simulation.
46 */
48{
49 private:
50 /*
51 * A flag to record the current status:
52 * 0: no one has the lock
53 * 1: exactly one thread has the lock
54 * >1: one or more threads are waiting for the lock
55 */
56 std::atomic<int> flag;
57 std::mutex m;
58 std::condition_variable cv;
59
60 bool
61 testAndSet(int expected, int desired)
62 {
63 return flag.compare_exchange_strong(expected, desired);
64 }
65
66 public:
68
69 void
71 {
72 /*
73 * Here we use 'flag' to check if we are the first thread to get the
74 * lock. If not, we try to obtain the real mutex, and use the condition
75 * variable to wait for the thread who has the lock to release it.
76 *
77 * The flag will be updated to more than 1, so the thread with lock
78 * knows that there is another thread waiting for the lock.
79 */
80 while (!testAndSet(0, 1)) {
81 std::unique_lock<std::mutex> ul(m);
82 /*
83 * It is possible that just before we obtain the mutex lock, the
84 * first thread releases the flag and thus flag becomes zero. In
85 * such case, we shouldn't wait for the condition variable because
86 * there is no the other thread to notify us.
87 */
88 if (flag++ == 0)
89 break;
90 cv.wait(ul);
91 }
92 }
93
94 void
96 {
97 /* In case there are no other threads waiting, we will just clear the
98 * flag and return.
99 */
100 if (testAndSet(1, 0))
101 return;
102
103 /*
104 * Otherwise, clear the flag and notify all the waiting threads. We
105 * need to protect the flag by mutex here so that there won't be
106 * another thread waiting but the flag is already set to 0.
107 */
108 {
109 std::lock_guard<std::mutex> g(m);
110 flag = 0;
111 }
112 /*
113 * It's possible to update the algorithm and use notify_one() here.
114 * However, tests show that notify_one() is much slower than
115 * notify_all() in this case. Here we choose to use notify_all().
116 */
117 cv.notify_all();
118 }
119};
120
121} // namespace gem5
122
123#endif // __BASE_UNCONTENDED_MUTEX_HH__
std::atomic< int > flag
std::condition_variable cv
bool testAndSet(int expected, int desired)
std::vector< SwitchingFiber * > expected({ &a, &b, &a, &a, &a, &b, &c, &a, &c, &c, &c })
Bitfield< 4 > g
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36

Generated on Tue Jun 18 2024 16:24:01 for gem5 by doxygen 1.11.0