+typedef struct xbt_os_sem_ {
+ HANDLE h;
+ unsigned int value;
+ CRITICAL_SECTION value_lock; /* protect access to value of the semaphore */
+}s_xbt_os_sem_t ;
+
+xbt_os_sem_t
+xbt_os_sem_init(unsigned int value)
+{
+ xbt_os_sem_t res;
+
+ if(value > INT_MAX)
+ THROW1(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))) {
+ THROW1(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)
+ THROW0(arg_error,EINVAL,"Cannot acquire the NULL semaphore");
+
+ /* wait failure */
+ if(WAIT_OBJECT_0 != WaitForSingleObject(sem->h,INFINITE))
+ THROW1(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)
+ THROW0(arg_error,EINVAL,"Cannot acquire the NULL semaphore");
+
+ if (timeout < 0)
+ {
+ xbt_os_sem_acquire(sem);
+ }
+ else
+ {
+
+ 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:
+ THROW2(timeout_error,GetLastError(),"semaphore %p wasn't signaled before timeout (%f)",sem,timeout);
+ return;
+
+ default:
+
+ THROW3(system_error,GetLastError(),"WaitForSingleObject(%p,%f) failed: %s",sem,timeout, strerror(GetLastError()));
+ }
+ }
+}
+
+void
+xbt_os_sem_release(xbt_os_sem_t sem)
+{
+ if(!sem)
+ THROW0(arg_error,EINVAL,"Cannot release the NULL semaphore");
+
+ if(!ReleaseSemaphore(sem->h,1, NULL))
+ THROW1(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) return;
+
+ if(!CloseHandle(sem->h))
+ THROW1(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)
+ THROW0(arg_error,EINVAL,"Cannot get the value of the NULL semaphore");
+
+ EnterCriticalSection(&(sem->value_lock));
+ *svalue = sem->value;
+ LeaveCriticalSection(&(sem->value_lock));
+}
+