1 /* xbt_os_thread -- portability layer over the pthread API */
2 /* Used in RL to get win/lin portability, and in SG when CONTEXT_THREAD */
3 /* in SG, when using CONTEXT_UCONTEXT, xbt_os_thread_stub is used instead */
5 /* Copyright (c) 2007, 2008, 2009, 2010. The SimGrid Team.
6 * All rights reserved. */
8 /* This program is free software; you can redistribute it and/or modify it
9 * under the terms of the license (GNU LGPL) which comes with this package. */
11 #include "xbt/sysdep.h"
13 #include "xbt/ex_interface.h" /* We play crude games with exceptions */
15 #include "xbt/xbt_os_time.h" /* Portable time facilities */
16 #include "xbt/xbt_os_thread.h" /* This module */
17 #include "xbt_modinter.h" /* Initialization/finalization of this module */
19 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_sync_os, xbt,
20 "Synchronization mechanism (OS-level)");
22 /* ********************************* PTHREAD IMPLEMENTATION ************************************ */
26 #include <semaphore.h>
28 #ifdef HAVE_MUTEX_TIMEDLOCK
29 /* redefine the function header since we fail to get this from system headers on amd (at least) */
30 int pthread_mutex_timedlock(pthread_mutex_t * mutex,
31 const struct timespec *abs_timeout);
35 /* use named sempahore when sem_init() does not work */
37 static int next_sem_ID = 0;
38 static xbt_os_mutex_t next_sem_ID_lock;
41 typedef struct xbt_os_thread_ {
45 pvoid_f_pvoid_t start_routine;
48 static xbt_os_thread_t main_thread = NULL;
50 /* thread-specific data containing the xbt_os_thread_t structure */
51 static pthread_key_t xbt_self_thread_key;
52 static int thread_mod_inited = 0;
54 /* frees the xbt_os_thread_t corresponding to the current thread */
55 static void xbt_os_thread_free_thread_data(void *d)
60 /* callback: context fetching */
61 static ex_ctx_t *_os_thread_ex_ctx(void)
63 return xbt_os_thread_self()->exception;
66 /* callback: termination */
67 static void _os_thread_ex_terminate(xbt_ex_t * e)
72 /* FIXME: there should be a configuration variable to choose to kill everyone or only this one */
75 void xbt_os_thread_mod_preinit(void)
79 if (thread_mod_inited)
82 if ((errcode = pthread_key_create(&xbt_self_thread_key, NULL)))
83 THROW0(system_error, errcode,
84 "pthread_key_create failed for xbt_self_thread_key");
86 main_thread = xbt_new(s_xbt_os_thread_t, 1);
87 main_thread->name = (char *) "main";
88 main_thread->start_routine = NULL;
89 main_thread->param = NULL;
90 main_thread->exception = xbt_new(ex_ctx_t, 1);
91 XBT_CTX_INITIALIZE(main_thread->exception);
93 __xbt_ex_ctx = _os_thread_ex_ctx;
94 __xbt_ex_terminate = _os_thread_ex_terminate;
96 thread_mod_inited = 1;
99 next_sem_ID_lock = xbt_os_mutex_init();
104 void xbt_os_thread_mod_postexit(void)
106 /* FIXME: don't try to free our key on shutdown.
107 Valgrind detects no leak if we don't, and whine if we try to */
110 // if ((errcode=pthread_key_delete(xbt_self_thread_key)))
111 // THROW0(system_error,errcode,"pthread_key_delete failed for xbt_self_thread_key");
112 free(main_thread->exception);
115 thread_mod_inited = 0;
116 #ifndef HAVE_SEM_WAIT
117 xbt_os_mutex_destroy(next_sem_ID_lock);
120 /* Restore the default exception setup */
121 __xbt_ex_ctx = &__xbt_ex_ctx_default;
122 __xbt_ex_terminate = &__xbt_ex_terminate_default;
125 static void *wrapper_start_routine(void *s)
127 xbt_os_thread_t t = s;
130 if ((errcode = pthread_setspecific(xbt_self_thread_key, t)))
131 THROW0(system_error, errcode,
132 "pthread_setspecific failed for xbt_self_thread_key");
134 return (*(t->start_routine)) (t->param);
137 xbt_os_thread_t xbt_os_thread_create(const char *name,
138 pvoid_f_pvoid_t start_routine,
143 xbt_os_thread_t res_thread = xbt_new(s_xbt_os_thread_t, 1);
144 res_thread->name = xbt_strdup(name);
145 res_thread->start_routine = start_routine;
146 res_thread->param = param;
147 res_thread->exception = xbt_new(ex_ctx_t, 1);
148 XBT_CTX_INITIALIZE(res_thread->exception);
150 if ((errcode = pthread_create(&(res_thread->t), NULL,
151 wrapper_start_routine, res_thread)))
152 THROW1(system_error, errcode,
153 "pthread_create failed: %s", strerror(errcode));
158 const char *xbt_os_thread_name(xbt_os_thread_t t)
163 const char *xbt_os_thread_self_name(void)
165 xbt_os_thread_t me = xbt_os_thread_self();
166 return me ? me->name : "main";
169 void xbt_os_thread_join(xbt_os_thread_t thread, void **thread_return)
174 if ((errcode = pthread_join(thread->t, thread_return)))
175 THROW1(system_error, errcode, "pthread_join failed: %s",
177 if (thread->exception)
178 free(thread->exception);
183 if (thread == main_thread) /* just killed main thread */
189 void xbt_os_thread_exit(int *retval)
191 pthread_exit(retval);
194 xbt_os_thread_t xbt_os_thread_self(void)
198 if (!thread_mod_inited)
201 res = pthread_getspecific(xbt_self_thread_key);
209 void xbt_os_thread_yield(void)
214 void xbt_os_thread_cancel(xbt_os_thread_t t)
216 pthread_cancel(t->t);
219 /****** mutex related functions ******/
220 typedef struct xbt_os_mutex_ {
221 /* KEEP IT IN SYNC WITH xbt_thread.c */
228 xbt_os_mutex_t xbt_os_mutex_init(void)
230 xbt_os_mutex_t res = xbt_new(s_xbt_os_mutex_t, 1);
233 if ((errcode = pthread_mutex_init(&(res->m), NULL)))
234 THROW1(system_error, errcode, "pthread_mutex_init() failed: %s",
240 void xbt_os_mutex_acquire(xbt_os_mutex_t mutex)
244 if ((errcode = pthread_mutex_lock(&(mutex->m))))
245 THROW2(system_error, errcode, "pthread_mutex_lock(%p) failed: %s",
246 mutex, strerror(errcode));
250 void xbt_os_mutex_timedacquire(xbt_os_mutex_t mutex, double delay)
255 xbt_os_mutex_acquire(mutex);
257 } else if (delay == 0) {
258 errcode = pthread_mutex_trylock(&(mutex->m));
264 THROW1(timeout_error, 0, "mutex %p not ready", mutex);
266 THROW2(system_error, errcode,
267 "xbt_mutex_timedacquire(%p) failed: %s", mutex,
274 #ifdef HAVE_MUTEX_TIMEDLOCK
275 struct timespec ts_end;
276 double end = delay + xbt_os_time();
278 ts_end.tv_sec = (time_t) floor(end);
279 ts_end.tv_nsec = (long) ((end - ts_end.tv_sec) * 1000000000);
280 DEBUG2("pthread_mutex_timedlock(%p,%p)", &(mutex->m), &ts_end);
282 errcode = pthread_mutex_timedlock(&(mutex->m), &ts_end);
284 #else /* Well, let's reimplement it since those lazy libc dudes didn't */
285 double start = xbt_os_time();
287 errcode = pthread_mutex_trylock(&(mutex->m));
288 if (errcode == EBUSY)
289 xbt_os_thread_yield();
290 } while (errcode == EBUSY && xbt_os_time() - start < delay);
292 if (errcode == EBUSY)
295 #endif /* HAVE_MUTEX_TIMEDLOCK */
302 THROW2(timeout_error, delay,
303 "mutex %p wasn't signaled before timeout (%f)", mutex, delay);
306 THROW3(system_error, errcode,
307 "pthread_mutex_timedlock(%p,%f) failed: %s", mutex, delay,
313 void xbt_os_mutex_release(xbt_os_mutex_t mutex)
317 if ((errcode = pthread_mutex_unlock(&(mutex->m))))
318 THROW2(system_error, errcode, "pthread_mutex_unlock(%p) failed: %s",
319 mutex, strerror(errcode));
322 void xbt_os_mutex_destroy(xbt_os_mutex_t mutex)
329 if ((errcode = pthread_mutex_destroy(&(mutex->m))))
330 THROW2(system_error, errcode, "pthread_mutex_destroy(%p) failed: %s",
331 mutex, strerror(errcode));
335 /***** condition related functions *****/
336 typedef struct xbt_os_cond_ {
337 /* KEEP IT IN SYNC WITH xbt_thread.c */
341 xbt_os_cond_t xbt_os_cond_init(void)
343 xbt_os_cond_t res = xbt_new(s_xbt_os_cond_t, 1);
345 if ((errcode = pthread_cond_init(&(res->c), NULL)))
346 THROW1(system_error, errcode, "pthread_cond_init() failed: %s",
352 void xbt_os_cond_wait(xbt_os_cond_t cond, xbt_os_mutex_t mutex)
355 if ((errcode = pthread_cond_wait(&(cond->c), &(mutex->m))))
356 THROW3(system_error, errcode, "pthread_cond_wait(%p,%p) failed: %s",
357 cond, mutex, strerror(errcode));
361 void xbt_os_cond_timedwait(xbt_os_cond_t cond, xbt_os_mutex_t mutex,
365 struct timespec ts_end;
366 double end = delay + xbt_os_time();
369 xbt_os_cond_wait(cond, mutex);
371 ts_end.tv_sec = (time_t) floor(end);
372 ts_end.tv_nsec = (long) ((end - ts_end.tv_sec) * 1000000000);
373 DEBUG3("pthread_cond_timedwait(%p,%p,%p)", &(cond->c), &(mutex->m),
376 pthread_cond_timedwait(&(cond->c), &(mutex->m), &ts_end))) {
380 THROW3(timeout_error, errcode,
381 "condition %p (mutex %p) wasn't signaled before timeout (%f)",
384 THROW4(system_error, errcode,
385 "pthread_cond_timedwait(%p,%p,%f) failed: %s", cond, mutex,
386 delay, strerror(errcode));
391 void xbt_os_cond_signal(xbt_os_cond_t cond)
394 if ((errcode = pthread_cond_signal(&(cond->c))))
395 THROW2(system_error, errcode, "pthread_cond_signal(%p) failed: %s",
396 cond, strerror(errcode));
399 void xbt_os_cond_broadcast(xbt_os_cond_t cond)
402 if ((errcode = pthread_cond_broadcast(&(cond->c))))
403 THROW2(system_error, errcode, "pthread_cond_broadcast(%p) failed: %s",
404 cond, strerror(errcode));
407 void xbt_os_cond_destroy(xbt_os_cond_t cond)
414 if ((errcode = pthread_cond_destroy(&(cond->c))))
415 THROW2(system_error, errcode, "pthread_cond_destroy(%p) failed: %s",
416 cond, strerror(errcode));
420 void *xbt_os_thread_getparam(void)
422 xbt_os_thread_t t = xbt_os_thread_self();
423 return t ? t->param : NULL;
426 typedef struct xbt_os_sem_ {
427 #ifndef HAVE_SEM_INIT
435 #define SEM_FAILED (-1)
438 xbt_os_sem_t xbt_os_sem_init(unsigned int value)
440 xbt_os_sem_t res = xbt_new(s_xbt_os_sem_t, 1);
442 /* On some systems (MAC OS X), only the stub of sem_init is to be found.
443 * Any attempt to use it leads to ENOSYS (function not implemented).
444 * If such a prehistoric system is detected, do the job with sem_open instead
447 if (sem_init(&(res->s), 0, value) != 0)
448 THROW1(system_error, errno, "sem_init() failed: %s", strerror(errno));
451 #else /* damn, no sem_init(). Reimplement it */
453 xbt_os_mutex_acquire(next_sem_ID_lock);
454 res->name = bprintf("/%d.%d", (*xbt_getpid) (), ++next_sem_ID);
455 xbt_os_mutex_release(next_sem_ID_lock);
457 res->ps = sem_open(res->name, O_CREAT, 0644, value);
458 if ((res->ps == (sem_t *) SEM_FAILED) && (errno == ENAMETOOLONG)) {
459 /* Old darwins only allow 13 chars. Did you create *that* amount of semaphores? */
460 res->name[13] = '\0';
461 res->ps = sem_open(res->name, O_CREAT, 0644, 1);
463 if ((res->ps == (sem_t *) SEM_FAILED))
464 THROW1(system_error, errno, "sem_open() failed: %s", strerror(errno));
466 /* Remove the name from the semaphore namespace: we never join on it */
467 if (sem_unlink(res->name) < 0)
468 THROW1(system_error, errno, "sem_unlink() failed: %s",
476 void xbt_os_sem_acquire(xbt_os_sem_t sem)
479 THROW0(arg_error, EINVAL, "Cannot acquire of the NULL semaphore");
480 if (sem_wait(sem->ps) < 0)
481 THROW1(system_error, errno, "sem_wait() failed: %s", strerror(errno));
484 void xbt_os_sem_timedacquire(xbt_os_sem_t sem, double delay)
489 THROW0(arg_error, EINVAL, "Cannot acquire of the NULL semaphore");
492 xbt_os_sem_acquire(sem);
493 } else if (delay == 0) {
494 errcode = sem_trywait(sem->ps);
500 THROW1(timeout_error, 0, "semaphore %p not ready", sem);
502 THROW2(system_error, errcode,
503 "xbt_os_sem_timedacquire(%p) failed: %s", sem,
509 struct timespec ts_end;
510 double end = delay + xbt_os_time();
512 ts_end.tv_sec = (time_t) floor(end);
513 ts_end.tv_nsec = (long) ((end - ts_end.tv_sec) * 1000000000);
514 DEBUG2("sem_timedwait(%p,%p)", sem->ps, &ts_end);
515 errcode = sem_timedwait(sem->s, &ts_end);
517 #else /* Okay, reimplement this function then */
518 double start = xbt_os_time();
520 errcode = sem_trywait(sem->ps);
521 if (errcode == EBUSY)
522 xbt_os_thread_yield();
523 } while (errcode == EBUSY && xbt_os_time() - start < delay);
525 if (errcode == EBUSY)
534 THROW2(timeout_error, delay,
535 "semaphore %p wasn't signaled before timeout (%f)", sem,
539 THROW3(system_error, errcode, "sem_timedwait(%p,%f) failed: %s", sem,
540 delay, strerror(errcode));
545 void xbt_os_sem_release(xbt_os_sem_t sem)
548 THROW0(arg_error, EINVAL, "Cannot release of the NULL semaphore");
550 if (sem_post(sem->ps) < 0)
551 THROW1(system_error, errno, "sem_post() failed: %s", strerror(errno));
554 void xbt_os_sem_destroy(xbt_os_sem_t sem)
557 THROW0(arg_error, EINVAL, "Cannot destroy the NULL sempahore");
560 if (sem_destroy(sem->ps) < 0)
561 THROW1(system_error, errno, "sem_destroy() failed: %s",
564 if (sem_close(sem->ps) < 0)
565 THROW1(system_error, errno, "sem_close() failed: %s", strerror(errno));
572 void xbt_os_sem_get_value(xbt_os_sem_t sem, int *svalue)
575 THROW0(arg_error, EINVAL,
576 "Cannot get the value of the NULL semaphore");
578 if (sem_getvalue(&(sem->s), svalue) < 0)
579 THROW1(system_error, errno, "sem_getvalue() failed: %s",
583 /* ********************************* WINDOWS IMPLEMENTATION ************************************ */
585 #elif defined(_XBT_WIN32)
589 typedef struct xbt_os_thread_ {
591 HANDLE handle; /* the win thread handle */
592 unsigned long id; /* the win thread id */
593 pvoid_f_pvoid_t start_routine;
597 /* so we can specify the size of the stack of the threads */
598 #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
599 #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
602 /* the default size of the stack of the threads (in bytes)*/
603 #define XBT_DEFAULT_THREAD_STACK_SIZE 4096
605 /* key to the TLS containing the xbt_os_thread_t structure */
606 static unsigned long xbt_self_thread_key;
608 void xbt_os_thread_mod_preinit(void)
610 xbt_self_thread_key = TlsAlloc();
613 void xbt_os_thread_mod_postexit(void)
616 if (!TlsFree(xbt_self_thread_key))
617 THROW0(system_error, (int) GetLastError(),
618 "TlsFree() failed to cleanup the thread submodule");
621 static DWORD WINAPI wrapper_start_routine(void *s)
623 xbt_os_thread_t t = (xbt_os_thread_t) s;
626 if (!TlsSetValue(xbt_self_thread_key, t))
627 THROW0(system_error, (int) GetLastError(),
628 "TlsSetValue of data describing the created thread failed");
630 rv = (DWORD *) ((t->start_routine) (t->param));
637 xbt_os_thread_t xbt_os_thread_create(const char *name,
638 pvoid_f_pvoid_t start_routine,
642 xbt_os_thread_t t = xbt_new(s_xbt_os_thread_t, 1);
644 t->name = xbt_strdup(name);
645 t->start_routine = start_routine;
648 t->handle = CreateThread(NULL, XBT_DEFAULT_THREAD_STACK_SIZE,
649 (LPTHREAD_START_ROUTINE) wrapper_start_routine,
650 t, STACK_SIZE_PARAM_IS_A_RESERVATION, &(t->id));
654 THROW0(system_error, (int) GetLastError(), "CreateThread failed");
660 const char *xbt_os_thread_name(xbt_os_thread_t t)
665 const char *xbt_os_thread_self_name(void)
667 xbt_os_thread_t t = xbt_os_thread_self();
668 return t ? t->name : "main";
671 void xbt_os_thread_join(xbt_os_thread_t thread, void **thread_return)
674 if (WAIT_OBJECT_0 != WaitForSingleObject(thread->handle, INFINITE))
675 THROW0(system_error, (int) GetLastError(),
676 "WaitForSingleObject failed");
680 if (!GetExitCodeThread(thread->handle, (DWORD *) (*thread_return)))
681 THROW0(system_error, (int) GetLastError(),
682 "GetExitCodeThread failed");
685 CloseHandle(thread->handle);
693 void xbt_os_thread_exit(int *retval)
701 xbt_os_thread_t xbt_os_thread_self(void)
703 return TlsGetValue(xbt_self_thread_key);
706 void *xbt_os_thread_getparam(void)
708 xbt_os_thread_t t = xbt_os_thread_self();
713 void xbt_os_thread_yield(void)
718 void xbt_os_thread_cancel(xbt_os_thread_t t)
720 if (!TerminateThread(t->handle, 0))
721 THROW0(system_error, (int) GetLastError(), "TerminateThread failed");
724 /****** mutex related functions ******/
725 typedef struct xbt_os_mutex_ {
726 /* KEEP IT IN SYNC WITH xbt_thread.c */
727 CRITICAL_SECTION lock;
730 xbt_os_mutex_t xbt_os_mutex_init(void)
732 xbt_os_mutex_t res = xbt_new(s_xbt_os_mutex_t, 1);
734 /* initialize the critical section object */
735 InitializeCriticalSection(&(res->lock));
740 void xbt_os_mutex_acquire(xbt_os_mutex_t mutex)
742 EnterCriticalSection(&mutex->lock);
745 void xbt_os_mutex_timedacquire(xbt_os_mutex_t mutex, double delay)
750 void xbt_os_mutex_release(xbt_os_mutex_t mutex)
753 LeaveCriticalSection(&mutex->lock);
757 void xbt_os_mutex_destroy(xbt_os_mutex_t mutex)
763 DeleteCriticalSection(&mutex->lock);
767 /***** condition related functions *****/
768 enum { /* KEEP IT IN SYNC WITH xbt_thread.c */
774 typedef struct xbt_os_cond_ {
775 /* KEEP IT IN SYNC WITH xbt_thread.c */
776 HANDLE events[MAX_EVENTS];
778 unsigned int waiters_count; /* the number of waiters */
779 CRITICAL_SECTION waiters_count_lock; /* protect access to waiters_count */
782 xbt_os_cond_t xbt_os_cond_init(void)
785 xbt_os_cond_t res = xbt_new0(s_xbt_os_cond_t, 1);
787 memset(&res->waiters_count_lock, 0, sizeof(CRITICAL_SECTION));
789 /* initialize the critical section object */
790 InitializeCriticalSection(&res->waiters_count_lock);
792 res->waiters_count = 0;
794 /* Create an auto-reset event */
795 res->events[SIGNAL] = CreateEvent(NULL, FALSE, FALSE, NULL);
797 if (!res->events[SIGNAL]) {
798 DeleteCriticalSection(&res->waiters_count_lock);
800 THROW0(system_error, 0, "CreateEvent failed for the signals");
803 /* Create a manual-reset event. */
804 res->events[BROADCAST] = CreateEvent(NULL, TRUE, FALSE, NULL);
806 if (!res->events[BROADCAST]) {
808 DeleteCriticalSection(&res->waiters_count_lock);
809 CloseHandle(res->events[SIGNAL]);
811 THROW0(system_error, 0, "CreateEvent failed for the broadcasts");
817 void xbt_os_cond_wait(xbt_os_cond_t cond, xbt_os_mutex_t mutex)
820 unsigned long wait_result;
823 /* lock the threads counter and increment it */
824 EnterCriticalSection(&cond->waiters_count_lock);
825 cond->waiters_count++;
826 LeaveCriticalSection(&cond->waiters_count_lock);
828 /* unlock the mutex associate with the condition */
829 LeaveCriticalSection(&mutex->lock);
831 /* wait for a signal (broadcast or no) */
832 wait_result = WaitForMultipleObjects(2, cond->events, FALSE, INFINITE);
834 if (wait_result == WAIT_FAILED)
835 THROW0(system_error, 0,
836 "WaitForMultipleObjects failed, so we cannot wait on the condition");
838 /* we have a signal lock the condition */
839 EnterCriticalSection(&cond->waiters_count_lock);
840 cond->waiters_count--;
842 /* it's the last waiter or it's a broadcast ? */
843 is_last_waiter = ((wait_result == WAIT_OBJECT_0 + BROADCAST - 1)
844 && (cond->waiters_count == 0));
846 LeaveCriticalSection(&cond->waiters_count_lock);
848 /* yes it's the last waiter or it's a broadcast
849 * only reset the manual event (the automatic event is reset in the WaitForMultipleObjects() function
853 if (!ResetEvent(cond->events[BROADCAST]))
854 THROW0(system_error, 0, "ResetEvent failed");
856 /* relock the mutex associated with the condition in accordance with the posix thread specification */
857 EnterCriticalSection(&mutex->lock);
860 void xbt_os_cond_timedwait(xbt_os_cond_t cond, xbt_os_mutex_t mutex,
864 unsigned long wait_result = WAIT_TIMEOUT;
866 unsigned long end = (unsigned long) (delay * 1000);
870 xbt_os_cond_wait(cond, mutex);
872 DEBUG3("xbt_cond_timedwait(%p,%p,%lu)", &(cond->events),
873 &(mutex->lock), end);
875 /* lock the threads counter and increment it */
876 EnterCriticalSection(&cond->waiters_count_lock);
877 cond->waiters_count++;
878 LeaveCriticalSection(&cond->waiters_count_lock);
880 /* unlock the mutex associate with the condition */
881 LeaveCriticalSection(&mutex->lock);
882 /* wait for a signal (broadcast or no) */
884 wait_result = WaitForMultipleObjects(2, cond->events, FALSE, end);
886 switch (wait_result) {
888 THROW3(timeout_error, GetLastError(),
889 "condition %p (mutex %p) wasn't signaled before timeout (%f)",
892 THROW0(system_error, GetLastError(),
893 "WaitForMultipleObjects failed, so we cannot wait on the condition");
896 /* we have a signal lock the condition */
897 EnterCriticalSection(&cond->waiters_count_lock);
898 cond->waiters_count--;
900 /* it's the last waiter or it's a broadcast ? */
901 is_last_waiter = ((wait_result == WAIT_OBJECT_0 + BROADCAST - 1)
902 && (cond->waiters_count == 0));
904 LeaveCriticalSection(&cond->waiters_count_lock);
906 /* yes it's the last waiter or it's a broadcast
907 * only reset the manual event (the automatic event is reset in the WaitForMultipleObjects() function
911 if (!ResetEvent(cond->events[BROADCAST]))
912 THROW0(system_error, 0, "ResetEvent failed");
914 /* relock the mutex associated with the condition in accordance with the posix thread specification */
915 EnterCriticalSection(&mutex->lock);
917 /*THROW_UNIMPLEMENTED; */
920 void xbt_os_cond_signal(xbt_os_cond_t cond)
924 EnterCriticalSection(&cond->waiters_count_lock);
925 have_waiters = cond->waiters_count > 0;
926 LeaveCriticalSection(&cond->waiters_count_lock);
929 if (!SetEvent(cond->events[SIGNAL]))
930 THROW0(system_error, 0, "SetEvent failed");
932 xbt_os_thread_yield();
935 void xbt_os_cond_broadcast(xbt_os_cond_t cond)
939 EnterCriticalSection(&cond->waiters_count_lock);
940 have_waiters = cond->waiters_count > 0;
941 LeaveCriticalSection(&cond->waiters_count_lock);
944 SetEvent(cond->events[BROADCAST]);
947 void xbt_os_cond_destroy(xbt_os_cond_t cond)
954 if (!CloseHandle(cond->events[SIGNAL]))
957 if (!CloseHandle(cond->events[BROADCAST]))
960 DeleteCriticalSection(&cond->waiters_count_lock);
965 THROW0(system_error, 0, "Error while destroying the condition");
968 typedef struct xbt_os_sem_ {
971 CRITICAL_SECTION value_lock; /* protect access to value of the semaphore */
975 # define INT_MAX 32767 /* let's be safe by underestimating this value: this is for 16bits only */
978 xbt_os_sem_t xbt_os_sem_init(unsigned int value)
983 THROW1(arg_error, value,
984 "Semaphore initial value too big: %ud cannot be stored as a signed int",
987 res = (xbt_os_sem_t) xbt_new0(s_xbt_os_sem_t, 1);
989 if (!(res->h = CreateSemaphore(NULL, value, (long) INT_MAX, NULL))) {
990 THROW1(system_error, GetLastError(), "CreateSemaphore() failed: %s",
991 strerror(GetLastError()));
997 InitializeCriticalSection(&(res->value_lock));
1002 void xbt_os_sem_acquire(xbt_os_sem_t sem)
1005 THROW0(arg_error, EINVAL, "Cannot acquire the NULL semaphore");
1008 if (WAIT_OBJECT_0 != WaitForSingleObject(sem->h, INFINITE))
1009 THROW1(system_error, GetLastError(),
1010 "WaitForSingleObject() failed: %s", strerror(GetLastError()));
1011 EnterCriticalSection(&(sem->value_lock));
1013 LeaveCriticalSection(&(sem->value_lock));
1016 void xbt_os_sem_timedacquire(xbt_os_sem_t sem, double timeout)
1020 double end = timeout + xbt_os_time();
1023 THROW0(arg_error, EINVAL, "Cannot acquire the NULL semaphore");
1026 xbt_os_sem_acquire(sem);
1027 } else { /* timeout can be zero <-> try acquire ) */
1030 seconds = (long) floor(end);
1031 milliseconds = (long) ((end - seconds) * 1000);
1032 milliseconds += (seconds * 1000);
1034 switch (WaitForSingleObject(sem->h, milliseconds)) {
1036 EnterCriticalSection(&(sem->value_lock));
1038 LeaveCriticalSection(&(sem->value_lock));
1042 THROW2(timeout_error, GetLastError(),
1043 "semaphore %p wasn't signaled before timeout (%f)", sem,
1048 THROW3(system_error, GetLastError(),
1049 "WaitForSingleObject(%p,%f) failed: %s", sem, timeout,
1050 strerror(GetLastError()));
1055 void xbt_os_sem_release(xbt_os_sem_t sem)
1058 THROW0(arg_error, EINVAL, "Cannot release the NULL semaphore");
1060 if (!ReleaseSemaphore(sem->h, 1, NULL))
1061 THROW1(system_error, GetLastError(), "ReleaseSemaphore() failed: %s",
1062 strerror(GetLastError()));
1063 EnterCriticalSection(&(sem->value_lock));
1065 LeaveCriticalSection(&(sem->value_lock));
1068 void xbt_os_sem_destroy(xbt_os_sem_t sem)
1071 THROW0(arg_error, EINVAL, "Cannot destroy the NULL semaphore");
1073 if (!CloseHandle(sem->h))
1074 THROW1(system_error, GetLastError(), "CloseHandle() failed: %s",
1075 strerror(GetLastError()));
1077 DeleteCriticalSection(&(sem->value_lock));
1083 void xbt_os_sem_get_value(xbt_os_sem_t sem, int *svalue)
1086 THROW0(arg_error, EINVAL,
1087 "Cannot get the value of the NULL semaphore");
1089 EnterCriticalSection(&(sem->value_lock));
1090 *svalue = sem->value;
1091 LeaveCriticalSection(&(sem->value_lock));