in src/mwcas/mwcas.cc [414:453]
uint64_t Descriptor::CondCAS(uint32_t word_index, uint64_t dirty_flag) {
auto* w = &words_[word_index];
uint64_t cond_descptr = SetFlags((uint64_t)w, kCondCASFlag);
retry:
uint64_t ret = CompareExchange64(w->address_, cond_descptr, w->old_value_);
if(IsCondCASDescriptorPtr(ret)) {
// Already a CondCAS descriptor (ie a WordDescriptor pointer)
WordDescriptor* wd = (WordDescriptor*)CleanPtr(ret);
RAW_CHECK(wd->address_ == w->address_, "wrong address");
uint64_t dptr = SetFlags(wd->GetDescriptor(), kMwCASFlag | dirty_flag);
uint64_t desired =
*wd->status_address_ == kStatusUndecided ? dptr : wd->old_value_;
if(*(volatile uint64_t*)wd->address_ != ret) {
goto retry;
}
auto rval = CompareExchange64(
wd->address_,
*wd->status_address_ == kStatusUndecided ? dptr : wd->old_value_,
ret);
if(rval == ret) {
if(desired == dptr) {
// Another competing operation succeeded, return
return dptr;
}
}
// Retry this operation
goto retry;
} else if(ret == w->old_value_) {
uint64_t mwcas_descptr = SetFlags(this, kMwCASFlag | dirty_flag);
CompareExchange64(w->address_,
status_ == kStatusUndecided ? mwcas_descptr : w->old_value_,
cond_descptr);
}
// ret could be a normal value or a pointer to a MwCAS descriptor
return ret;
}