in src/mwcas/mwcas.cc [481:552]
bool Descriptor::VolatileMwCAS(uint32_t calldepth) {
DCHECK(owner_partition_->garbage_list->GetEpoch()->IsProtected());
if(status_ != kStatusUndecided) {
if(calldepth > 0) {
// Short circuit and return if the operation has already concluded.
MwCASMetrics::AddBailedHelp();
return status_ == kStatusSucceeded;
} else {
return Cleanup();
}
}
uint64_t descptr = SetFlags(this, kMwCASFlag);
uint32_t my_status = kStatusSucceeded;
// Try to swap a pointer to this descriptor into all target addresses using
// CondCAS
#ifdef RTM
// If this operation is helping along, go to phase 2 directly
if(calldepth == 0 && !RTMInstallDescriptors()) {
my_status = kStatusFailed;
}
#else
for(uint32_t i = 0; i < count_ && my_status == kStatusSucceeded; i++) {
WordDescriptor* wd = &words_[i];
if((uint64_t)wd->address_ == Descriptor::kAllocNullAddress){
continue;
}
retry_entry:
auto rval = CondCAS(i);
// Ok if a) we succeeded to swap in a pointer to this descriptor or b) some
// other thread has already done so.
if(rval == wd->old_value_ || rval == descptr) {
continue;
}
// Do we need to help another MWCAS operation?
if(IsMwCASDescriptorPtr(rval)) {
// Clashed with another MWCAS; help complete the other MWCAS if it is
// still being worked on.
Descriptor* otherMWCAS = (Descriptor*)CleanPtr(rval);
otherMWCAS->VolatileMwCAS(calldepth + 1);
MwCASMetrics::AddHelpAttempt();
goto retry_entry;
} else {
// rval must be another value, we failed
my_status = kStatusFailed;
}
}
#endif
CompareExchange32(&status_, my_status, kStatusUndecided);
bool succeeded = (status_ == kStatusSucceeded);
for(int i = 0; i < count_; i++) {
WordDescriptor* wd = &words_[i];
if((uint64_t)wd->address_ == Descriptor::kAllocNullAddress){
continue;
}
CompareExchange64(wd->address_,
succeeded ? wd->new_value_ : wd->old_value_, descptr);
}
if(calldepth == 0) {
return Cleanup();
} else {
return succeeded;
}
}