+
+xbt_os_sem_t xbt_os_sem_init(unsigned int value)
+{
+ xbt_os_sem_t res;
+
+ if (value > INT_MAX)
+ THROWF(arg_error, value,
+ "Semaphore initial value too big: %ud cannot be stored as a signed int",
+ value);
+
+ res = (xbt_os_sem_t) xbt_new0(s_xbt_os_sem_t, 1);
+
+ if (!(res->h = CreateSemaphore(NULL, value, (long) INT_MAX, NULL))) {
+ THROWF(system_error, GetLastError(), "CreateSemaphore() failed: %s",
+ strerror(GetLastError()));
+ return NULL;
+ }
+
+ res->value = value;
+
+ InitializeCriticalSection(&(res->value_lock));
+
+ return res;
+}
+
+void xbt_os_sem_acquire(xbt_os_sem_t sem)
+{
+ if (!sem)
+ THROWF(arg_error, EINVAL, "Cannot acquire the NULL semaphore");
+
+ /* wait failure */
+ if (WAIT_OBJECT_0 != WaitForSingleObject(sem->h, INFINITE))
+ THROWF(system_error, GetLastError(),
+ "WaitForSingleObject() failed: %s", strerror(GetLastError()));
+ EnterCriticalSection(&(sem->value_lock));
+ sem->value--;
+ LeaveCriticalSection(&(sem->value_lock));
+}
+
+void xbt_os_sem_timedacquire(xbt_os_sem_t sem, double timeout)
+{
+ long seconds;
+ long milliseconds;
+ double end = timeout + xbt_os_time();
+
+ if (!sem)
+ THROWF(arg_error, EINVAL, "Cannot acquire the NULL semaphore");
+
+ if (timeout < 0) {
+ xbt_os_sem_acquire(sem);
+ } else { /* timeout can be zero <-> try acquire ) */
+
+
+ seconds = (long) floor(end);
+ milliseconds = (long) ((end - seconds) * 1000);
+ milliseconds += (seconds * 1000);
+
+ switch (WaitForSingleObject(sem->h, milliseconds)) {
+ case WAIT_OBJECT_0:
+ EnterCriticalSection(&(sem->value_lock));
+ sem->value--;
+ LeaveCriticalSection(&(sem->value_lock));
+ return;
+
+ case WAIT_TIMEOUT:
+ THROWF(timeout_error, GetLastError(),
+ "semaphore %p wasn't signaled before timeout (%f)", sem,
+ timeout);
+ return;
+
+ default:
+ THROWF(system_error, GetLastError(),
+ "WaitForSingleObject(%p,%f) failed: %s", sem, timeout,
+ strerror(GetLastError()));
+ }
+ }
+}
+
+void xbt_os_sem_release(xbt_os_sem_t sem)
+{
+ if (!sem)
+ THROWF(arg_error, EINVAL, "Cannot release the NULL semaphore");
+
+ if (!ReleaseSemaphore(sem->h, 1, NULL))
+ THROWF(system_error, GetLastError(), "ReleaseSemaphore() failed: %s",
+ strerror(GetLastError()));
+ EnterCriticalSection(&(sem->value_lock));
+ sem->value++;
+ LeaveCriticalSection(&(sem->value_lock));
+}
+
+void xbt_os_sem_destroy(xbt_os_sem_t sem)
+{
+ if (!sem)
+ THROWF(arg_error, EINVAL, "Cannot destroy the NULL semaphore");
+
+ if (!CloseHandle(sem->h))
+ THROWF(system_error, GetLastError(), "CloseHandle() failed: %s",
+ strerror(GetLastError()));
+
+ DeleteCriticalSection(&(sem->value_lock));
+
+ xbt_free(sem);
+
+}
+
+void xbt_os_sem_get_value(xbt_os_sem_t sem, int *svalue)
+{
+ if (!sem)
+ THROWF(arg_error, EINVAL,
+ "Cannot get the value of the NULL semaphore");
+
+ EnterCriticalSection(&(sem->value_lock));
+ *svalue = sem->value;
+ LeaveCriticalSection(&(sem->value_lock));
+}
+
+
+#endif
+
+
+/** @brief Returns the amount of cores on the current host */
+int xbt_os_get_numcores(void) {
+#ifdef WIN32
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ return sysinfo.dwNumberOfProcessors;
+#elif MACOS
+ int nm[2];
+ size_t len = 4;
+ uint32_t count;
+
+ nm[0] = CTL_HW; nm[1] = HW_AVAILCPU;
+ sysctl(nm, 2, &count, &len, NULL, 0);
+
+ if(count < 1) {
+ nm[1] = HW_NCPU;
+ sysctl(nm, 2, &count, &len, NULL, 0);
+ if(count < 1) { count = 1; }
+ }
+ return count;
+#else
+ return sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+}
+
+
+/***** reentrant mutexes *****/
+typedef struct xbt_os_rmutex_ {
+ xbt_os_mutex_t mutex;
+ xbt_os_thread_t owner;
+ int count;
+} s_xbt_os_rmutex_t;
+
+void xbt_os_thread_set_extra_data(void *data)
+{
+ xbt_os_thread_self()->extra_data = data;
+}
+
+void *xbt_os_thread_get_extra_data(void)
+{
+ return xbt_os_thread_self()->extra_data;
+}
+
+xbt_os_rmutex_t xbt_os_rmutex_init(void)
+{
+ xbt_os_rmutex_t rmutex = xbt_new0(struct xbt_os_rmutex_, 1);
+ rmutex->mutex = xbt_os_mutex_init();
+ rmutex->owner = NULL;
+ rmutex->count = 0;
+ return rmutex;
+}
+
+void xbt_os_rmutex_acquire(xbt_os_rmutex_t rmutex)
+{
+ xbt_os_thread_t self = xbt_os_thread_self();
+
+ if (self == NULL) {
+ /* the thread module is not initialized yet */
+ rmutex->owner = NULL;
+ return;
+ }
+
+ if (self != rmutex->owner) {
+ xbt_os_mutex_acquire(rmutex->mutex);
+ rmutex->owner = self;
+ rmutex->count = 1;
+ } else {
+ rmutex->count++;
+ }
+}
+
+void xbt_os_rmutex_release(xbt_os_rmutex_t rmutex)
+{
+ if (rmutex->owner == NULL) {
+ /* the thread module was not initialized */
+ return;
+ }
+
+ xbt_assert(rmutex->owner == xbt_os_thread_self());
+
+ if (--rmutex->count == 0) {
+ rmutex->owner = NULL;
+ xbt_os_mutex_release(rmutex->mutex);
+ }
+}
+
+void xbt_os_rmutex_destroy(xbt_os_rmutex_t rmutex)
+{
+ xbt_os_mutex_destroy(rmutex->mutex);
+ xbt_free(rmutex);
+}