X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FCrashRecoveryContext.h;h=f1e636d8ecc9bbbe200d8a79a8a5b364a42f974d;hb=a80ff266885a464b9270a86462dc01d41258d7d8;hp=28b31f3a782a62383351dc49795843e88b74c150;hpb=b52fde4185cd724f51aae4018b0f8278732379c7;p=oota-llvm.git diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 28b31f3a782..f1e636d8ecc 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -12,11 +12,13 @@ #include +#include "llvm/ADT/STLExtras.h" + namespace llvm { class StringRef; class CrashRecoveryContextCleanup; - + /// \brief Crash recovery helper object. /// /// This class implements support for running operations in a safe context so @@ -47,9 +49,9 @@ class CrashRecoveryContext { CrashRecoveryContextCleanup *head; public: - CrashRecoveryContext() : Impl(0), head(0) {} + CrashRecoveryContext() : Impl(nullptr), head(nullptr) {} ~CrashRecoveryContext(); - + void registerCleanup(CrashRecoveryContextCleanup *cleanup); void unregisterCleanup(CrashRecoveryContextCleanup *cleanup); @@ -75,15 +77,24 @@ public: /// make as little assumptions as possible about the program state when /// RunSafely has returned false. Clients can use getBacktrace() to retrieve /// the backtrace of the crash on failures. - bool RunSafely(void (*Fn)(void*), void *UserData); + bool RunSafely(function_ref Fn); + bool RunSafely(void (*Fn)(void*), void *UserData) { + return RunSafely([&]() { Fn(UserData); }); + } /// \brief Execute the provide callback function (with the given arguments) in /// a protected context which is run in another thread (optionally with a /// requested stack size). /// /// See RunSafely() and llvm_execute_on_thread(). + /// + /// On Darwin, if PRIO_DARWIN_BG is set on the calling thread, it will be + /// propagated to the new thread as well. + bool RunSafelyOnThread(function_ref, unsigned RequestedStackSize = 0); bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, - unsigned RequestedStackSize = 0); + unsigned RequestedStackSize = 0) { + return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize); + } /// \brief Explicitly trigger a crash recovery in the current process, and /// return failure from RunSafely(). This function does not return. @@ -98,89 +109,97 @@ public: }; class CrashRecoveryContextCleanup { +protected: + CrashRecoveryContext *context; + CrashRecoveryContextCleanup(CrashRecoveryContext *context) + : context(context), cleanupFired(false) {} public: bool cleanupFired; - enum ProvidedCleanups { DeleteCleanup, DestructorCleanup }; - CrashRecoveryContextCleanup() : cleanupFired(false) {} virtual ~CrashRecoveryContextCleanup(); virtual void recoverResources() = 0; - - template static CrashRecoveryContextCleanup *create(T *, - ProvidedCleanups cleanupKind = - CrashRecoveryContextCleanup::DeleteCleanup); - + + CrashRecoveryContext *getContext() const { + return context; + } + private: friend class CrashRecoveryContext; CrashRecoveryContextCleanup *prev, *next; }; -template -class CrashRecoveryContextDestructorCleanup - : public CrashRecoveryContextCleanup -{ +template +class CrashRecoveryContextCleanupBase : public CrashRecoveryContextCleanup { +protected: T *resource; + CrashRecoveryContextCleanupBase(CrashRecoveryContext *context, T* resource) + : CrashRecoveryContextCleanup(context), resource(resource) {} public: - CrashRecoveryContextDestructorCleanup(T *resource) : resource(resource) {} - virtual void recoverResources() { - resource->~T(); + static DERIVED *create(T *x) { + if (x) { + if (CrashRecoveryContext *context = CrashRecoveryContext::GetCurrent()) + return new DERIVED(context, x); + } + return 0; } }; template -class CrashRecoveryContextDeleteCleanup - : public CrashRecoveryContextCleanup -{ - T *resource; +class CrashRecoveryContextDestructorCleanup : public + CrashRecoveryContextCleanupBase, T> { public: - CrashRecoveryContextDeleteCleanup(T *resource) : resource(resource) {} + CrashRecoveryContextDestructorCleanup(CrashRecoveryContext *context, + T *resource) + : CrashRecoveryContextCleanupBase< + CrashRecoveryContextDestructorCleanup, T>(context, resource) {} + virtual void recoverResources() { - delete resource; + this->resource->~T(); } }; template -struct CrashRecoveryContextTrait { - static inline CrashRecoveryContextCleanup * - createCleanup(T *resource, - CrashRecoveryContextCleanup::ProvidedCleanups cleanup) { - switch (cleanup) { - case CrashRecoveryContextCleanup::DeleteCleanup: - return new CrashRecoveryContextDeleteCleanup(resource); - case CrashRecoveryContextCleanup::DestructorCleanup: - return new CrashRecoveryContextDestructorCleanup(resource); - } - return 0; - } +class CrashRecoveryContextDeleteCleanup : public + CrashRecoveryContextCleanupBase, T> { +public: + CrashRecoveryContextDeleteCleanup(CrashRecoveryContext *context, T *resource) + : CrashRecoveryContextCleanupBase< + CrashRecoveryContextDeleteCleanup, T>(context, resource) {} + + void recoverResources() override { delete this->resource; } }; -template -inline CrashRecoveryContextCleanup* -CrashRecoveryContextCleanup::create(T *x, - CrashRecoveryContextCleanup::ProvidedCleanups cleanupKind) { - return CrashRecoveryContext::GetCurrent() ? - CrashRecoveryContextTrait::createCleanup(x, cleanupKind) : - 0; -} +template +class CrashRecoveryContextReleaseRefCleanup : public + CrashRecoveryContextCleanupBase, T> +{ +public: + CrashRecoveryContextReleaseRefCleanup(CrashRecoveryContext *context, + T *resource) + : CrashRecoveryContextCleanupBase, + T>(context, resource) {} + void recoverResources() override { this->resource->Release(); } +}; + +template > class CrashRecoveryContextCleanupRegistrar { - CrashRecoveryContext *context; CrashRecoveryContextCleanup *cleanup; public: - CrashRecoveryContextCleanupRegistrar(CrashRecoveryContextCleanup *cleanup) - : context(CrashRecoveryContext::GetCurrent()), - cleanup(cleanup) - { - if (context && cleanup) - context->registerCleanup(cleanup); + CrashRecoveryContextCleanupRegistrar(T *x) + : cleanup(Cleanup::create(x)) { + if (cleanup) + cleanup->getContext()->registerCleanup(cleanup); } + ~CrashRecoveryContextCleanupRegistrar() { - if (cleanup && !cleanup->cleanupFired) { - if (context) - context->unregisterCleanup(cleanup); - else - delete cleanup; - } + unregister(); + } + + void unregister() { + if (cleanup && !cleanup->cleanupFired) + cleanup->getContext()->unregisterCleanup(cleanup); + cleanup = 0; } }; }