![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /proc/thread-self/root/usr/lib/llvm-10/build/include/llvm/ExecutionEngine/Orc/ |
Upload File : |
//===----------- ThreadSafeModule.h -- Layer interfaces ---------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Thread safe wrappers and utilities for Module and LLVMContext. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULEWRAPPER_H #define LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULEWRAPPER_H #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/Compiler.h" #include <functional> #include <memory> #include <mutex> namespace llvm { namespace orc { /// An LLVMContext together with an associated mutex that can be used to lock /// the context to prevent concurrent access by other threads. class ThreadSafeContext { private: struct State { State(std::unique_ptr<LLVMContext> Ctx) : Ctx(std::move(Ctx)) {} std::unique_ptr<LLVMContext> Ctx; std::recursive_mutex Mutex; }; public: // RAII based lock for ThreadSafeContext. class LLVM_NODISCARD Lock { public: Lock(std::shared_ptr<State> S) : S(std::move(S)), L(this->S->Mutex) {} private: std::shared_ptr<State> S; std::unique_lock<std::recursive_mutex> L; }; /// Construct a null context. ThreadSafeContext() = default; /// Construct a ThreadSafeContext from the given LLVMContext. ThreadSafeContext(std::unique_ptr<LLVMContext> NewCtx) : S(std::make_shared<State>(std::move(NewCtx))) { assert(S->Ctx != nullptr && "Can not construct a ThreadSafeContext from a nullptr"); } /// Returns a pointer to the LLVMContext that was used to construct this /// instance, or null if the instance was default constructed. LLVMContext *getContext() { return S ? S->Ctx.get() : nullptr; } /// Returns a pointer to the LLVMContext that was used to construct this /// instance, or null if the instance was default constructed. const LLVMContext *getContext() const { return S ? S->Ctx.get() : nullptr; } Lock getLock() const { assert(S && "Can not lock an empty ThreadSafeContext"); return Lock(S); } private: std::shared_ptr<State> S; }; /// An LLVM Module together with a shared ThreadSafeContext. class ThreadSafeModule { public: /// Default construct a ThreadSafeModule. This results in a null module and /// null context. ThreadSafeModule() = default; ThreadSafeModule(ThreadSafeModule &&Other) = default; ThreadSafeModule &operator=(ThreadSafeModule &&Other) { // We have to explicitly define this move operator to copy the fields in // reverse order (i.e. module first) to ensure the dependencies are // protected: The old module that is being overwritten must be destroyed // *before* the context that it depends on. // We also need to lock the context to make sure the module tear-down // does not overlap any other work on the context. if (M) { auto L = TSCtx.getLock(); M = nullptr; } M = std::move(Other.M); TSCtx = std::move(Other.TSCtx); return *this; } /// Construct a ThreadSafeModule from a unique_ptr<Module> and a /// unique_ptr<LLVMContext>. This creates a new ThreadSafeContext from the /// given context. ThreadSafeModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> Ctx) : M(std::move(M)), TSCtx(std::move(Ctx)) {} /// Construct a ThreadSafeModule from a unique_ptr<Module> and an /// existing ThreadSafeContext. ThreadSafeModule(std::unique_ptr<Module> M, ThreadSafeContext TSCtx) : M(std::move(M)), TSCtx(std::move(TSCtx)) {} ~ThreadSafeModule() { // We need to lock the context while we destruct the module. if (M) { auto L = TSCtx.getLock(); M = nullptr; } } /// Boolean conversion: This ThreadSafeModule will evaluate to true if it /// wraps a non-null module. explicit operator bool() const { if (M) { assert(TSCtx.getContext() && "Non-null module must have non-null context"); return true; } return false; } /// Locks the associated ThreadSafeContext and calls the given function /// on the contained Module. template <typename Func> auto withModuleDo(Func &&F) -> decltype(F(std::declval<Module &>())) { assert(M && "Can not call on null module"); auto Lock = TSCtx.getLock(); return F(*M); } /// Locks the associated ThreadSafeContext and calls the given function /// on the contained Module. template <typename Func> auto withModuleDo(Func &&F) const -> decltype(F(std::declval<const Module &>())) { auto Lock = TSCtx.getLock(); return F(*M); } /// Get a raw pointer to the contained module without locking the context. Module *getModuleUnlocked() { return M.get(); } /// Get a raw pointer to the contained module without locking the context. const Module *getModuleUnlocked() const { return M.get(); } /// Returns the context for this ThreadSafeModule. ThreadSafeContext getContext() const { return TSCtx; } private: std::unique_ptr<Module> M; ThreadSafeContext TSCtx; }; using GVPredicate = std::function<bool(const GlobalValue &)>; using GVModifier = std::function<void(GlobalValue &)>; /// Clones the given module on to a new context. ThreadSafeModule cloneToNewContext(ThreadSafeModule &TSMW, GVPredicate ShouldCloneDef = GVPredicate(), GVModifier UpdateClonedDefSource = GVModifier()); } // End namespace orc } // End namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULEWRAPPER_H