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