[tools] Add nuget-hash-extractor tool to help produce the runtime ignored assemblies...
[mono-project.git] / mono / utils / mono-os-mutex.h
blobcd33375894c1db0f95fdf61ae054c50043a18f2d
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * mono-os-mutex.h: Portability wrappers around POSIX Mutexes
5 * Authors: Jeffrey Stedfast <fejj@ximian.com>
7 * Copyright 2002 Ximian, Inc. (www.ximian.com)
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #ifndef __MONO_OS_MUTEX_H__
13 #define __MONO_OS_MUTEX_H__
15 #include <config.h>
16 #include <glib.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
22 #if !defined(HOST_WIN32)
23 #include <pthread.h>
24 #include <errno.h>
25 #else
26 #include <winsock2.h>
27 #include <windows.h>
28 #endif
30 #ifdef HAVE_SYS_TIME_H
31 #include <sys/time.h>
32 #endif
34 G_BEGIN_DECLS
36 #ifndef MONO_INFINITE_WAIT
37 #define MONO_INFINITE_WAIT ((guint32) 0xFFFFFFFF)
38 #endif
41 #if !defined(HOST_WIN32)
43 typedef pthread_mutex_t mono_mutex_t;
44 typedef pthread_cond_t mono_cond_t;
46 static inline void
47 mono_os_mutex_init (mono_mutex_t *mutex)
49 int res;
51 res = pthread_mutex_init (mutex, NULL);
52 if (G_UNLIKELY (res != 0))
53 g_error ("%s: pthread_mutex_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
56 static inline void
57 mono_os_mutex_init_recursive (mono_mutex_t *mutex)
59 int res;
60 pthread_mutexattr_t attr;
62 res = pthread_mutexattr_init (&attr);
63 if (G_UNLIKELY (res != 0))
64 g_error ("%s: pthread_mutexattr_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
66 res = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
67 if (G_UNLIKELY (res != 0))
68 g_error ("%s: pthread_mutexattr_settype failed with \"%s\" (%d)", __func__, g_strerror (res), res);
70 res = pthread_mutex_init (mutex, &attr);
71 if (G_UNLIKELY (res != 0))
72 g_error ("%s: pthread_mutex_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
74 res = pthread_mutexattr_destroy (&attr);
75 if (G_UNLIKELY (res != 0))
76 g_error ("%s: pthread_mutexattr_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
79 static inline void
80 mono_os_mutex_destroy (mono_mutex_t *mutex)
82 int res;
84 res = pthread_mutex_destroy (mutex);
85 if (G_UNLIKELY (res != 0))
86 g_error ("%s: pthread_mutex_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
89 static inline void
90 mono_os_mutex_lock (mono_mutex_t *mutex)
92 int res;
94 res = pthread_mutex_lock (mutex);
95 if (G_UNLIKELY (res != 0))
96 g_error ("%s: pthread_mutex_lock failed with \"%s\" (%d)", __func__, g_strerror (res), res);
99 static inline int
100 mono_os_mutex_trylock (mono_mutex_t *mutex)
102 int res;
104 res = pthread_mutex_trylock (mutex);
105 if (G_UNLIKELY (res != 0 && res != EBUSY))
106 g_error ("%s: pthread_mutex_trylock failed with \"%s\" (%d)", __func__, g_strerror (res), res);
108 return res != 0 ? -1 : 0;
111 static inline void
112 mono_os_mutex_unlock (mono_mutex_t *mutex)
114 int res;
116 res = pthread_mutex_unlock (mutex);
117 if (G_UNLIKELY (res != 0))
118 g_error ("%s: pthread_mutex_unlock failed with \"%s\" (%d)", __func__, g_strerror (res), res);
121 static inline void
122 mono_os_cond_init (mono_cond_t *cond)
124 int res;
126 res = pthread_cond_init (cond, NULL);
127 if (G_UNLIKELY (res != 0))
128 g_error ("%s: pthread_cond_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
131 static inline void
132 mono_os_cond_destroy (mono_cond_t *cond)
134 int res;
136 res = pthread_cond_destroy (cond);
137 if (G_UNLIKELY (res != 0))
138 g_error ("%s: pthread_cond_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
141 static inline void
142 mono_os_cond_wait (mono_cond_t *cond, mono_mutex_t *mutex)
144 int res;
146 res = pthread_cond_wait (cond, mutex);
147 if (G_UNLIKELY (res != 0))
148 g_error ("%s: pthread_cond_wait failed with \"%s\" (%d)", __func__, g_strerror (res), res);
151 static inline int
152 mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms)
154 struct timeval tv;
155 struct timespec ts;
156 gint64 usecs;
157 int res;
159 if (timeout_ms == MONO_INFINITE_WAIT) {
160 mono_os_cond_wait (cond, mutex);
161 return 0;
164 /* ms = 10^-3, us = 10^-6, ns = 10^-9 */
166 res = gettimeofday (&tv, NULL);
167 if (G_UNLIKELY (res != 0))
168 g_error ("%s: gettimeofday failed with \"%s\" (%d)", __func__, g_strerror (errno), errno);
170 tv.tv_sec += timeout_ms / 1000;
171 usecs = tv.tv_usec + ((timeout_ms % 1000) * 1000);
172 if (usecs >= 1000000) {
173 usecs -= 1000000;
174 tv.tv_sec ++;
176 ts.tv_sec = tv.tv_sec;
177 ts.tv_nsec = usecs * 1000;
179 res = pthread_cond_timedwait (cond, mutex, &ts);
180 if (G_UNLIKELY (res != 0 && res != ETIMEDOUT))
181 g_error ("%s: pthread_cond_timedwait failed with \"%s\" (%d)", __func__, g_strerror (res), res);
183 return res != 0 ? -1 : 0;
186 static inline void
187 mono_os_cond_signal (mono_cond_t *cond)
189 int res;
191 res = pthread_cond_signal (cond);
192 if (G_UNLIKELY (res != 0))
193 g_error ("%s: pthread_cond_signal failed with \"%s\" (%d)", __func__, g_strerror (res), res);
196 static inline void
197 mono_os_cond_broadcast (mono_cond_t *cond)
199 int res;
201 res = pthread_cond_broadcast (cond);
202 if (G_UNLIKELY (res != 0))
203 g_error ("%s: pthread_cond_broadcast failed with \"%s\" (%d)", __func__, g_strerror (res), res);
206 #else
208 /* Vanilla MinGW is missing some defs, load them from MinGW-w64. */
209 #if defined __MINGW32__ && !defined __MINGW64_VERSION_MAJOR && (_WIN32_WINNT >= 0x0600)
211 /* Fixme: Opaque structs */
212 typedef PVOID RTL_CONDITION_VARIABLE;
213 typedef PVOID RTL_SRWLOCK;
215 #ifndef _RTL_RUN_ONCE_DEF
216 #define _RTL_RUN_ONCE_DEF 1
217 typedef PVOID RTL_RUN_ONCE, *PRTL_RUN_ONCE;
218 typedef DWORD (WINAPI *PRTL_RUN_ONCE_INIT_FN)(PRTL_RUN_ONCE, PVOID, PVOID *);
219 #define RTL_RUN_ONCE_INIT 0
220 #define RTL_RUN_ONCE_CHECK_ONLY 1UL
221 #define RTL_RUN_ONCE_ASYNC 2UL
222 #define RTL_RUN_ONCE_INIT_FAILED 4UL
223 #define RTL_RUN_ONCE_CTX_RESERVED_BITS 2
224 #endif /* _RTL_RUN_ONCE_DEF */
225 #define RTL_SRWLOCK_INIT 0
226 #define RTL_CONDITION_VARIABLE_INIT 0
227 #define RTL_CONDITION_VARIABLE_LOCKMODE_SHARED 1
229 #define CONDITION_VARIABLE_INIT RTL_CONDITION_VARIABLE_INIT
230 #define CONDITION_VARIABLE_LOCKMODE_SHARED RTL_CONDITION_VARIABLE_LOCKMODE_SHARED
231 #define SRWLOCK_INIT RTL_SRWLOCK_INIT
233 /*Condition Variables http://msdn.microsoft.com/en-us/library/ms682052%28VS.85%29.aspx*/
234 typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
235 typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
237 WINBASEAPI VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE ConditionVariable);
238 WINBASEAPI WINBOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE ConditionVariable, PCRITICAL_SECTION CriticalSection, DWORD dwMilliseconds);
239 WINBASEAPI WINBOOL WINAPI SleepConditionVariableSRW(PCONDITION_VARIABLE ConditionVariable, PSRWLOCK SRWLock, DWORD dwMilliseconds, ULONG Flags);
240 WINBASEAPI VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE ConditionVariable);
241 WINBASEAPI VOID WINAPI WakeConditionVariable(PCONDITION_VARIABLE ConditionVariable);
243 /*Slim Reader/Writer (SRW) Locks http://msdn.microsoft.com/en-us/library/aa904937%28VS.85%29.aspx*/
244 WINBASEAPI VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK SRWLock);
245 WINBASEAPI VOID WINAPI AcquireSRWLockShared(PSRWLOCK SRWLock);
246 WINBASEAPI VOID WINAPI InitializeSRWLock(PSRWLOCK SRWLock);
247 WINBASEAPI VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK SRWLock);
248 WINBASEAPI VOID WINAPI ReleaseSRWLockShared(PSRWLOCK SRWLock);
250 WINBASEAPI BOOLEAN TryAcquireSRWLockExclusive(PSRWLOCK SRWLock);
251 WINBASEAPI BOOLEAN TryAcquireSRWLockShared(PSRWLOCK SRWLock);
253 /*One-Time Initialization http://msdn.microsoft.com/en-us/library/aa363808(VS.85).aspx*/
254 #define INIT_ONCE_ASYNC 0x00000002UL
255 #define INIT_ONCE_INIT_FAILED 0x00000004UL
257 typedef PRTL_RUN_ONCE PINIT_ONCE;
258 typedef PRTL_RUN_ONCE LPINIT_ONCE;
259 typedef WINBOOL CALLBACK (*PINIT_ONCE_FN) (PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context);
261 WINBASEAPI WINBOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL fPending, LPVOID *lpContext);
262 WINBASEAPI WINBOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpContext);
263 WINBASEAPI WINBOOL WINAPI InitOnceExecuteOnce(PINIT_ONCE InitOnce, PINIT_ONCE_FN InitFn, PVOID Parameter, LPVOID *Context);
265 /* https://msdn.microsoft.com/en-us/library/windows/desktop/ms683477(v=vs.85).aspx */
266 WINBASEAPI BOOL WINAPI InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags);
268 #define CRITICAL_SECTION_NO_DEBUG_INFO 0x01000000
270 #endif /* defined __MINGW32__ && !defined __MINGW64_VERSION_MAJOR && (_WIN32_WINNT >= 0x0600) */
272 typedef CRITICAL_SECTION mono_mutex_t;
273 typedef CONDITION_VARIABLE mono_cond_t;
275 static inline void
276 mono_os_mutex_init (mono_mutex_t *mutex)
278 BOOL res;
280 res = InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
281 if (G_UNLIKELY (res == 0))
282 g_error ("%s: InitializeCriticalSectionEx failed with error %d", __func__, GetLastError ());
285 static inline void
286 mono_os_mutex_init_recursive (mono_mutex_t *mutex)
288 BOOL res;
290 res = InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
291 if (G_UNLIKELY (res == 0))
292 g_error ("%s: InitializeCriticalSectionEx failed with error %d", __func__, GetLastError ());
295 static inline void
296 mono_os_mutex_destroy (mono_mutex_t *mutex)
298 DeleteCriticalSection (mutex);
301 static inline void
302 mono_os_mutex_lock (mono_mutex_t *mutex)
304 EnterCriticalSection (mutex);
307 static inline int
308 mono_os_mutex_trylock (mono_mutex_t *mutex)
310 return TryEnterCriticalSection (mutex) == 0 ? -1 : 0;
313 static inline void
314 mono_os_mutex_unlock (mono_mutex_t *mutex)
316 LeaveCriticalSection (mutex);
319 static inline void
320 mono_os_cond_init (mono_cond_t *cond)
322 InitializeConditionVariable (cond);
325 static inline void
326 mono_os_cond_destroy (mono_cond_t *cond)
328 /* Beauty of win32 API: do not destroy it */
331 static inline void
332 mono_os_cond_wait (mono_cond_t *cond, mono_mutex_t *mutex)
334 BOOL res;
336 res = SleepConditionVariableCS (cond, mutex, INFINITE);
337 if (G_UNLIKELY (res == 0))
338 g_error ("%s: SleepConditionVariableCS failed with error %d", __func__, GetLastError ());
341 static inline int
342 mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms)
344 BOOL res;
346 res = SleepConditionVariableCS (cond, mutex, timeout_ms);
347 if (G_UNLIKELY (res == 0 && GetLastError () != ERROR_TIMEOUT))
348 g_error ("%s: SleepConditionVariableCS failed with error %d", __func__, GetLastError ());
350 return res == 0 ? -1 : 0;
353 static inline void
354 mono_os_cond_signal (mono_cond_t *cond)
356 WakeConditionVariable (cond);
359 static inline void
360 mono_os_cond_broadcast (mono_cond_t *cond)
362 WakeAllConditionVariable (cond);
365 #endif
367 G_END_DECLS
369 #endif /* __MONO_OS_MUTEX_H__ */