in src/mwcas/mwcas.cc [554:622]
bool Descriptor::VolatileMwCASWithFailure(uint32_t calldepth,
bool complete_descriptor_install) {
DCHECK(owner_partition_->garbage_list->GetEpoch()->IsProtected());
if(status_ != kStatusUndecided) {
if(calldepth > 0) {
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 I'm helping, 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
// The compare exchange below will determine whether the mwcas will roll
// forward or back on recovery. If we are told to not complete descriptor
// install, exit the function before updating the operation status. Otherwise
// update the status but do not perform the final phase of the mwcas
// (installing final values in place of the descriptors and memory cleanup).
if (!complete_descriptor_install) {
return false;
}
CompareExchange32(&status_, my_status, kStatusUndecided);
// Always return false in this function, since operation is not supposed to
// fully succeed.
return false;
}