2010-04-06 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / utils / mono-semaphore.c
blobc6bf58885c552ae8a5b31958827aa07c21b71a98
1 /*
2 * mono-semaphore.c: mono-semaphore functions
4 * Author:
5 * Gonzalo Paniagua Javier <gonzalo@novell.com>
7 * (C) 2010 Novell, Inc.
8 */
10 #include <config.h>
11 #include <errno.h>
12 #include "utils/mono-semaphore.h"
13 #ifdef HAVE_SYS_TIME_H
14 #include <sys/time.h>
15 #endif
16 #ifdef HAVE_UNISTD_H
17 #include <unistd.h>
18 #endif
20 #if (defined(HAVE_SEMAPHORE_H) || defined(USE_MACH_SEMA))
21 /* sem_* or semaphore_* functions in use */
22 # ifdef USE_MACH_SEMA
23 # define TIMESPEC mach_timespec_t
24 # define WAIT_BLOCK(a,b) semaphore_timedwait (*(a), *(b))
25 # elif defined(__OpenBSD__)
26 # define TIMESPEC struct timespec
27 # define WAIT_BLOCK(a) sem_trywait(a)
28 # else
29 # define TIMESPEC struct timespec
30 # define WAIT_BLOCK(a,b) sem_timedwait (a, b)
31 # endif
33 int
34 mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, gboolean alertable)
36 TIMESPEC ts, copy;
37 struct timeval t;
38 int res = 0;
39 #if defined(__OpenBSD__)
40 int timeout;
41 #endif
43 #ifndef USE_MACH_SEMA
44 if (timeout_ms == 0)
45 return (!sem_trywait (sem));
46 #endif
47 if (timeout_ms == (guint32) 0xFFFFFFFF)
48 return mono_sem_wait (sem, alertable);
50 gettimeofday (&t, NULL);
51 ts.tv_sec = timeout_ms / 1000 + t.tv_sec;
52 ts.tv_nsec = (timeout_ms % 1000) * 1000000 + t.tv_usec * 1000;
53 while (ts.tv_nsec > 1000000000) {
54 ts.tv_nsec -= 1000000000;
55 ts.tv_sec++;
57 #if defined(__OpenBSD__)
58 timeout = ts.tv_sec;
59 while (timeout) {
60 if ((res = WAIT_BLOCK (sem)) == 0)
61 return res;
63 if (alertable)
64 return -1;
66 usleep (ts.tv_nsec / 1000);
67 timeout--;
69 #else
70 copy = ts;
71 while ((res = WAIT_BLOCK (sem, &ts) == -1) && errno == EINTR) {
72 if (alertable)
73 return -1;
74 ts = copy;
76 #endif
77 return res;
80 int
81 mono_sem_wait (MonoSemType *sem, gboolean alertable)
83 int res;
84 #ifndef USE_MACH_SEMA
85 while ((res = sem_wait (sem) == -1) && errno == EINTR)
86 #else
87 while ((res = semaphore_wait (*sem) == -1) && errno == EINTR)
88 #endif
90 if (alertable)
91 return -1;
93 return res;
96 int
97 mono_sem_post (MonoSemType *sem)
99 int res;
100 #ifndef USE_MACH_SEMA
101 while ((res = sem_post (sem) == -1) && errno == EINTR);
102 #else
103 while ((res = semaphore_signal (*sem) == -1) && errno == EINTR);
104 #endif
105 return res;
108 #else
109 /* Windows or io-layer functions in use */
111 mono_sem_wait (MonoSemType *sem, gboolean alertable)
113 return mono_sem_timedwait (sem, INFINITE, alertable);
117 mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, gboolean alertable)
119 gboolean res;
121 res = WaitForSingleObjectEx (*sem, timeout_ms, alertable);
122 if (!res)
123 return -1;
124 return 0;
128 mono_sem_post (MonoSemType *sem)
130 if (!ReleaseSemaphore (*sem, 1, NULL))
131 return -1;
132 return 0;
134 #endif