bool LeaseHolder::checkKind(TransKind kind) { assertx(m_canTranslate); return m_canTranslate = m_lease.amOwner() || concurrentlyJitKind(kind) || (m_acquired = m_lease.acquire()); }
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; }
bool LeaseHolder::NeedGlobal(TransKind kind) { return !concurrentlyJitKind(kind); }