@@ -21,23 +21,18 @@ Module Name:
21
21
#define _PAL_MUTEX_H_
22
22
23
23
#include " corunix.hpp"
24
- #include " sharedmemory.h"
25
24
26
25
#include < pthread.h>
27
26
28
27
namespace CorUnix
29
28
{
30
29
extern CObjectType otMutex;
31
- extern CObjectType otNamedMutex;
32
30
33
31
PAL_ERROR
34
32
InternalCreateMutex (
35
- SharedMemorySystemCallErrors *errors,
36
33
CPalThread *pThread,
37
34
LPSECURITY_ATTRIBUTES lpMutexAttributes,
38
35
BOOL bInitialOwner,
39
- LPCSTR lpName,
40
- BOOL bCurrentUserOnly,
41
36
HANDLE *phMutex
42
37
);
43
38
@@ -46,16 +41,6 @@ namespace CorUnix
46
41
CPalThread *pThread,
47
42
HANDLE hMutex
48
43
);
49
-
50
- PAL_ERROR
51
- InternalOpenMutex (
52
- SharedMemorySystemCallErrors *errors,
53
- CPalThread *pThread,
54
- LPCSTR lpName,
55
- BOOL bCurrentUserOnly,
56
- HANDLE *phMutex
57
- );
58
-
59
44
}
60
45
61
46
#define SYNCSPINLOCK_F_ASYMMETRIC 1
@@ -66,197 +51,4 @@ namespace CorUnix
66
51
void SPINLOCKAcquire (LONG * lock, unsigned int flags);
67
52
void SPINLOCKRelease (LONG * lock);
68
53
DWORD SPINLOCKTryAcquire (LONG * lock);
69
-
70
- // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71
- // Named mutex
72
-
73
- /*
74
- Design
75
-
76
- - On systems that support pthread process-shared robust recursive mutexes, they will be used
77
- - On other systems, file locks are used. File locks unfortunately don't have a timeout in the blocking wait call, and I didn't
78
- find any other sync object with a timed wait with the necessary properties, so polling is done for timed waits.
79
-
80
- Shared memory files
81
- - Session-scoped mutexes (name not prefixed, or prefixed with Local) go in /tmp/.dotnet/shm/session<sessionId>/<mutexName>
82
- - Globally-scoped mutexes (name prefixed with Global) go in /tmp/.dotnet/shm/global/<mutexName>
83
- - Contains shared state, and is mmap'ped into the process, see SharedMemorySharedDataHeader and NamedMutexSharedData for data
84
- stored
85
- - Creation and deletion is synchronized using an exclusive file lock on the shm directory
86
- - Any process using the shared memory file holds a shared file lock on the shared memory file
87
- - Upon creation, if the shared memory file already exists, an exclusive file lock is attempted on it, to see if the file data is
88
- valid. If no other processes have the mutex open, the file is reinitialized.
89
- - Upon releasing the last reference to a mutex in a process, it will try to get an exclusive lock on the shared memory file to
90
- see if any other processes have the mutex opened. If not, the file is deleted, along with the session directory if it's empty.
91
- The .dotnet and shm directories are not deleted.
92
- - This allows managing the lifetime of mutex state based on active processes that have the mutex open. Depending on how the
93
- process terminated, the file may still be left over in the tmp directory, I haven't found anything that can be done about
94
- that.
95
-
96
- Lock files when using file locks:
97
- - In addition to the shared memory file, we need another file for the actual synchronization file lock, since a file lock on the
98
- shared memory file is used for lifetime purposes.
99
- - These files go in /tmp/.dotnet/lockfiles/session<sessionId>|global/<mutexName>
100
- - The file is empty, and is only used for file locks
101
-
102
- Process data
103
- - See SharedMemoryProcessDataHeader and NamedMutexProcessData for data stored
104
- - Per mutex name, there is only one instance of process data that is ref-counted. They are currently stored in a linked list in
105
- SharedMemoryManager. It should use a hash table, but of the many hash table implementations that are already there, none seem
106
- to be easily usable in the PAL. I'll look into that and will fix later.
107
- - Refers to the associated shared memory, and knows how to clean up both the process data and shared data
108
- - When using file locks for synchronization, a process-local mutex is also created for synchronizing threads, since file locks
109
- are owned at the file descriptor level and there is only one open file descriptor in the process per mutex name. The
110
- process-local mutex is locked around the file lock, so that only one thread per process is ever trying to flock on a given
111
- file descriptor.
112
-
113
- Abandon detection
114
- - When a lock is acquired, the process data is added to a linked list on the owning thread
115
- - When a thread exits, the list is walked, each mutex is flagged as abandoned and released
116
- - For detecting process abruptly terminating, pthread robust mutexes give us that. When using file locks, the file lock is
117
- automatically released by the system. Upon acquiring a lock, the lock owner info in the shared memory is checked to see if the
118
- mutex was abandoned.
119
-
120
- Miscellaneous
121
- - CreateMutex and OpenMutex both create new handles for each mutex opened. Each handle just refers to the process data header
122
- for the mutex name.
123
- - Some of the above features are already available in the PAL, but not quite in a way that I can use for this purpose. The
124
- existing shared memory, naming, and waiting infrastructure is not suitable for this purpose, and is not used.
125
- */
126
-
127
- // - On FreeBSD, pthread process-shared robust mutexes cannot be placed in shared memory mapped independently by the processes
128
- // involved. See https://github.com/dotnet/runtime/issues/10519.
129
- // - On OSX, pthread robust mutexes were/are not available at the time of this writing. In case they are made available in the
130
- // future, their use is disabled for compatibility.
131
- #if HAVE_FULLY_FEATURED_PTHREAD_MUTEXES && \
132
- HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES && \
133
- !(defined (__FreeBSD__) || defined (TARGET_OSX))
134
-
135
- #define NAMED_MUTEX_USE_PTHREAD_MUTEX 1
136
- #else
137
- #define NAMED_MUTEX_USE_PTHREAD_MUTEX 0
138
- #endif
139
-
140
- enum class NamedMutexError : DWORD
141
- {
142
- MaximumRecursiveLocksReached = ERROR_NOT_ENOUGH_MEMORY,
143
- ThreadHasNotAcquiredMutex = ERROR_NOT_OWNER,
144
- Unknown = ERROR_NOT_ENOUGH_MEMORY
145
- };
146
-
147
- enum class MutexTryAcquireLockResult
148
- {
149
- AcquiredLock,
150
- AcquiredLockButMutexWasAbandoned,
151
- TimedOut
152
- };
153
-
154
- #if NAMED_MUTEX_USE_PTHREAD_MUTEX
155
- class MutexHelpers
156
- {
157
- public:
158
- static void InitializeProcessSharedRobustRecursiveMutex (SharedMemorySystemCallErrors *errors, pthread_mutex_t *mutex);
159
- static void DestroyMutex (pthread_mutex_t *mutex);
160
-
161
- static MutexTryAcquireLockResult TryAcquireLock (SharedMemorySystemCallErrors *errors, pthread_mutex_t *mutex, DWORD timeoutMilliseconds);
162
- static void ReleaseLock (pthread_mutex_t *mutex);
163
- };
164
- #endif // NAMED_MUTEX_USE_PTHREAD_MUTEX
165
-
166
- class NamedMutexSharedData
167
- {
168
- private:
169
- #if NAMED_MUTEX_USE_PTHREAD_MUTEX
170
- pthread_mutex_t m_lock;
171
- #else // !NAMED_MUTEX_USE_PTHREAD_MUTEX
172
- UINT32 m_timedWaiterCount;
173
- #endif // NAMED_MUTEX_USE_PTHREAD_MUTEX
174
- UINT32 m_lockOwnerProcessId;
175
- UINT64 m_lockOwnerThreadId;
176
- bool m_isAbandoned;
177
-
178
- public:
179
- NamedMutexSharedData (SharedMemorySystemCallErrors *errors);
180
- ~NamedMutexSharedData ();
181
-
182
- #if NAMED_MUTEX_USE_PTHREAD_MUTEX
183
- public:
184
- pthread_mutex_t *GetLock ();
185
- #else // !NAMED_MUTEX_USE_PTHREAD_MUTEX
186
- public:
187
- bool HasAnyTimedWaiters () const ;
188
- void IncTimedWaiterCount ();
189
- void DecTimedWaiterCount ();
190
- #endif // NAMED_MUTEX_USE_PTHREAD_MUTEX
191
-
192
- public:
193
- bool IsAbandoned () const ;
194
- void SetIsAbandoned (bool isAbandoned);
195
-
196
- public:
197
- bool IsLockOwnedByAnyThread () const ;
198
- bool IsLockOwnedByCurrentThread () const ;
199
- void SetLockOwnerToCurrentThread ();
200
- void ClearLockOwner ();
201
- };
202
-
203
- class NamedMutexProcessData : public SharedMemoryProcessDataBase
204
- {
205
- private:
206
- static const UINT8 SyncSystemVersion;
207
- static const DWORD PollLoopMaximumSleepMilliseconds;
208
-
209
- private:
210
- SharedMemoryProcessDataHeader *m_processDataHeader;
211
- SIZE_T m_lockCount;
212
- #if !NAMED_MUTEX_USE_PTHREAD_MUTEX
213
- HANDLE m_processLockHandle;
214
- int m_sharedLockFileDescriptor;
215
- #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX
216
- CorUnix::CPalThread *m_lockOwnerThread;
217
- NamedMutexProcessData *m_nextInThreadOwnedNamedMutexList;
218
- bool m_hasRefFromLockOwnerThread;
219
-
220
- public:
221
- static SharedMemoryProcessDataHeader *CreateOrOpen (SharedMemorySystemCallErrors *errors, LPCSTR name, bool isUserScope, bool acquireLockIfCreated, bool *createdRef);
222
- static SharedMemoryProcessDataHeader *Open (SharedMemorySystemCallErrors *errors, LPCSTR name, bool isUserScope);
223
- private:
224
- static SharedMemoryProcessDataHeader *CreateOrOpen (SharedMemorySystemCallErrors *errors, LPCSTR name, bool isUserScope, bool createIfNotExist, bool acquireLockIfCreated, bool *createdRef);
225
-
226
- public:
227
- NamedMutexProcessData (
228
- SharedMemoryProcessDataHeader *processDataHeader
229
- #if !NAMED_MUTEX_USE_PTHREAD_MUTEX
230
- ,
231
- int sharedLockFileDescriptor
232
- #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX
233
- );
234
-
235
- public:
236
- virtual bool CanClose () const override ;
237
- virtual bool HasImplicitRef () const override ;
238
- virtual void SetHasImplicitRef (bool value) override ;
239
- virtual void Close (bool isAbruptShutdown, bool releaseSharedData) override ;
240
-
241
- public:
242
- bool IsLockOwnedByCurrentThread () const
243
- {
244
- return GetSharedData ()->IsLockOwnedByCurrentThread ();
245
- }
246
-
247
- private:
248
- NamedMutexSharedData *GetSharedData () const ;
249
- void SetLockOwnerThread (CorUnix::CPalThread *lockOwnerThread);
250
- public:
251
- NamedMutexProcessData *GetNextInThreadOwnedNamedMutexList () const ;
252
- void SetNextInThreadOwnedNamedMutexList (NamedMutexProcessData *next);
253
-
254
- public:
255
- MutexTryAcquireLockResult TryAcquireLock (SharedMemorySystemCallErrors *errors, DWORD timeoutMilliseconds);
256
- void ReleaseLock ();
257
- void Abandon ();
258
- private:
259
- void ActuallyReleaseLock ();
260
- };
261
-
262
54
#endif // _PAL_MUTEX_H_
0 commit comments