2 * semaphores.c: Semaphore handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
13 #ifdef HAVE_SEMAPHORE_H
14 #include <semaphore.h>
20 #include <mono/io-layer/wapi.h>
21 #include <mono/io-layer/wapi-private.h>
22 #include <mono/io-layer/misc-private.h>
23 #include <mono/io-layer/handles-private.h>
24 #include <mono/io-layer/mono-mutex.h>
25 #include <mono/io-layer/semaphore-private.h>
29 static void sema_signal(gpointer handle);
30 static gboolean sema_own (gpointer handle);
32 struct _WapiHandleOps _wapi_sem_ops = {
34 sema_signal, /* signal */
39 void _wapi_sem_details (gpointer handle_info)
41 struct _WapiHandle_sem *sem = (struct _WapiHandle_sem *)handle_info;
43 g_print ("val: %5u, max: %5d", sem->val, sem->max);
46 static mono_once_t sem_ops_once=MONO_ONCE_INIT;
48 static void sem_ops_init (void)
50 _wapi_handle_register_capabilities (WAPI_HANDLE_SEM,
51 WAPI_HANDLE_CAP_WAIT |
52 WAPI_HANDLE_CAP_SIGNAL);
55 static void sema_signal(gpointer handle)
57 ReleaseSemaphore(handle, 1, NULL);
60 static gboolean sema_own (gpointer handle)
62 struct _WapiHandle_sem *sem_handle;
65 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
66 (gpointer *)&sem_handle);
68 g_warning ("%s: error looking up sem handle %p", __func__,
74 g_message("%s: owning sem handle %p", __func__, handle);
80 g_message ("%s: sem %p val now %d", __func__, handle, sem_handle->val);
83 if(sem_handle->val==0) {
84 _wapi_handle_set_signal_state (handle, FALSE, FALSE);
93 * @security: Ignored for now.
94 * @initial: The initial count for the semaphore. The value must be
95 * greater than or equal to zero, and less than or equal to @max.
96 * @max: The maximum count for this semaphore. The value must be
98 * @name: Pointer to a string specifying the name of this semaphore,
99 * or %NULL. Currently ignored.
101 * Creates a new semaphore handle. A semaphore is signalled when its
102 * count is greater than zero, and unsignalled otherwise. The count
103 * is decreased by one whenever a wait function releases a thread that
104 * was waiting for the semaphore. The count is increased by calling
105 * ReleaseSemaphore().
107 * Return value: a new handle, or NULL
109 gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name G_GNUC_UNUSED)
111 struct _WapiHandle_sem sem_handle = {0};
115 mono_once (&sem_ops_once, sem_ops_init);
119 g_message("%s: max <= 0", __func__);
122 SetLastError (ERROR_INVALID_PARAMETER);
126 if(initial>max || initial<0) {
128 g_message("%s: initial>max or < 0", __func__);
131 SetLastError (ERROR_INVALID_PARAMETER);
135 sem_handle.val = initial;
136 sem_handle.max = max;
138 handle = _wapi_handle_new (WAPI_HANDLE_SEM, &sem_handle);
139 if (handle == _WAPI_HANDLE_INVALID) {
140 g_warning ("%s: error creating semaphore handle", __func__);
141 SetLastError (ERROR_GEN_FAILURE);
145 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
147 thr_ret = _wapi_handle_lock_handle (handle);
148 g_assert (thr_ret == 0);
151 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
155 g_message ("%s: Created semaphore handle %p initial %d max %d",
156 __func__, handle, initial, max);
159 thr_ret = _wapi_handle_unlock_handle (handle);
160 g_assert (thr_ret == 0);
161 pthread_cleanup_pop (0);
168 * @handle: The semaphore handle to release.
169 * @count: The amount by which the semaphore's count should be
171 * @prevcount: Pointer to a location to store the previous count of
172 * the semaphore, or %NULL.
174 * Increases the count of semaphore @handle by @count.
176 * Return value: %TRUE on success, %FALSE otherwise.
178 gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
180 struct _WapiHandle_sem *sem_handle;
185 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
186 (gpointer *)&sem_handle);
188 g_warning ("%s: error looking up sem handle %p", __func__,
193 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
195 thr_ret = _wapi_handle_lock_handle (handle);
196 g_assert (thr_ret == 0);
199 g_message("%s: sem %p val %d count %d", __func__, handle,
200 sem_handle->val, count);
203 /* Do this before checking for count overflow, because overflowing max
204 * is a listed technique for finding the current value
206 if(prevcount!=NULL) {
207 *prevcount=sem_handle->val;
210 /* No idea why max is signed, but thats the spec :-( */
211 if(sem_handle->val+count > (guint32)sem_handle->max) {
213 g_message("%s: sem %p max value would be exceeded: max %d current %d count %d", __func__, handle, sem_handle->max, sem_handle->val, count);
219 sem_handle->val+=count;
220 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
225 g_message("%s: sem %p val now %d", __func__, handle, sem_handle->val);
229 thr_ret = _wapi_handle_unlock_handle (handle);
230 g_assert (thr_ret == 0);
231 pthread_cleanup_pop (0);