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