Exemple #1
0
bool LeaseHolder::checkKind(TransKind kind) {
  assertx(m_canTranslate);

  return m_canTranslate =
    m_lease.amOwner() ||
    concurrentlyJitKind(kind) ||
    (m_acquired = m_lease.acquire());
}
Exemple #2
0
LeaseHolder::LeaseHolder(Lease& l, const Func* func, TransKind kind)
  : m_lease(l)
  , m_func{RuntimeOption::EvalJitConcurrently > 0 ? func : nullptr}
{
  auto const need_global = m_func == nullptr || !concurrentlyJitKind(kind);

  if (need_global && !m_lease.amOwner()) {
    auto const blocking = RuntimeOption::EvalJitRequireWriteLease &&
      RuntimeOption::EvalJitConcurrently == 0;
    if (!(m_acquired = m_lease.acquire(blocking))) return;
  }

  SCOPE_EXIT { if (!m_canTranslate) dropLocks(); };

  if (m_func) {
    auto const funcId = m_func->getFuncId();
    s_funcOwners.ensureSize(funcId + 1);
    auto& owner = s_funcOwners[funcId];
    auto oldOwner = owner.load(std::memory_order_acquire);
    auto const self = Treadmill::threadIdx();

    if (oldOwner == self) {
      // We already have the lock on this Func.
    } else if (oldOwner != Treadmill::kInvalidThreadIdx) {
      // Already owned by another thread.
      return;
    } else {
      // Unowned. Try to grab it. Threads with the global write lease don't
      // count towards Eval.JitThreads.
      if (!need_global) {
        auto threads = s_jittingThreads.load(std::memory_order_relaxed);
        if (threads >= RuntimeOption::EvalJitThreads) return;

        threads = s_jittingThreads.fetch_add(1, std::memory_order_relaxed);
        m_acquiredThread = true;
        if (threads >= RuntimeOption::EvalJitThreads) return;
      }

      if (!owner.compare_exchange_strong(oldOwner, self,
                                         std::memory_order_relaxed)) {
        return;
      }
      m_acquiredFunc = true;
    }
  }

  // If we made it this far, we acquired all the locks we need to translate.
  m_canTranslate = true;
}
Exemple #3
0
bool LeaseHolder::NeedGlobal(TransKind kind) {
  return !concurrentlyJitKind(kind);
}