2 * mono-semaphore.c: mono-semaphore functions
5 * Gonzalo Paniagua Javier <gonzalo@novell.com>
7 * (C) 2010 Novell, Inc.
12 #include "utils/mono-semaphore.h"
13 #ifdef HAVE_SYS_TIME_H
20 #if (defined (HAVE_SEMAPHORE_H) || defined (USE_MACH_SEMA)) && !defined(HOST_WIN32)
21 /* sem_* or semaphore_* functions in use */
23 # define TIMESPEC mach_timespec_t
24 # define WAIT_BLOCK(a,b) semaphore_timedwait (*(a), *(b))
25 # elif defined(__native_client__) && defined(USE_NEWLIB)
26 # define TIMESPEC struct timespec
27 # define WAIT_BLOCK(a, b) sem_trywait(a)
28 # elif defined(__OpenBSD__)
29 # define TIMESPEC struct timespec
30 # define WAIT_BLOCK(a) sem_trywait(a)
32 # define TIMESPEC struct timespec
33 # define WAIT_BLOCK(a,b) sem_timedwait (a, b)
36 #define NSEC_PER_SEC 1000000000
38 mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, gboolean alertable)
43 #if defined(__OpenBSD__)
49 return sem_trywait (sem);
51 if (timeout_ms == (guint32) 0xFFFFFFFF)
52 return mono_sem_wait (sem, alertable);
55 memset (&t, 0, sizeof (TIMESPEC));
57 gettimeofday (&t, NULL);
59 ts.tv_sec = timeout_ms / 1000 + t.tv_sec;
60 ts.tv_nsec = (timeout_ms % 1000) * 1000000 + t.tv_usec * 1000;
61 while (ts.tv_nsec > NSEC_PER_SEC) {
62 ts.tv_nsec -= NSEC_PER_SEC;
65 #if defined(__OpenBSD__)
68 if ((res = WAIT_BLOCK (sem)) == 0)
74 usleep (ts.tv_nsec / 1000);
79 while ((res = WAIT_BLOCK (sem, &ts)) == -1 && errno == EINTR) {
80 struct timeval current;
84 memset (¤t, 0, sizeof (TIMESPEC));
86 gettimeofday (¤t, NULL);
89 ts.tv_sec -= (current.tv_sec - t.tv_sec);
90 ts.tv_nsec -= (current.tv_usec - t.tv_usec) * 1000;
96 ts.tv_nsec += NSEC_PER_SEC;
105 /* OSX might return > 0 for error */
112 mono_sem_wait (MonoSemType *sem, gboolean alertable)
115 #ifndef USE_MACH_SEMA
116 while ((res = sem_wait (sem)) == -1 && errno == EINTR)
118 while ((res = semaphore_wait (*sem)) == KERN_ABORTED)
124 /* OSX might return > 0 for error */
131 mono_sem_post (MonoSemType *sem)
134 #ifndef USE_MACH_SEMA
135 while ((res = sem_post (sem)) == -1 && errno == EINTR);
137 res = semaphore_signal (*sem);
138 /* OSX might return > 0 for error */
139 if (res != KERN_SUCCESS)
146 /* Windows or io-layer functions in use */
148 mono_sem_wait (MonoSemType *sem, gboolean alertable)
150 return mono_sem_timedwait (sem, INFINITE, alertable);
154 mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, gboolean alertable)
158 while ((res = WaitForSingleObjectEx (*sem, timeout_ms, alertable)) == WAIT_IO_COMPLETION) {
167 // WAIT_TIMEOUT and WAIT_FAILED
174 mono_sem_post (MonoSemType *sem)
176 if (!ReleaseSemaphore (*sem, 1, NULL))