+typedef struct xbt_os_sem_ {
+ HANDLE h;
+ unsigned int value;
+ const char* name;
+ CRITICAL_SECTION value_lock; /* protect access to value of the semaphore */
+}s_xbt_os_sem_t ;
+
+xbt_os_sem_t
+xbt_os_sem_init(int pshared, unsigned int value)
+{
+ xbt_os_sem_t res;
+
+ if(0 != pshared)
+ THROW1(arg_error,EPERM,"xbt_os_sem_init() failed: %s",
+ strerror(EPERM));
+
+ if(value > INT_MAX)
+ THROW1(arg_error,EINVAL,"xbt_os_sem_init() failed: %s",
+ strerror(EINVAL));
+
+ 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_wait(xbt_os_sem_t sem)
+{
+ if(!sem)
+ THROW1(arg_error,EINVAL,"xbt_os_sem_wait() failed: %s",
+ strerror(EINVAL));
+
+ /* 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_timedwait(xbt_os_sem_t sem,const struct timespec* abs_timeout)
+{
+ long timeout;
+ struct timeval tv;
+
+ if(!sem)
+ THROW1(arg_error,EINVAL,"xbt_os_sem_timedwait() failed: %s",
+ strerror(EINVAL));
+
+ if(!abs_timeout)
+ timeout = INFINITE;
+ else
+ {
+ if(gettimeofday(&tv, NULL) < 0)
+ THROW1(system_error,errno,"gettimeofday() failed: %s",
+ strerror(errno));
+
+ timeout = ((long) (abs_timeout->tv_sec - tv.tv_sec) * 1e3 + (long)((abs_timeout->tv_nsec / 1e3) - tv.tv_usec) / 1e3);
+ }
+
+ switch(WaitForSingleObject(sem->h,timeout))
+ {
+ case WAIT_OBJECT_0:
+ EnterCriticalSection(&(sem->value_lock));
+ sem->value--;
+ LeaveCriticalSection(&(sem->value_lock));
+ return;
+
+ case WAIT_TIMEOUT:
+ /* it's not an exception :
+ * (semaphore could not be locked before the specified timeout expired)
+ */
+ return;
+
+ default:
+
+ THROW1(system_error,GetLastError(),"WaitForSingleObject() failed: %s",
+ strerror(GetLastError()));
+ }
+}
+
+void
+xbt_os_sem_post(xbt_os_sem_t sem)
+{
+ if(!sem)
+ THROW1(arg_error,EINVAL,"xbt_os_sem_post() failed: %s",
+ strerror(EINVAL));
+
+ 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));
+}
+
+xbt_os_sem_t
+xbt_os_sem_open(const char *name, int oflag, mode_t mode, unsigned int value)
+{
+ THROW_UNIMPLEMENTED;
+}
+
+void
+xbt_os_sem_close(xbt_os_sem_t sem)
+{
+ THROW_UNIMPLEMENTED;
+}
+
+void
+xbt_os_sem_destroy(xbt_os_sem_t sem)
+{
+ if(!sem)
+ THROW1(arg_error,EINVAL,"xbt_os_sem_destroy() failed: %s",
+ strerror(EINVAL));
+
+ 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)
+ THROW1(arg_error,EINVAL,"xbt_os_sem_get_value() failed: %s",
+ strerror(EINVAL));
+
+ EnterCriticalSection(&(sem->value_lock));
+ *svalue = sem->value;
+ LeaveCriticalSection(&(sem->value_lock));
+}
+