]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/ReadWriteLock.cc
2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /* DEBUG: section 54 Interprocess Communication */
12 #include "ipc/ReadWriteLock.h"
15 void Ipc::AssertFlagIsSet(std::atomic_flag
&flag
)
17 // If the flag was false, then we set it to true and assert. A true flag
18 // may help keep other processes away from this broken entry.
19 // Otherwise, we just set an already set flag, which is probably a no-op.
20 assert(flag
.test_and_set(std::memory_order_relaxed
));
24 Ipc::ReadWriteLock::lockShared()
26 ++readLevel
; // this locks "new" writers out
27 if (!writeLevel
|| appending
) { // nobody is writing, or sharing is OK
36 Ipc::ReadWriteLock::lockExclusive()
38 if (!writeLevel
++) { // we are the first writer + lock "new" readers out
39 if (!readLevel
) { // no old readers and nobody is becoming one
49 Ipc::ReadWriteLock::lockHeaders()
52 if (!updating
.test_and_set(std::memory_order_acquire
))
53 return true; // we got here first
54 // the updating lock was already set by somebody else
61 Ipc::ReadWriteLock::unlockShared()
69 Ipc::ReadWriteLock::unlockExclusive()
78 Ipc::ReadWriteLock::unlockHeaders()
80 AssertFlagIsSet(updating
);
81 updating
.clear(std::memory_order_release
);
86 Ipc::ReadWriteLock::switchExclusiveToShared()
89 ++readLevel
; // must be done before we release exclusive control
95 Ipc::ReadWriteLock::unlockSharedAndSwitchToExclusive()
98 if (!writeLevel
++) { // we are the first writer + lock "new" readers out
105 // somebody is still reading: fall through
107 // somebody is still writing: just stop reading
115 Ipc::ReadWriteLock::startAppending()
122 Ipc::ReadWriteLock::updateStats(ReadWriteLockStats
&stats
) const
126 stats
.readers
+= readers
;
127 } else if (writing
) {
130 stats
.appenders
+= appending
;
137 /* Ipc::ReadWriteLockStats */
139 Ipc::ReadWriteLockStats::ReadWriteLockStats()
141 memset(this, 0, sizeof(*this));
145 Ipc::ReadWriteLockStats::dump(StoreEntry
&e
) const
147 storeAppendPrintf(&e
, "Available locks: %9d\n", count
);
152 storeAppendPrintf(&e
, "Reading: %9d %6.2f%%\n",
153 readable
, (100.0 * readable
/ count
));
154 storeAppendPrintf(&e
, "Writing: %9d %6.2f%%\n",
155 writeable
, (100.0 * writeable
/ count
));
156 storeAppendPrintf(&e
, "Idle: %9d %6.2f%%\n",
157 idle
, (100.0 * idle
/ count
));
159 if (readers
|| writers
) {
160 const int locked
= readers
+ writers
;
161 storeAppendPrintf(&e
, "Readers: %9d %6.2f%%\n",
162 readers
, (100.0 * readers
/ locked
));
163 const double appPerc
= writers
? (100.0 * appenders
/ writers
) : 0.0;
164 storeAppendPrintf(&e
, "Writers: %9d %6.2f%% including Appenders: %9d %6.2f%%\n",
165 writers
, (100.0 * writers
/ locked
),
171 Ipc::operator <<(std::ostream
&os
, const Ipc::ReadWriteLock
&lock
)
173 return os
<< lock
.readers
<< 'R' <<
174 (lock
.writing
? "W" : "") <<
175 (lock
.appending
? "A" : "");
176 // impossible to report lock.updating without setting/clearing that flag