summaryrefslogtreecommitdiff
path: root/src/pal/src/include/pal/mutex.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/include/pal/mutex.hpp')
-rw-r--r--src/pal/src/include/pal/mutex.hpp191
1 files changed, 191 insertions, 0 deletions
diff --git a/src/pal/src/include/pal/mutex.hpp b/src/pal/src/include/pal/mutex.hpp
new file mode 100644
index 0000000000..6a46689d7d
--- /dev/null
+++ b/src/pal/src/include/pal/mutex.hpp
@@ -0,0 +1,191 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*++
+
+
+
+Module Name:
+
+ mutex.hpp
+
+Abstract:
+
+ Mutex object structure definition.
+
+
+
+--*/
+
+#ifndef _PAL_MUTEX_H_
+#define _PAL_MUTEX_H_
+
+#include "corunix.hpp"
+#include "sharedmemory.h"
+
+#include <pthread.h>
+
+namespace CorUnix
+{
+ extern CObjectType otMutex;
+ extern CObjectType otNamedMutex;
+
+ PAL_ERROR
+ InternalCreateMutex(
+ CPalThread *pThread,
+ LPSECURITY_ATTRIBUTES lpMutexAttributes,
+ BOOL bInitialOwner,
+ LPCSTR lpName,
+ HANDLE *phMutex
+ );
+
+ PAL_ERROR
+ InternalReleaseMutex(
+ CPalThread *pThread,
+ HANDLE hMutex
+ );
+
+ PAL_ERROR
+ InternalOpenMutex(
+ CPalThread *pThread,
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCSTR lpName,
+ HANDLE *phMutex
+ );
+
+}
+
+#define SYNCSPINLOCK_F_ASYMMETRIC 1
+
+#define SPINLOCKInit(lock) (*(lock) = 0)
+#define SPINLOCKDestroy SPINLOCKInit
+
+void SPINLOCKAcquire (LONG * lock, unsigned int flags);
+void SPINLOCKRelease (LONG * lock);
+DWORD SPINLOCKTryAcquire (LONG * lock);
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Named mutex
+
+// Temporarily disabling usage of pthread process-shared mutexes on ARM/ARM64 due to functional issues that cannot easily be
+// detected with code due to hangs. See https://github.com/dotnet/coreclr/issues/5456.
+#if HAVE_FULLY_FEATURED_PTHREAD_MUTEXES && HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES && !(defined(_ARM_) || defined(_ARM64_))
+ #define NAMED_MUTEX_USE_PTHREAD_MUTEX 1
+#else
+ #define NAMED_MUTEX_USE_PTHREAD_MUTEX 0
+#endif
+
+enum class NamedMutexError : DWORD
+{
+ MaximumRecursiveLocksReached = ERROR_NOT_ENOUGH_MEMORY,
+ ThreadHasNotAcquiredMutex = ERROR_NOT_OWNER,
+ Unknown = ERROR_NOT_ENOUGH_MEMORY
+};
+
+enum class MutexTryAcquireLockResult
+{
+ AcquiredLock,
+ AcquiredLockButMutexWasAbandoned,
+ TimedOut
+};
+
+#if NAMED_MUTEX_USE_PTHREAD_MUTEX
+class MutexHelpers
+{
+public:
+ static void InitializeProcessSharedRobustRecursiveMutex(pthread_mutex_t *mutex);
+ static void DestroyMutex(pthread_mutex_t *mutex);
+
+ static MutexTryAcquireLockResult TryAcquireLock(pthread_mutex_t *mutex, DWORD timeoutMilliseconds);
+ static void ReleaseLock(pthread_mutex_t *mutex);
+};
+#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX
+
+class NamedMutexSharedData
+{
+private:
+#if NAMED_MUTEX_USE_PTHREAD_MUTEX
+ pthread_mutex_t m_lock;
+#else // !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ UINT32 m_timedWaiterCount;
+#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX
+ UINT32 m_lockOwnerProcessId;
+ UINT64 m_lockOwnerThreadId;
+ bool m_isAbandoned;
+
+public:
+ NamedMutexSharedData();
+ ~NamedMutexSharedData();
+
+#if NAMED_MUTEX_USE_PTHREAD_MUTEX
+public:
+ pthread_mutex_t *GetLock();
+#else // !NAMED_MUTEX_USE_PTHREAD_MUTEX
+public:
+ bool HasAnyTimedWaiters() const;
+ void IncTimedWaiterCount();
+ void DecTimedWaiterCount();
+#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX
+
+public:
+ bool IsAbandoned() const;
+ void SetIsAbandoned(bool isAbandoned);
+
+public:
+ bool IsLockOwnedByAnyThread() const;
+ bool IsLockOwnedByCurrentThread() const;
+ void SetLockOwnerToCurrentThread();
+ void ClearLockOwner();
+};
+
+class NamedMutexProcessData : public SharedMemoryProcessDataBase
+{
+private:
+ static const UINT8 SyncSystemVersion;
+ static const DWORD PollLoopMaximumSleepMilliseconds;
+
+private:
+ SharedMemoryProcessDataHeader *m_processDataHeader;
+ NamedMutexSharedData *m_sharedData;
+ SIZE_T m_lockCount;
+#if !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ HANDLE m_processLockHandle;
+ int m_sharedLockFileDescriptor;
+#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ CorUnix::CPalThread *m_lockOwnerThread;
+ NamedMutexProcessData *m_nextInThreadOwnedNamedMutexList;
+
+public:
+ static SharedMemoryProcessDataHeader *CreateOrOpen(LPCSTR name, bool acquireLockIfCreated, bool *createdRef);
+ static SharedMemoryProcessDataHeader *Open(LPCSTR name);
+private:
+ static SharedMemoryProcessDataHeader *CreateOrOpen(LPCSTR name, bool createIfNotExist, bool acquireLockIfCreated, bool *createdRef);
+
+public:
+ NamedMutexProcessData(
+ SharedMemoryProcessDataHeader *processDataHeader
+ #if !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ ,
+ int sharedLockFileDescriptor
+ #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ );
+ virtual void Close(bool isAbruptShutdown, bool releaseSharedData) override;
+
+private:
+ NamedMutexSharedData *GetSharedData() const;
+ void SetLockOwnerThread(CorUnix::CPalThread *lockOwnerThread);
+public:
+ NamedMutexProcessData *GetNextInThreadOwnedNamedMutexList() const;
+ void SetNextInThreadOwnedNamedMutexList(NamedMutexProcessData *next);
+
+public:
+ MutexTryAcquireLockResult TryAcquireLock(DWORD timeoutMilliseconds);
+ void ReleaseLock();
+ void Abandon();
+private:
+ void ActuallyReleaseLock();
+};
+
+#endif //_PAL_MUTEX_H_