bool Descriptor::VolatileMwCASWithFailure()

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;
}