bool Descriptor::VolatileMwCAS()

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