[llvm] r208945 - Add C API for thread yielding callback.
Chandler Carruth
chandlerc at google.com
Thu May 15 19:49:36 PDT 2014
Just want to say, thanks for all the work figuring out the right shape for
this. =] This looks really, really nice.
On Thu, May 15, 2014 at 8:33 PM, Juergen Ributzka <juergen at apple.com> wrote:
> Author: ributzka
> Date: Thu May 15 21:33:15 2014
> New Revision: 208945
>
> URL: http://llvm.org/viewvc/llvm-project?rev=208945&view=rev
> Log:
> Add C API for thread yielding callback.
>
> Sometimes a LLVM compilation may take more time then a client would like to
> wait for. The problem is that it is not possible to safely suspend the LLVM
> thread from the outside. When the timing is bad it might be possible that
> the
> LLVM thread holds a global mutex and this would block any progress in any
> other
> thread.
>
> This commit adds a new yield callback function that can be registered with
> a
> context. LLVM will try to yield by calling this callback function, but
> there is
> no guaranteed frequency. LLVM will only do so if it can guarantee that
> suspending the thread won't block any forward progress in other LLVM
> contexts
> in the same process.
>
> Once the client receives the call back it can suspend the thread safely and
> resume it at another time.
>
> Related to <rdar://problem/16728690>
>
> Modified:
> llvm/trunk/include/llvm-c/Core.h
> llvm/trunk/include/llvm/IR/LLVMContext.h
> llvm/trunk/lib/Analysis/IPA/CallGraphSCCPass.cpp
> llvm/trunk/lib/Analysis/LoopPass.cpp
> llvm/trunk/lib/IR/Core.cpp
> llvm/trunk/lib/IR/LLVMContext.cpp
> llvm/trunk/lib/IR/LLVMContextImpl.cpp
> llvm/trunk/lib/IR/LLVMContextImpl.h
> llvm/trunk/lib/IR/LegacyPassManager.cpp
> llvm/trunk/lib/IR/PassManager.cpp
> llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
>
> Modified: llvm/trunk/include/llvm-c/Core.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Core.h?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm-c/Core.h (original)
> +++ llvm/trunk/include/llvm-c/Core.h Thu May 15 21:33:15 2014
> @@ -467,6 +467,7 @@ void LLVMEnablePrettyStackTrace(void);
> */
>
> typedef void (*LLVMDiagnosticHandler)(LLVMDiagnosticInfoRef, void *);
> +typedef void (*LLVMYieldCallback)(LLVMContextRef, void *);
>
> /**
> * Create a new context.
> @@ -489,6 +490,14 @@ void LLVMContextSetDiagnosticHandler(LLV
> void *DiagnosticContext);
>
> /**
> + * Set the yield callback function for this context.
> + *
> + * @see LLVMContext::setYieldCallback()
> + */
> +void LLVMContextSetYieldCallback(LLVMContextRef C, LLVMYieldCallback
> Callback,
> + void *OpaqueHandle);
> +
> +/**
> * Destroy a context instance.
> *
> * This should be called for every call to LLVMContextCreate() or memory
>
> Modified: llvm/trunk/include/llvm/IR/LLVMContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/LLVMContext.h?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/LLVMContext.h (original)
> +++ llvm/trunk/include/llvm/IR/LLVMContext.h Thu May 15 21:33:15 2014
> @@ -72,6 +72,10 @@ public:
> /// \see LLVMContext::diagnose.
> typedef void (*DiagnosticHandlerTy)(const DiagnosticInfo &DI, void
> *Context);
>
> + /// Defines the type of a yield callback.
> + /// \see LLVMContext::setYieldCallback.
> + typedef void (*YieldCallbackTy)(LLVMContext *Context, void
> *OpaqueHandle);
> +
> /// setInlineAsmDiagnosticHandler - This method sets a handler that is
> invoked
> /// when problems with inline asm are detected by the backend. The
> first
> /// argument is a function pointer and the second is a context pointer
> that
> @@ -118,6 +122,32 @@ public:
> /// for RS_Error, "warning: " for RS_Warning, and "note: " for RS_Note.
> void diagnose(const DiagnosticInfo &DI);
>
> + /// \brief Registers a yield callback with the given context.
> + ///
> + /// The yield callback function may be called by LLVM to transfer
> control back
> + /// to the client that invoked the LLVM compilation. This can be used
> to yield
> + /// control of the thread, or perform periodic work needed by the
> client.
> + /// There is no guaranteed frequency at which callbacks must occur; in
> fact,
> + /// the client is not guaranteed to ever receive this callback. It is
> at the
> + /// sole discretion of LLVM to do so and only if it can guarantee that
> + /// suspending the thread won't block any forward progress in other LLVM
> + /// contexts in the same process.
> + ///
> + /// At a suspend point, the state of the current LLVM context is
> intentionally
> + /// undefined. No assumptions about it can or should be made. Only LLVM
> + /// context API calls that explicitly state that they can be used
> during a
> + /// yield callback are allowed to be used. Any other API calls into the
> + /// context are not supported until the yield callback function returns
> + /// control to LLVM. Other LLVM contexts are unaffected by this
> restriction.
> + void setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle);
> +
> + /// \brief Calls the yield callback (if applicable).
> + ///
> + /// This transfers control of the current thread back to the client,
> which may
> + /// suspend the current thread. Only call this method when LLVM doesn't
> hold
> + /// any global mutex or cannot block the execution in another LLVM
> context.
> + void yield();
> +
> /// emitError - Emit an error message to the currently installed error
> handler
> /// with optional location information. This function returns, so code
> should
> /// be prepared to drop the erroneous construct on the floor and "not
> crash".
>
> Modified: llvm/trunk/lib/Analysis/IPA/CallGraphSCCPass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/IPA/CallGraphSCCPass.cpp?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/IPA/CallGraphSCCPass.cpp (original)
> +++ llvm/trunk/lib/Analysis/IPA/CallGraphSCCPass.cpp Thu May 15 21:33:15
> 2014
> @@ -22,6 +22,7 @@
> #include "llvm/IR/Function.h"
> #include "llvm/IR/IntrinsicInst.h"
> #include "llvm/IR/LegacyPassManagers.h"
> +#include "llvm/IR/LLVMContext.h"
> #include "llvm/Support/CommandLine.h"
> #include "llvm/Support/Debug.h"
> #include "llvm/Support/Timer.h"
> @@ -145,8 +146,11 @@ bool CGPassManager::RunPassOnSCC(Pass *P
> I != E; ++I) {
> if (Function *F = (*I)->getFunction()) {
> dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());
> - TimeRegion PassTimer(getPassTimer(FPP));
> - Changed |= FPP->runOnFunction(*F);
> + {
> + TimeRegion PassTimer(getPassTimer(FPP));
> + Changed |= FPP->runOnFunction(*F);
> + }
> + F->getContext().yield();
> }
> }
>
>
> Modified: llvm/trunk/lib/Analysis/LoopPass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopPass.cpp?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/LoopPass.cpp (original)
> +++ llvm/trunk/lib/Analysis/LoopPass.cpp Thu May 15 21:33:15 2014
> @@ -15,6 +15,7 @@
>
> #include "llvm/Analysis/LoopPass.h"
> #include "llvm/IR/IRPrintingPasses.h"
> +#include "llvm/IR/LLVMContext.h"
> #include "llvm/Support/Debug.h"
> #include "llvm/Support/Timer.h"
> using namespace llvm;
> @@ -253,6 +254,8 @@ bool LPPassManager::runOnFunction(Functi
>
> // Then call the regular verifyAnalysis functions.
> verifyPreservedAnalysis(P);
> +
> + F.getContext().yield();
> }
>
> removeNotPreservedAnalysis(P);
>
> Modified: llvm/trunk/lib/IR/Core.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Core.cpp?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/Core.cpp (original)
> +++ llvm/trunk/lib/IR/Core.cpp Thu May 15 21:33:15 2014
> @@ -89,6 +89,13 @@ void LLVMContextSetDiagnosticHandler(LLV
> DiagnosticContext);
> }
>
> +void LLVMContextSetYieldCallback(LLVMContextRef C, LLVMYieldCallback
> Callback,
> + void *OpaqueHandle) {
> + auto YieldCallback =
> + LLVM_EXTENSION
> reinterpret_cast<LLVMContext::YieldCallbackTy>(Callback);
> + unwrap(C)->setYieldCallback(YieldCallback, OpaqueHandle);
> +}
> +
> void LLVMContextDispose(LLVMContextRef C) {
> delete unwrap(C);
> }
>
> Modified: llvm/trunk/lib/IR/LLVMContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContext.cpp?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/LLVMContext.cpp (original)
> +++ llvm/trunk/lib/IR/LLVMContext.cpp Thu May 15 21:33:15 2014
> @@ -115,6 +115,17 @@ void *LLVMContext::getDiagnosticContext(
> return pImpl->DiagnosticContext;
> }
>
> +void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void
> *OpaqueHandle)
> +{
> + pImpl->YieldCallback = Callback;
> + pImpl->YieldOpaqueHandle = OpaqueHandle;
> +}
> +
> +void LLVMContext::yield() {
> + if (pImpl->YieldCallback)
> + pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle);
> +}
> +
> void LLVMContext::emitError(const Twine &ErrorStr) {
> diagnose(DiagnosticInfoInlineAsm(ErrorStr));
> }
>
> Modified: llvm/trunk/lib/IR/LLVMContextImpl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.cpp?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/LLVMContextImpl.cpp (original)
> +++ llvm/trunk/lib/IR/LLVMContextImpl.cpp Thu May 15 21:33:15 2014
> @@ -41,6 +41,8 @@ LLVMContextImpl::LLVMContextImpl(LLVMCon
> InlineAsmDiagContext = nullptr;
> DiagnosticHandler = nullptr;
> DiagnosticContext = nullptr;
> + YieldCallback = nullptr;
> + YieldOpaqueHandle = nullptr;
> NamedStructTypesUniqueID = 0;
> }
>
>
> Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
> +++ llvm/trunk/lib/IR/LLVMContextImpl.h Thu May 15 21:33:15 2014
> @@ -242,6 +242,9 @@ public:
> LLVMContext::DiagnosticHandlerTy DiagnosticHandler;
> void *DiagnosticContext;
>
> + LLVMContext::YieldCallbackTy YieldCallback;
> + void *YieldOpaqueHandle;
> +
> typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt *,
> DenseMapAPIntKeyInfo> IntMapTy;
> IntMapTy IntConstants;
>
> Modified: llvm/trunk/lib/IR/LegacyPassManager.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LegacyPassManager.cpp?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/LegacyPassManager.cpp (original)
> +++ llvm/trunk/lib/IR/LegacyPassManager.cpp Thu May 15 21:33:15 2014
> @@ -12,6 +12,7 @@
>
> //===----------------------------------------------------------------------===//
>
>
> +#include "llvm/IR/LLVMContext.h"
> #include "llvm/IR/IRPrintingPasses.h"
> #include "llvm/IR/LegacyPassManager.h"
> #include "llvm/IR/LegacyPassManagers.h"
> @@ -1489,8 +1490,10 @@ bool FunctionPassManagerImpl::run(Functi
> TimingInfo::createTheTimeInfo();
>
> initializeAllAnalysisInfo();
> - for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
> + for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
> Changed |= getContainedManager(Index)->runOnFunction(F);
> + F.getContext().yield();
> + }
>
> for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
> getContainedManager(Index)->cleanup();
> @@ -1723,8 +1726,10 @@ bool PassManagerImpl::run(Module &M) {
> }
>
> initializeAllAnalysisInfo();
> - for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
> + for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
> Changed |= getContainedManager(Index)->runOnModule(M);
> + M.getContext().yield();
> + }
>
> for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(),
> E = IPV.end(); I != E; ++I) {
>
> Modified: llvm/trunk/lib/IR/PassManager.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/PassManager.cpp?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/PassManager.cpp (original)
> +++ llvm/trunk/lib/IR/PassManager.cpp Thu May 15 21:33:15 2014
> @@ -8,6 +8,7 @@
>
> //===----------------------------------------------------------------------===//
>
> #include "llvm/ADT/STLExtras.h"
> +#include "llvm/IR/LLVMContext.h"
> #include "llvm/IR/PassManager.h"
> #include "llvm/Support/CommandLine.h"
> #include "llvm/Support/Debug.h"
> @@ -32,6 +33,8 @@ PreservedAnalyses ModulePassManager::run
> if (AM)
> AM->invalidate(M, PassPA);
> PA.intersect(std::move(PassPA));
> +
> + M->getContext().yield();
> }
>
> if (DebugPM)
> @@ -92,6 +95,8 @@ PreservedAnalyses FunctionPassManager::r
> if (AM)
> AM->invalidate(F, PassPA);
> PA.intersect(std::move(PassPA));
> +
> + F->getContext().yield();
> }
>
> if (DebugPM)
>
> Modified: llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp?rev=208945&r1=208944&r2=208945&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp (original)
> +++ llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp Thu May
> 15 21:33:15 2014
> @@ -28,6 +28,7 @@ using namespace llvm;
>
> static bool didCallAllocateCodeSection;
> static bool didAllocateCompactUnwindSection;
> +static bool didCallYield;
>
> static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
> unsigned alignment,
> @@ -64,6 +65,10 @@ static void roundTripDestroy(void *objec
> delete static_cast<SectionMemoryManager*>(object);
> }
>
> +static void yield(LLVMContextRef, void *) {
> + didCallYield = true;
> +}
> +
> namespace {
>
> // memory manager to test reserve allocation space callback
> @@ -142,6 +147,7 @@ protected:
> virtual void SetUp() {
> didCallAllocateCodeSection = false;
> didAllocateCompactUnwindSection = false;
> + didCallYield = false;
> Module = 0;
> Function = 0;
> Engine = 0;
> @@ -429,3 +435,24 @@ TEST_F(MCJITCAPITest, reserve_allocation
> EXPECT_TRUE(MM->UsedCodeSize > 0);
> EXPECT_TRUE(MM->UsedDataSizeRW > 0);
> }
> +
> +TEST_F(MCJITCAPITest, yield) {
> + SKIP_UNSUPPORTED_PLATFORM;
> +
> + buildSimpleFunction();
> + buildMCJITOptions();
> + buildMCJITEngine();
> + LLVMContextRef C = LLVMGetGlobalContext();
> + LLVMContextSetYieldCallback(C, yield, NULL);
> + buildAndRunPasses();
> +
> + union {
> + void *raw;
> + int (*usable)();
> + } functionPointer;
> + functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
> +
> + EXPECT_EQ(42, functionPointer.usable());
> + EXPECT_TRUE(didCallYield);
> +}
> +
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140515/136dd45c/attachment.html>
More information about the llvm-commits
mailing list