diff options
author | Andy Ayers <andya@microsoft.com> | 2016-05-19 10:39:25 -0700 |
---|---|---|
committer | Andy Ayers <andya@microsoft.com> | 2016-05-20 16:16:56 -0700 |
commit | 27484e2c82d8b3b98322e1d758b9caf312231c9c (patch) | |
tree | 77f4c24bbee1de05a7ef1d6893f1f366b6da7fe5 /src/jit/utils.h | |
parent | ce3ff76234bf199b4498a5d31f05af6eb43073f6 (diff) | |
download | coreclr-27484e2c82d8b3b98322e1d758b9caf312231c9c.tar.gz coreclr-27484e2c82d8b3b98322e1d758b9caf312231c9c.tar.bz2 coreclr-27484e2c82d8b3b98322e1d758b9caf312231c9c.zip |
Inliner: locks for xml read/write access
Move CritSecObject into util.h, and use it to lock around reading
and writing inline Xml. Introduce CritSecHolder for RAII management
of the locks.
Add a simple file position cache for methods to speed up replay
when the inline xml file is large.
Diffstat (limited to 'src/jit/utils.h')
-rw-r--r-- | src/jit/utils.h | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/jit/utils.h b/src/jit/utils.h index db7756809b..af9f2db009 100644 --- a/src/jit/utils.h +++ b/src/jit/utils.h @@ -578,4 +578,78 @@ public: static double round(double d); }; + +// The CLR requires that critical section locks be initialized via its ClrCreateCriticalSection API...but +// that can't be called until the CLR is initialized. If we have static data that we'd like to protect by a +// lock, and we have a statically allocated lock to protect that data, there's an issue in how to initialize +// that lock. We could insert an initialize call in the startup path, but one might prefer to keep the code +// more local. For such situations, CritSecObject solves the initialization problem, via a level of +// indirection. A pointer to the lock is initially null, and when we query for the lock pointer via "Val()". +// If the lock has not yet been allocated, this allocates one (here a leaf lock), and uses a +// CompareAndExchange-based lazy-initialization to update the field. If this fails, the allocated lock is +// destroyed. This will work as long as the first locking attempt occurs after enough CLR initialization has +// happened to make ClrCreateCriticalSection calls legal. + +class CritSecObject +{ +public: + + CritSecObject() + { + m_pCs = NULL; + } + + CRITSEC_COOKIE Val() + { + if (m_pCs == NULL) + { + // CompareExchange-based lazy init. + CRITSEC_COOKIE newCs = ClrCreateCriticalSection(CrstLeafLock, CRST_DEFAULT); + CRITSEC_COOKIE observed = InterlockedCompareExchangeT(&m_pCs, newCs, NULL); + if (observed != NULL) + { + ClrDeleteCriticalSection(newCs); + } + } + return m_pCs; + } + +private: + + // CRITSEC_COOKIE is an opaque pointer type. + CRITSEC_COOKIE m_pCs; + + // No copying or assignment allowed. + CritSecObject(const CritSecObject&) = delete; + CritSecObject& operator=(const CritSecObject&) = delete; +}; + +// Stack-based holder for a critial section lock. +// Ensures lock is released. + +class CritSecHolder +{ +public: + + CritSecHolder(CritSecObject& critSec) + : m_CritSec(critSec) + { + ClrEnterCriticalSection(m_CritSec.Val()); + } + + ~CritSecHolder() + { + ClrLeaveCriticalSection(m_CritSec.Val()); + } + +private: + + CritSecObject& m_CritSec; + + // No copying or assignment allowed. + CritSecHolder(const CritSecHolder&) = delete; + CritSecHolder& operator=(const CritSecHolder&) = delete; +}; + + #endif // _UTILS_H_ |