summaryrefslogtreecommitdiff
path: root/absl/synchronization
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2023-09-08 07:52:22 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-09-08 07:53:12 -0700
commit792e55fc0d373b80e4712a6d01ee1834067ef9bd (patch)
tree000955ef3a0f22c551707b75d7ad6be9ce1b1a6d /absl/synchronization
parent6644e5bbbd39bcdd2a33ff7c08d2663a65279e9c (diff)
Rollback:
absl: remove special handling of Condition::kTrue absl: remove known_false condition in Mutex code There are some test breakages. PiperOrigin-RevId: 563751370 Change-Id: Ie14dc799e0a0d286a7e1b47f0a9bbe59dfb23f70
Diffstat (limited to 'absl/synchronization')
-rw-r--r--absl/synchronization/mutex.cc34
-rw-r--r--absl/synchronization/mutex.h8
2 files changed, 28 insertions, 14 deletions
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 8148fbde..ea0d96cf 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -960,7 +960,8 @@ static PerThreadSynch* Enqueue(PerThreadSynch* head, SynchWaitParams* waitp,
} while (s->priority <= advance_to->priority);
// termination guaranteed because s->priority > head->priority
// and head is the end of a skip chain
- } else if (waitp->how == kExclusive && waitp->cond == nullptr) {
+ } else if (waitp->how == kExclusive &&
+ Condition::GuaranteedEqual(waitp->cond, nullptr)) {
// An unlocker could be scanning the queue, but we know it will recheck
// the queue front for writers that have no condition, which is what s
// is, so an insert at front is safe.
@@ -1541,11 +1542,15 @@ bool Mutex::AwaitCommon(const Condition& cond, KernelTimeout t) {
SynchWaitParams waitp(how, &cond, t, nullptr /*no cvmu*/,
Synch_GetPerThreadAnnotated(this),
nullptr /*no cv_word*/);
+ int flags = kMuHasBlocked;
+ if (!Condition::GuaranteedEqual(&cond, nullptr)) {
+ flags |= kMuIsCond;
+ }
this->UnlockSlow(&waitp);
this->Block(waitp.thread);
ABSL_TSAN_MUTEX_POST_UNLOCK(this, TsanFlags(how));
ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));
- this->LockSlowLoop(&waitp, kMuHasBlocked | kMuIsCond);
+ this->LockSlowLoop(&waitp, flags);
bool res = waitp.cond != nullptr || // => cond known true from LockSlowLoop
EvalConditionAnnotated(&cond, this, true, false, how == kShared);
ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);
@@ -1829,7 +1834,7 @@ bool Mutex::LockSlowWithDeadline(MuHow how, const Condition* cond,
SynchWaitParams waitp(how, cond, t, nullptr /*no cvmu*/,
Synch_GetPerThreadAnnotated(this),
nullptr /*no cv_word*/);
- if (cond != nullptr) {
+ if (!Condition::GuaranteedEqual(cond, nullptr)) {
flags |= kMuIsCond;
}
if (unlock) {
@@ -2019,6 +2024,7 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) {
// head of the list searched previously, or zero
PerThreadSynch* old_h = nullptr;
// a condition that's known to be false.
+ const Condition* known_false = nullptr;
PerThreadSynch* wake_list = kPerThreadSynchNull; // list of threads to wake
intptr_t wr_wait = 0; // set to kMuWrWait if we wake a reader and a
// later writer could have acquired the lock
@@ -2122,7 +2128,7 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) {
}
}
if (h->next->waitp->how == kExclusive &&
- h->next->waitp->cond == nullptr) {
+ Condition::GuaranteedEqual(h->next->waitp->cond, nullptr)) {
// easy case: writer with no condition; no need to search
pw = h; // wake w, the successor of h (=pw)
w = h->next;
@@ -2205,8 +2211,10 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) {
w_walk->wake = false;
if (w_walk->waitp->cond ==
nullptr || // no condition => vacuously true OR
- // this thread's condition is true
- EvalConditionIgnored(this, w_walk->waitp->cond)) {
+ (w_walk->waitp->cond != known_false &&
+ // this thread's condition is not known false, AND
+ // is in fact true
+ EvalConditionIgnored(this, w_walk->waitp->cond))) {
if (w == nullptr) {
w_walk->wake = true; // can wake this waiter
w = w_walk;
@@ -2220,6 +2228,8 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) {
} else { // writer with true condition
wr_wait = kMuWrWait;
}
+ } else { // can't wake; condition false
+ known_false = w_walk->waitp->cond; // remember last false condition
}
if (w_walk->wake) { // we're waking reader w_walk
pw_walk = w_walk; // don't skip similar waiters
@@ -2712,11 +2722,17 @@ Condition::Condition(const bool* cond)
StoreCallback(dereference);
}
-bool Condition::Eval() const { return (*this->eval_)(this); }
+bool Condition::Eval() const {
+ // eval_ == null for kTrue
+ return (this->eval_ == nullptr) || (*this->eval_)(this);
+}
bool Condition::GuaranteedEqual(const Condition* a, const Condition* b) {
- if (a == nullptr || b == nullptr) {
- return a == b;
+ // kTrue logic.
+ if (a == nullptr || a->eval_ == nullptr) {
+ return b == nullptr || b->eval_ == nullptr;
+ } else if (b == nullptr || b->eval_ == nullptr) {
+ return false;
}
// Check equality of the representative fields.
return a->eval_ == b->eval_ && a->arg_ == b->arg_ &&
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index 6459053b..ff4747b5 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -833,10 +833,10 @@ class Condition {
#endif
// Function with which to evaluate callbacks and/or arguments.
- bool (*const eval_)(const Condition*);
+ bool (*eval_)(const Condition*) = nullptr;
// Either an argument for a function call or an object for a method call.
- void* const arg_;
+ void* arg_ = nullptr;
// Various functions eval_ can point to:
static bool CallVoidPtrFunction(const Condition*);
@@ -859,10 +859,8 @@ class Condition {
std::memcpy(callback, callback_, sizeof(*callback));
}
- static bool AlwaysTrue(const Condition*) { return true; }
-
// Used only to create kTrue.
- constexpr Condition() : eval_(AlwaysTrue), arg_(nullptr) {}
+ constexpr Condition() = default;
};
// -----------------------------------------------------------------------------