Merge pull request #3262 from lindenlab/add_continuations_test
[mono.git] / mono / utils / mono-os-mutex.h
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
4  *
5  * Authors: Jeffrey Stedfast <fejj@ximian.com>
6  *
7  * Copyright 2002 Ximian, Inc. (www.ximian.com)
8  *
9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
10  */
11
12 #ifndef __MONO_OS_MUTEX_H__
13 #define __MONO_OS_MUTEX_H__
14
15 #include <config.h>
16 #include <glib.h>
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21
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
29
30 #ifdef HAVE_SYS_TIME_H
31 #include <sys/time.h>
32 #endif
33
34 G_BEGIN_DECLS
35
36 #ifndef MONO_INFINITE_WAIT
37 #define MONO_INFINITE_WAIT ((guint32) 0xFFFFFFFF)
38 #endif
39
40
41 #if !defined(HOST_WIN32)
42
43 typedef pthread_mutex_t mono_mutex_t;
44 typedef pthread_cond_t mono_cond_t;
45
46 static inline int
47 mono_os_mutex_init (mono_mutex_t *mutex)
48 {
49         return pthread_mutex_init (mutex, NULL);
50 }
51
52 static inline int
53 mono_os_mutex_init_recursive (mono_mutex_t *mutex)
54 {
55         int res;
56         pthread_mutexattr_t attr;
57
58         pthread_mutexattr_init (&attr);
59         pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
60         res = pthread_mutex_init (mutex, &attr);
61         pthread_mutexattr_destroy (&attr);
62
63         return res;
64 }
65
66 static inline int
67 mono_os_mutex_destroy (mono_mutex_t *mutex)
68 {
69         return pthread_mutex_destroy (mutex);
70 }
71
72 static inline int
73 mono_os_mutex_lock (mono_mutex_t *mutex)
74 {
75         int res;
76
77         res = pthread_mutex_lock (mutex);
78         g_assert (res != EINVAL);
79
80         return res;
81 }
82
83 static inline int
84 mono_os_mutex_trylock (mono_mutex_t *mutex)
85 {
86         return pthread_mutex_trylock (mutex);
87 }
88
89 static inline int
90 mono_os_mutex_unlock (mono_mutex_t *mutex)
91 {
92         return pthread_mutex_unlock (mutex);
93 }
94
95 static inline int
96 mono_os_cond_init (mono_cond_t *cond)
97 {
98         return pthread_cond_init (cond, NULL);
99 }
100
101 static inline int
102 mono_os_cond_destroy (mono_cond_t *cond)
103 {
104         return pthread_cond_destroy (cond);
105 }
106
107 static inline int
108 mono_os_cond_wait (mono_cond_t *cond, mono_mutex_t *mutex)
109 {
110         int res;
111
112         res = pthread_cond_wait (cond, mutex);
113         g_assert (res != EINVAL);
114
115         return res;
116 }
117
118 static inline int
119 mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms)
120 {
121         struct timeval tv;
122         struct timespec ts;
123         gint64 usecs;
124         int res;
125
126         if (timeout_ms == MONO_INFINITE_WAIT)
127                 return mono_os_cond_wait (cond, mutex);
128
129         /* ms = 10^-3, us = 10^-6, ns = 10^-9 */
130
131         gettimeofday (&tv, NULL);
132         tv.tv_sec += timeout_ms / 1000;
133         usecs = tv.tv_usec + ((timeout_ms % 1000) * 1000);
134         if (usecs >= 1000000) {
135                 usecs -= 1000000;
136                 tv.tv_sec ++;
137         }
138         ts.tv_sec = tv.tv_sec;
139         ts.tv_nsec = usecs * 1000;
140
141         res = pthread_cond_timedwait (cond, mutex, &ts);
142         g_assert (res != EINVAL);
143
144         return res;
145 }
146
147 static inline int
148 mono_os_cond_signal (mono_cond_t *cond)
149 {
150         return pthread_cond_signal (cond);
151 }
152
153 static inline int
154 mono_os_cond_broadcast (mono_cond_t *cond)
155 {
156         return pthread_cond_broadcast (cond);
157 }
158
159 #else
160
161 /* Vanilla MinGW is missing some defs, load them from MinGW-w64. */
162 #if defined __MINGW32__ && !defined __MINGW64_VERSION_MAJOR && (_WIN32_WINNT >= 0x0600)
163
164 /* Fixme: Opaque structs */
165 typedef PVOID RTL_CONDITION_VARIABLE;
166 typedef PVOID RTL_SRWLOCK;
167
168 #ifndef _RTL_RUN_ONCE_DEF
169 #define _RTL_RUN_ONCE_DEF 1
170 typedef PVOID RTL_RUN_ONCE, *PRTL_RUN_ONCE;
171 typedef DWORD (WINAPI *PRTL_RUN_ONCE_INIT_FN)(PRTL_RUN_ONCE, PVOID, PVOID *);
172 #define RTL_RUN_ONCE_INIT 0
173 #define RTL_RUN_ONCE_CHECK_ONLY 1UL
174 #define RTL_RUN_ONCE_ASYNC 2UL
175 #define RTL_RUN_ONCE_INIT_FAILED 4UL
176 #define RTL_RUN_ONCE_CTX_RESERVED_BITS 2
177 #endif /* _RTL_RUN_ONCE_DEF */
178 #define RTL_SRWLOCK_INIT 0
179 #define RTL_CONDITION_VARIABLE_INIT 0
180 #define RTL_CONDITION_VARIABLE_LOCKMODE_SHARED 1
181
182 #define CONDITION_VARIABLE_INIT RTL_CONDITION_VARIABLE_INIT
183 #define CONDITION_VARIABLE_LOCKMODE_SHARED RTL_CONDITION_VARIABLE_LOCKMODE_SHARED
184 #define SRWLOCK_INIT RTL_SRWLOCK_INIT
185
186 /*Condition Variables http://msdn.microsoft.com/en-us/library/ms682052%28VS.85%29.aspx*/
187 typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
188 typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
189
190 WINBASEAPI VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE ConditionVariable);
191 WINBASEAPI WINBOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE ConditionVariable, PCRITICAL_SECTION CriticalSection, DWORD dwMilliseconds);
192 WINBASEAPI WINBOOL WINAPI SleepConditionVariableSRW(PCONDITION_VARIABLE ConditionVariable, PSRWLOCK SRWLock, DWORD dwMilliseconds, ULONG Flags);
193 WINBASEAPI VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE ConditionVariable);
194 WINBASEAPI VOID WINAPI WakeConditionVariable(PCONDITION_VARIABLE ConditionVariable);
195
196 /*Slim Reader/Writer (SRW) Locks http://msdn.microsoft.com/en-us/library/aa904937%28VS.85%29.aspx*/
197 WINBASEAPI VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK SRWLock);
198 WINBASEAPI VOID WINAPI AcquireSRWLockShared(PSRWLOCK SRWLock);
199 WINBASEAPI VOID WINAPI InitializeSRWLock(PSRWLOCK SRWLock);
200 WINBASEAPI VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK SRWLock);
201 WINBASEAPI VOID WINAPI ReleaseSRWLockShared(PSRWLOCK SRWLock);
202
203 WINBASEAPI BOOLEAN TryAcquireSRWLockExclusive(PSRWLOCK SRWLock);
204 WINBASEAPI BOOLEAN TryAcquireSRWLockShared(PSRWLOCK SRWLock);
205
206 /*One-Time Initialization http://msdn.microsoft.com/en-us/library/aa363808(VS.85).aspx*/
207 #define INIT_ONCE_ASYNC 0x00000002UL
208 #define INIT_ONCE_INIT_FAILED 0x00000004UL
209
210 typedef PRTL_RUN_ONCE PINIT_ONCE;
211 typedef PRTL_RUN_ONCE LPINIT_ONCE;
212 typedef WINBOOL CALLBACK (*PINIT_ONCE_FN) (PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context);
213
214 WINBASEAPI WINBOOL WINAPI InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL fPending, LPVOID *lpContext);
215 WINBASEAPI WINBOOL WINAPI InitOnceComplete(LPINIT_ONCE lpInitOnce, DWORD dwFlags, LPVOID lpContext);
216 WINBASEAPI WINBOOL WINAPI InitOnceExecuteOnce(PINIT_ONCE InitOnce, PINIT_ONCE_FN InitFn, PVOID Parameter, LPVOID *Context);
217
218 /* https://msdn.microsoft.com/en-us/library/windows/desktop/ms683477(v=vs.85).aspx */
219 WINBASEAPI BOOL WINAPI InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags);
220
221 #define CRITICAL_SECTION_NO_DEBUG_INFO 0x01000000
222
223 #endif /* defined __MINGW32__ && !defined __MINGW64_VERSION_MAJOR && (_WIN32_WINNT >= 0x0600) */
224
225 typedef CRITICAL_SECTION mono_mutex_t;
226 typedef CONDITION_VARIABLE mono_cond_t;
227
228 static inline int
229 mono_os_mutex_init (mono_mutex_t *mutex)
230 {
231         InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
232         return 0;
233 }
234
235 static inline int
236 mono_os_mutex_init_recursive (mono_mutex_t *mutex)
237 {
238         InitializeCriticalSectionEx (mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
239         return 0;
240 }
241
242 static inline int
243 mono_os_mutex_destroy (mono_mutex_t *mutex)
244 {
245         DeleteCriticalSection (mutex);
246         return 0;
247 }
248
249 static inline int
250 mono_os_mutex_lock (mono_mutex_t *mutex)
251 {
252         EnterCriticalSection (mutex);
253         return 0;
254 }
255
256 static inline int
257 mono_os_mutex_trylock (mono_mutex_t *mutex)
258 {
259         return TryEnterCriticalSection (mutex) != 0 ? 0 : 1;
260 }
261
262 static inline int
263 mono_os_mutex_unlock (mono_mutex_t *mutex)
264 {
265         LeaveCriticalSection (mutex);
266         return 0;
267 }
268
269 static inline int
270 mono_os_cond_init (mono_cond_t *cond)
271 {
272         InitializeConditionVariable (cond);
273         return 0;
274 }
275
276 static inline int
277 mono_os_cond_destroy (mono_cond_t *cond)
278 {
279         /* Beauty of win32 API: do not destroy it */
280         return 0;
281 }
282
283 static inline int
284 mono_os_cond_wait (mono_cond_t *cond, mono_mutex_t *mutex)
285 {
286         return SleepConditionVariableCS (cond, mutex, INFINITE) ? 0 : 1;
287 }
288
289 static inline int
290 mono_os_cond_timedwait (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout_ms)
291 {
292         return SleepConditionVariableCS (cond, mutex, timeout_ms) ? 0 : 1;
293 }
294
295 static inline int
296 mono_os_cond_signal (mono_cond_t *cond)
297 {
298         WakeConditionVariable (cond);
299         return 0;
300 }
301
302 static inline int
303 mono_os_cond_broadcast (mono_cond_t *cond)
304 {
305         WakeAllConditionVariable (cond);
306         return 0;
307 }
308
309 #endif
310
311 G_END_DECLS
312
313 #endif /* __MONO_OS_MUTEX_H__ */