Ai
21 Star 49 Fork 0

Gitee 极速下载/julia-language

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/JuliaLang/julia
克隆/下载
engine.cpp 5.35 KB
一键复制 编辑 原始数据 按行查看 历史
Keno Fischer 提交于 2024-12-20 11:45 +08:00 . Add ABIOverride type for def field (#56555)
// This file is a part of Julia. License is MIT: https://julialang.org/license
#include <mutex>
#include <condition_variable>
#include <llvm/ADT/DenseMap.h>
#include <llvm/ADT/DenseSet.h>
#include <llvm/ADT/SmallVector.h>
#include "julia.h"
#include "julia_internal.h"
#include "julia_assert.h"
using namespace llvm;
struct ReservationInfo {
int16_t tid = 0;
jl_code_instance_t *ci = nullptr;
};
struct InferKey {
jl_method_instance_t *mi = nullptr;
jl_value_t *owner = nullptr;
};
template<> struct llvm::DenseMapInfo<InferKey> {
using FirstInfo = DenseMapInfo<jl_method_instance_t*>;
using SecondInfo = DenseMapInfo<jl_value_t*>;
static inline InferKey getEmptyKey() {
return InferKey{FirstInfo::getEmptyKey(),
SecondInfo::getEmptyKey()};
}
static inline InferKey getTombstoneKey() {
return InferKey{FirstInfo::getTombstoneKey(),
SecondInfo::getTombstoneKey()};
}
static unsigned getHashValue(const InferKey& PairVal) {
return detail::combineHashValue(FirstInfo::getHashValue(PairVal.mi),
SecondInfo::getHashValue(PairVal.owner));
}
static bool isEqual(const InferKey &LHS, const InferKey &RHS) {
return LHS.mi == RHS.mi && LHS.owner == RHS.owner;
}
};
static std::mutex engine_lock; // n.b. this lock is only ever held briefly
static std::condition_variable engine_wait; // but it may be waiting a while in this state
// map from MethodInstance to threadid that owns it currently for inference
static DenseMap<InferKey, ReservationInfo> Reservations;
// vector of which threads are blocked and which lease they need
static SmallVector<InferKey, 0> Awaiting; // (this could be merged into ptls also)
#ifdef __cplusplus
extern "C" {
#endif
jl_code_instance_t *jl_engine_reserve(jl_method_instance_t *m, jl_value_t *owner)
{
jl_task_t *ct = jl_current_task;
ct->ptls->engine_nqueued++; // disables finalizers until inference is finished on this method graph
jl_code_instance_t *ci = jl_new_codeinst_uninit(m, owner); // allocate a placeholder
JL_GC_PUSH1(&ci);
auto tid = jl_atomic_load_relaxed(&ct->tid);
if (([tid, m, owner, ci] () -> bool { // necessary scope block / lambda for unique_lock
jl_unique_gcsafe_lock lock(engine_lock);
InferKey key{m, owner};
if ((signed)Awaiting.size() < tid + 1)
Awaiting.resize(tid + 1);
while (1) {
auto record = Reservations.find(key);
if (record == Reservations.end()) {
Reservations[key] = ReservationInfo{tid, ci};
return false;
}
// before waiting, need to run deadlock/cycle detection
// there is a cycle if the thread holding our lease is blocked
// and waiting for (transitively) any lease that is held by this thread
auto wait_tid = record->second.tid;
while (1) {
if (wait_tid == tid)
return true;
if ((signed)Awaiting.size() <= wait_tid)
break; // no cycle, since it is running (and this should be unreachable)
auto key2 = Awaiting[wait_tid];
if (key2.mi == nullptr)
break; // no cycle, since it is running
auto record2 = Reservations.find(key2);
if (record2 == Reservations.end())
break; // no cycle, since it is about to resume
assert(wait_tid != record2->second.tid);
wait_tid = record2->second.tid;
}
Awaiting[tid] = key;
lock.wait(engine_wait);
Awaiting[tid] = InferKey{};
}
})())
ct->ptls->engine_nqueued--;
JL_GC_POP();
return ci;
}
int jl_engine_hasreserved(jl_method_instance_t *m, jl_value_t *owner)
{
jl_task_t *ct = jl_current_task;
InferKey key = {m, owner};
std::unique_lock lock(engine_lock);
auto record = Reservations.find(key);
return record != Reservations.end() && record->second.tid == jl_atomic_load_relaxed(&ct->tid);
}
STATIC_INLINE int gc_marked(uintptr_t bits) JL_NOTSAFEPOINT
{
return (bits & GC_MARKED) != 0;
}
void jl_engine_sweep(jl_ptls_t *gc_all_tls_states)
{
std::unique_lock lock(engine_lock);
bool any = false;
for (auto I = Reservations.begin(); I != Reservations.end(); ++I) {
jl_code_instance_t *ci = I->second.ci;
if (!gc_marked(jl_astaggedvalue(ci)->bits.gc)) {
auto tid = I->second.tid;
Reservations.erase(I);
jl_ptls_t ptls2 = gc_all_tls_states[tid];
ptls2->engine_nqueued--;
any = true;
}
}
if (any)
engine_wait.notify_all();
}
void jl_engine_fulfill(jl_code_instance_t *ci, jl_code_info_t *src)
{
jl_task_t *ct = jl_current_task;
std::unique_lock lock(engine_lock);
auto record = Reservations.find(InferKey{jl_get_ci_mi(ci), ci->owner});
if (record == Reservations.end() || record->second.ci != ci)
return;
assert(jl_atomic_load_relaxed(&ct->tid) == record->second.tid);
ct->ptls->engine_nqueued--; // re-enables finalizers, but doesn't immediately try to run them
Reservations.erase(record);
engine_wait.notify_all();
}
#ifdef __cplusplus
}
#endif
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/mirrors/julia-language.git
git@gitee.com:mirrors/julia-language.git
mirrors
julia-language
julia-language
master

搜索帮助