gem5
v24.0.0.0
Loading...
Searching...
No Matches
base
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
35
namespace
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
*/
47
class
UncontendedMutex
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
:
67
UncontendedMutex
() :
flag
(0) {}
68
69
void
70
lock
()
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
95
unlock
()
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__
gem5::UncontendedMutex
Definition
uncontended_mutex.hh:48
gem5::UncontendedMutex::flag
std::atomic< int > flag
Definition
uncontended_mutex.hh:56
gem5::UncontendedMutex::UncontendedMutex
UncontendedMutex()
Definition
uncontended_mutex.hh:67
gem5::UncontendedMutex::cv
std::condition_variable cv
Definition
uncontended_mutex.hh:58
gem5::UncontendedMutex::testAndSet
bool testAndSet(int expected, int desired)
Definition
uncontended_mutex.hh:61
gem5::UncontendedMutex::lock
void lock()
Definition
uncontended_mutex.hh:70
gem5::UncontendedMutex::unlock
void unlock()
Definition
uncontended_mutex.hh:95
gem5::UncontendedMutex::m
std::mutex m
Definition
uncontended_mutex.hh:57
expected
std::vector< SwitchingFiber * > expected({ &a, &b, &a, &a, &a, &b, &c, &a, &c, &c, &c })
gem5::MipsISA::g
Bitfield< 4 > g
Definition
dt_constants.hh:86
gem5
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