New test.
[mono.git] / mono / utils / mono-semaphore.c
1 /*
2  * mono-semaphore.c: mono-semaphore functions
3  *
4  * Author:
5  *      Gonzalo Paniagua Javier  <gonzalo@novell.com>
6  *
7  * (C) 2010 Novell, Inc.
8  */
9
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
17 #if (defined(HAVE_SEMAPHORE_H) || defined(USE_MACH_SEMA)) && !defined(__OpenBSD__)
18 /* sem_* or semaphore_* functions in use */
19 #  ifdef USE_MACH_SEMA
20 #    define TIMESPEC mach_timespec_t
21 #    define WAIT_BLOCK(a,b) semaphore_timedwait (*(a), *(b))
22 #  else
23 #    define TIMESPEC struct timespec
24 #    define WAIT_BLOCK(a,b) sem_timedwait (a, b)
25 #  endif
26
27 int
28 mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms)
29 {
30         TIMESPEC ts, copy;
31         struct timeval t;
32         int res;
33
34 #ifndef USE_MACH_SEMA
35         if (timeout_ms == 0)
36                 return (!sem_trywait (sem));
37 #endif
38         if (timeout_ms == (guint32) 0xFFFFFFFF)
39                 return mono_sem_wait (sem);
40
41         gettimeofday (&t, NULL);
42         ts.tv_sec = timeout_ms / 1000 + t.tv_sec;
43         ts.tv_nsec = (timeout_ms % 1000) * 1000000 + t.tv_usec * 1000;
44         while (ts.tv_nsec > 1000000000) {
45                 ts.tv_nsec -= 1000000000;
46                 ts.tv_sec++;
47         }
48         copy = ts;
49         while ((res = WAIT_BLOCK (sem, &ts) == -1) && errno == EINTR)
50                 ts = copy;
51         return res;
52 }
53
54 int
55 mono_sem_wait (MonoSemType *sem)
56 {
57         int res;
58 #ifndef USE_MACH_SEMA
59         while ((res = sem_wait (sem) == -1) && errno == EINTR);
60 #else
61         while ((res = semaphore_wait (*sem) == -1) && errno == EINTR);
62 #endif
63         return res;
64 }
65
66 int
67 mono_sem_post (MonoSemType *sem)
68 {
69         int res;
70 #ifndef USE_MACH_SEMA
71         while ((res = sem_post (sem) == -1) && errno == EINTR);
72 #else
73         while ((res = semaphore_signal (*sem) == -1) && errno == EINTR);
74 #endif
75         return res;
76 }
77
78 #else
79 /* Windows or io-layer functions in use */
80 int
81 mono_sem_wait (MonoSemType *sem)
82 {
83         return mono_sem_timedwait (sem, INFINITE);
84 }
85
86 int
87 mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms)
88 {
89         gboolean res;
90
91         res = WaitForSingleObjectEx (*sem, timeout_ms, FALSE);
92         if (!res)
93                 return -1;
94         return 0;
95 }
96
97 int
98 mono_sem_post (MonoSemType *sem)
99 {
100         if (!ReleaseSemaphore (*sem, 1, NULL))
101                 return -1;
102         return 0;
103 }
104 #endif
105