Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Visual C++ already declare the isatty function in io.h. So this change avoids a warni...
[simgrid.git] / src / xbt / xbt_os_thread.c
1 /* $Id$ */
2
3 /* xbt_os_thread -- portability layer over the pthread API                  */
4 /* Used in RL to get win/lin portability, and in SG when CONTEXT_THREAD     */
5 /* in SG, when using CONTEXT_UCONTEXT, xbt_os_thread_stub is used instead   */
6
7 /* Copyright 2006,2007 Malek Cherier, Martin Quinson          
8  * All right reserved.                                                      */
9
10 /* This program is free software; you can redistribute it and/or modify it
11  * under the terms of the license (GNU LGPL) which comes with this package. */
12
13 #include "xbt/sysdep.h"
14 #include "xbt/ex.h"
15 #include "xbt/ex_interface.h" /* We play crude games with exceptions */
16 #include "portable.h"
17 #include "xbt/xbt_os_time.h" /* Portable time facilities */
18 #include "xbt/xbt_os_thread.h" /* This module */
19 #include "xbt_modinter.h" /* Initialization/finalization of this module */
20
21 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_sync_os,xbt,"Synchronization mechanism (OS-level)");
22
23 /* ********************************* PTHREAD IMPLEMENTATION ************************************ */
24 #ifdef HAVE_PTHREAD_H
25 #include <pthread.h>
26 #include <semaphore.h>
27
28 typedef struct xbt_os_thread_ {
29    pthread_t t;
30    char *name;
31    void *param;
32    pvoid_f_pvoid_t start_routine;
33    ex_ctx_t *exception;
34 } s_xbt_os_thread_t ;
35 static xbt_os_thread_t main_thread = NULL;
36
37 /* thread-specific data containing the xbt_os_thread_t structure */
38 static pthread_key_t xbt_self_thread_key;
39 static int thread_mod_inited = 0;
40
41 /* frees the xbt_os_thread_t corresponding to the current thread */
42 static void xbt_os_thread_free_thread_data(void*d){
43    free(d);
44 }
45
46 /* callback: context fetching */
47 static ex_ctx_t *_os_thread_ex_ctx(void) {
48   return xbt_os_thread_self()->exception;
49 }
50
51 /* callback: termination */
52 static void _os_thread_ex_terminate(xbt_ex_t * e) {
53   xbt_ex_display(e);
54
55   abort();
56   /* FIXME: there should be a configuration variable to choose to kill everyone or only this one */
57 }
58
59 void xbt_os_thread_mod_init(void) {
60    int errcode;
61    
62    if (thread_mod_inited)
63      return;
64    
65    if ((errcode=pthread_key_create(&xbt_self_thread_key, NULL)))
66      THROW0(system_error,errcode,"pthread_key_create failed for xbt_self_thread_key");
67
68    main_thread=xbt_new(s_xbt_os_thread_t,1);
69    main_thread->name = (char*)"main";
70    main_thread->start_routine = NULL;
71    main_thread->param = NULL;
72    main_thread->exception = xbt_new(ex_ctx_t, 1);
73    XBT_CTX_INITIALIZE(main_thread->exception);
74
75    __xbt_ex_ctx = _os_thread_ex_ctx;
76    __xbt_ex_terminate = _os_thread_ex_terminate;
77
78    thread_mod_inited = 1;
79 }
80 void xbt_os_thread_mod_exit(void) {
81    /* FIXME: don't try to free our key on shutdown. 
82       Valgrind detects no leak if we don't, and whine if we try to */
83 //   int errcode;
84    
85 //   if ((errcode=pthread_key_delete(xbt_self_thread_key)))
86 //     THROW0(system_error,errcode,"pthread_key_delete failed for xbt_self_thread_key");
87 }
88
89 static void * wrapper_start_routine(void *s) {
90   xbt_os_thread_t t = s;   
91   int errcode;
92
93   if ((errcode=pthread_setspecific(xbt_self_thread_key,t)))
94     THROW0(system_error,errcode,
95            "pthread_setspecific failed for xbt_self_thread_key");   
96    
97   return (*(t->start_routine))(t->param);
98 }
99 xbt_os_thread_t xbt_os_thread_create(const char*name,
100                                      pvoid_f_pvoid_t start_routine,
101                                      void* param)  {
102    int errcode;
103
104    xbt_os_thread_t res_thread=xbt_new(s_xbt_os_thread_t,1);
105    res_thread->name = xbt_strdup(name);
106    res_thread->start_routine = start_routine;
107    res_thread->param = param;
108    res_thread->exception = xbt_new(ex_ctx_t, 1);
109    XBT_CTX_INITIALIZE(res_thread->exception);
110    
111    if ((errcode = pthread_create(&(res_thread->t), NULL, 
112                                  wrapper_start_routine, res_thread)))
113      THROW1(system_error,errcode, 
114             "pthread_create failed: %s",strerror(errcode));
115
116    return res_thread;
117 }
118
119 const char* xbt_os_thread_name(xbt_os_thread_t t) {
120    return t->name;
121 }
122
123 const char* xbt_os_thread_self_name(void) {
124    xbt_os_thread_t self = xbt_os_thread_self();
125    return self?self->name:"main";
126 }
127 void 
128 xbt_os_thread_join(xbt_os_thread_t thread,void ** thread_return) {
129         
130   int errcode;   
131   
132   if ((errcode = pthread_join(thread->t,thread_return)))
133     THROW1(system_error,errcode, "pthread_join failed: %s",
134            strerror(errcode));
135    if (thread->exception)
136      free(thread->exception);
137
138    if (thread == main_thread) /* just killed main thread */
139      main_thread = NULL;
140
141    free(thread);   
142 }                      
143
144 void xbt_os_thread_exit(int *retval) {
145    pthread_exit(retval);
146 }
147
148 xbt_os_thread_t xbt_os_thread_self(void) {
149   xbt_os_thread_t res;
150
151   if (!thread_mod_inited)
152     return NULL;
153   
154   res = pthread_getspecific(xbt_self_thread_key);
155   if (!res)
156     res = main_thread;
157
158   return res;
159 }
160
161 #include <sched.h>
162 void xbt_os_thread_yield(void) {
163    sched_yield();
164 }
165 void xbt_os_thread_cancel(xbt_os_thread_t t) {
166    pthread_cancel(t->t);
167 }
168 /****** mutex related functions ******/
169 typedef struct xbt_os_mutex_ {
170   /* KEEP IT IN SYNC WITH xbt_thread.c */
171    pthread_mutex_t m;
172 } s_xbt_os_mutex_t;
173
174 xbt_os_mutex_t xbt_os_mutex_init(void) {
175    xbt_os_mutex_t res = xbt_new(s_xbt_os_mutex_t,1);
176    int errcode;
177    
178    if ((errcode = pthread_mutex_init(&(res->m),NULL)))
179      THROW1(system_error,errcode,"pthread_mutex_init() failed: %s",
180             strerror(errcode));
181    
182    return res;
183 }
184
185 void xbt_os_mutex_lock(xbt_os_mutex_t mutex) {
186    int errcode;
187    
188    if ((errcode=pthread_mutex_lock(&(mutex->m))))
189      THROW2(system_error,errcode,"pthread_mutex_lock(%p) failed: %s",
190             mutex, strerror(errcode));
191 }
192
193 void xbt_os_mutex_unlock(xbt_os_mutex_t mutex) {
194    int errcode;
195    
196    if ((errcode=pthread_mutex_unlock(&(mutex->m))))
197      THROW2(system_error,errcode,"pthread_mutex_unlock(%p) failed: %s",
198             mutex, strerror(errcode));
199 }
200
201 void xbt_os_mutex_destroy(xbt_os_mutex_t mutex) {
202    int errcode;
203    
204    if (!mutex) return;
205    
206    if ((errcode=pthread_mutex_destroy(&(mutex->m))))
207      THROW2(system_error,errcode,"pthread_mutex_destroy(%p) failed: %s",
208             mutex, strerror(errcode));
209    free(mutex);
210 }
211
212 /***** condition related functions *****/
213 typedef struct xbt_os_cond_ {
214   /* KEEP IT IN SYNC WITH xbt_thread.c */
215    pthread_cond_t c;
216 } s_xbt_os_cond_t;
217
218 xbt_os_cond_t xbt_os_cond_init(void) {
219    xbt_os_cond_t res = xbt_new(s_xbt_os_cond_t,1);
220    int errcode;
221    if ((errcode=pthread_cond_init(&(res->c),NULL)))
222      THROW1(system_error,errcode,"pthread_cond_init() failed: %s",
223             strerror(errcode));
224
225    return res;
226 }
227
228 void xbt_os_cond_wait(xbt_os_cond_t cond, xbt_os_mutex_t mutex) {
229    int errcode;
230    if ((errcode=pthread_cond_wait(&(cond->c),&(mutex->m))))
231      THROW3(system_error,errcode,"pthread_cond_wait(%p,%p) failed: %s",
232             cond,mutex, strerror(errcode));
233 }
234
235 #include <time.h>
236 #include <math.h>
237 void xbt_os_cond_timedwait(xbt_os_cond_t cond, xbt_os_mutex_t mutex, double delay) {
238    int errcode;
239    struct timespec ts_end;
240    double end = delay + xbt_os_time();
241    
242    if (delay < 0) {
243       xbt_os_cond_wait(cond,mutex);
244    } else {
245       ts_end.tv_sec = (time_t) floor(end);
246       ts_end.tv_nsec = (long)  ( ( end - ts_end.tv_sec) * 1000000000);
247       DEBUG3("pthread_cond_timedwait(%p,%p,%p)",&(cond->c),&(mutex->m), &ts_end);
248       switch ( (errcode=pthread_cond_timedwait(&(cond->c),&(mutex->m), &ts_end)) ) {
249        case 0:
250          return;
251        case ETIMEDOUT:
252          THROW3(timeout_error,errcode,"condition %p (mutex %p) wasn't signaled before timeout (%f)",
253                 cond,mutex, delay);
254        default:
255          THROW4(system_error,errcode,"pthread_cond_timedwait(%p,%p,%f) failed: %s",
256                 cond,mutex, delay, strerror(errcode));
257       }   
258    }
259 }
260
261 void xbt_os_cond_signal(xbt_os_cond_t cond) {
262    int errcode;
263    if ((errcode=pthread_cond_signal(&(cond->c))))
264      THROW2(system_error,errcode,"pthread_cond_signal(%p) failed: %s",
265             cond, strerror(errcode));
266 }
267          
268 void xbt_os_cond_broadcast(xbt_os_cond_t cond){
269    int errcode;
270    if ((errcode=pthread_cond_broadcast(&(cond->c))))
271      THROW2(system_error,errcode,"pthread_cond_broadcast(%p) failed: %s",
272             cond, strerror(errcode));
273 }
274 void xbt_os_cond_destroy(xbt_os_cond_t cond){
275    int errcode;
276
277    if (!cond) return;
278
279    if ((errcode=pthread_cond_destroy(&(cond->c))))
280      THROW2(system_error,errcode,"pthread_cond_destroy(%p) failed: %s",
281             cond, strerror(errcode));
282    free(cond);
283 }
284
285 void *xbt_os_thread_getparam(void) {
286    xbt_os_thread_t t = xbt_os_thread_self();
287    return t?t->param:NULL;
288 }
289
290 typedef struct xbt_os_sem_ {
291    sem_t s;
292    int pshared;
293    unsigned int value;
294    const char* name;
295 }s_xbt_os_sem_t ;
296
297 xbt_os_sem_t
298 xbt_os_sem_init(int pshared, unsigned int value)
299 {
300         xbt_os_sem_t res = xbt_new(s_xbt_os_sem_t,1);
301         
302         if(sem_init(&(res->s),pshared,value) < 0)
303                 THROW1(system_error,errno,"sem_init() failed: %s",
304             strerror(errno));
305    
306    res->pshared = pshared;
307    res->value = value;
308    
309    return res;
310 }
311
312 void 
313 xbt_os_sem_wait(xbt_os_sem_t sem)
314 {
315         if(!sem)
316                 THROW1(arg_error,EINVAL,"xbt_os_sem_wait() failed: %s",
317             strerror(EINVAL));
318         
319         if(sem_wait(&(sem->s)) < 0)
320                 THROW1(system_error,errno,"sem_wait() failed: %s",
321             strerror(errno));            
322 }
323
324 void xbt_os_sem_timedwait(xbt_os_sem_t sem,const struct timespec* abs_timeout)
325 {
326         if(!sem)
327                 THROW1(arg_error,EINVAL,"xbt_os_sem_timedwait() failed: %s",
328             strerror(EINVAL));
329         
330         /* only throw an exception if the global variable errno is different than ETIMEDOUT :
331          * (the semaphore could not be locked before the specified timeout expired)
332          */
333         if((sem_timedwait(&(sem->s),abs_timeout) < 0) && (ETIMEDOUT != errno))
334                 THROW1(system_error,errno,"sem_wait() failed: %s",
335             strerror(errno));   
336 }
337
338 void 
339 xbt_os_sem_post(xbt_os_sem_t sem)
340 {
341         if(!sem)
342                 THROW1(arg_error,EINVAL,"xbt_os_sem_post() failed: %s",
343             strerror(EINVAL));
344         
345         if(sem_post(&(sem->s)) < 0)
346                 THROW1(system_error,errno,"sem_post() failed: %s",
347             strerror(errno));            
348 }
349
350 void
351 xbt_os_sem_close(xbt_os_sem_t sem)
352 {
353         if(!sem)
354                 THROW1(arg_error,EINVAL,"xbt_os_sem_close() failed: %s",
355             strerror(EINVAL));
356             
357         if(sem_close(&(sem->s)) < 0)
358                 THROW1(system_error,errno,"sem_close() failed: %s",
359             strerror(errno));
360 }
361
362 xbt_os_sem_t 
363 xbt_os_sem_open(const char *name, int oflag, mode_t mode, unsigned int value)
364 {
365         sem_t* ps;
366         xbt_os_sem_t res = xbt_new(s_xbt_os_sem_t,1);
367         
368         if(SEM_FAILED == (ps = sem_open(name,oflag, mode, value)))
369                 THROW1(system_error,errno,"sem_open() failed: %s",
370             strerror(errno));
371         
372    res->s = *ps;
373    res->value = value;
374    
375    return res;  
376 }
377
378 void
379 xbt_os_sem_destroy(xbt_os_sem_t sem)
380 {
381         if(!sem)
382                 THROW1(arg_error,EINVAL,"xbt_os_sem_destroy() failed: %s",
383             strerror(EINVAL));
384             
385         if(sem_destroy(&(sem->s)) < 0)
386                 THROW1(system_error,errno,"sem_destroy() failed: %s",
387             strerror(errno));
388 }
389
390 void
391 xbt_os_sem_get_value(xbt_os_sem_t sem, int* svalue)
392 {
393         if(!sem)
394                 THROW1(arg_error,EINVAL,"xbt_os_sem_getvalue() failed: %s",
395             strerror(EINVAL));
396             
397         if(sem_getvalue(&(sem->s),svalue) < 0)
398                 THROW1(system_error,errno,"sem_getvalue() failed: %s",
399             strerror(errno));
400 }
401
402 /* ********************************* WINDOWS IMPLEMENTATION ************************************ */
403
404 #elif defined(WIN32)
405
406 typedef struct xbt_os_thread_ {
407   char *name;
408   HANDLE handle;                  /* the win thread handle        */
409   unsigned long id;               /* the win thread id            */
410   pvoid_f_pvoid_t start_routine;
411   void* param;
412 } s_xbt_os_thread_t ;
413
414 /* so we can specify the size of the stack of the threads */
415 #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
416 #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
417 #endif
418
419 /* the default size of the stack of the threads (in bytes)*/
420 #define XBT_DEFAULT_THREAD_STACK_SIZE   4096
421
422 /* key to the TLS containing the xbt_os_thread_t structure */
423 static unsigned long xbt_self_thread_key;
424
425 void xbt_os_thread_mod_init(void) {
426    xbt_self_thread_key = TlsAlloc();
427 }
428 void xbt_os_thread_mod_exit(void) {
429    
430    if (!TlsFree(xbt_self_thread_key)) 
431      THROW0(system_error,(int)GetLastError(),"TlsFree() failed to cleanup the thread submodule");
432 }
433
434 static DWORD WINAPI  wrapper_start_routine(void *s) {
435   xbt_os_thread_t t = (xbt_os_thread_t)s;
436   void* rv;
437  
438     if(!TlsSetValue(xbt_self_thread_key,t))
439      THROW0(system_error,(int)GetLastError(),"TlsSetValue of data describing the created thread failed");
440    
441    rv = (*(t->start_routine))(t->param);
442
443    return *((DWORD*)rv);
444 }
445
446
447 xbt_os_thread_t xbt_os_thread_create(const char *name,pvoid_f_pvoid_t start_routine,
448                                void* param)  {
449    
450    xbt_os_thread_t t = xbt_new(s_xbt_os_thread_t,1);
451
452    t->name = xbt_strdup(name);
453    t->start_routine = start_routine ;
454    t->param = param;
455    
456    t->handle = CreateThread(NULL,XBT_DEFAULT_THREAD_STACK_SIZE,
457                             (LPTHREAD_START_ROUTINE)wrapper_start_routine,
458                             t,STACK_SIZE_PARAM_IS_A_RESERVATION,&(t->id));
459         
460    if(!t->handle) {
461      xbt_free(t);
462      THROW0(system_error,(int)GetLastError(),"CreateThread failed");
463    }
464    
465    return t;
466 }
467
468 const char* xbt_os_thread_name(xbt_os_thread_t t) {
469    return t->name;
470 }
471
472 const char* xbt_os_thread_self_name(void) {
473    xbt_os_thread_t t = xbt_os_thread_self();
474    return t?t->name:"main";
475 }
476
477 void 
478 xbt_os_thread_join(xbt_os_thread_t thread,void ** thread_return) {
479
480         if(WAIT_OBJECT_0 != WaitForSingleObject(thread->handle,INFINITE))  
481                 THROW0(system_error,(int)GetLastError(), "WaitForSingleObject failed");
482                 
483         if(thread_return){
484                 
485                 if(!GetExitCodeThread(thread->handle,(DWORD*)(*thread_return)))
486                         THROW0(system_error,(int)GetLastError(), "GetExitCodeThread failed");
487         }
488         
489         CloseHandle(thread->handle);
490         free(thread->name);
491         free(thread);
492 }
493
494 void xbt_os_thread_exit(int *retval) {
495    if(retval)
496         ExitThread(*retval);
497    else
498         ExitThread(0);
499 }
500
501 xbt_os_thread_t xbt_os_thread_self(void) {
502    return TlsGetValue(xbt_self_thread_key);
503 }
504
505 void *xbt_os_thread_getparam(void) {
506    xbt_os_thread_t t = xbt_os_thread_self();
507    return t->param;
508 }
509
510
511 void xbt_os_thread_yield(void) {
512     Sleep(0);
513 }
514 void xbt_os_thread_cancel(xbt_os_thread_t t) {
515    THROW_UNIMPLEMENTED;
516 }
517
518 /****** mutex related functions ******/
519 typedef struct xbt_os_mutex_ {
520   /* KEEP IT IN SYNC WITH xbt_thread.c */
521    CRITICAL_SECTION lock;   
522 } s_xbt_os_mutex_t;
523
524 xbt_os_mutex_t xbt_os_mutex_init(void) {
525    xbt_os_mutex_t res = xbt_new(s_xbt_os_mutex_t,1);
526
527    /* initialize the critical section object */
528    InitializeCriticalSection(&(res->lock));
529    
530    return res;
531 }
532
533 void xbt_os_mutex_lock(xbt_os_mutex_t mutex) {
534
535    EnterCriticalSection(& mutex->lock);
536 }
537
538 void xbt_os_mutex_unlock(xbt_os_mutex_t mutex) {
539
540    LeaveCriticalSection (& mutex->lock);
541
542 }
543
544 void xbt_os_mutex_destroy(xbt_os_mutex_t mutex) {
545
546    if (!mutex) return;
547    
548    DeleteCriticalSection(& mutex->lock);                
549    free(mutex);
550 }
551
552 /***** condition related functions *****/
553  enum { /* KEEP IT IN SYNC WITH xbt_thread.c */
554     SIGNAL = 0,
555     BROADCAST = 1,
556     MAX_EVENTS = 2
557  };
558
559 typedef struct xbt_os_cond_ {
560   /* KEEP IT IN SYNC WITH xbt_thread.c */
561    HANDLE events[MAX_EVENTS];
562    
563    unsigned int waiters_count;           /* the number of waiters                        */
564    CRITICAL_SECTION waiters_count_lock;  /* protect access to waiters_count  */
565 } s_xbt_os_cond_t;
566
567 xbt_os_cond_t xbt_os_cond_init(void) {
568
569    xbt_os_cond_t res = xbt_new0(s_xbt_os_cond_t,1);
570         
571    memset(& res->waiters_count_lock,0,sizeof(CRITICAL_SECTION));
572         
573    /* initialize the critical section object */
574    InitializeCriticalSection(& res->waiters_count_lock);
575         
576    res->waiters_count = 0;
577         
578    /* Create an auto-reset event */
579    res->events[SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL); 
580         
581    if(!res->events[SIGNAL]){
582       DeleteCriticalSection(& res->waiters_count_lock);
583       free(res);
584       THROW0(system_error,0,"CreateEvent failed for the signals");
585    }
586         
587    /* Create a manual-reset event. */
588    res->events[BROADCAST] = CreateEvent (NULL, TRUE, FALSE,NULL);
589         
590    if(!res->events[BROADCAST]){
591                 
592       DeleteCriticalSection(& res->waiters_count_lock);         
593       CloseHandle(res->events[SIGNAL]);
594       free(res); 
595       THROW0(system_error,0,"CreateEvent failed for the broadcasts");
596    }
597
598    return res;
599 }
600
601 void xbt_os_cond_wait(xbt_os_cond_t cond, xbt_os_mutex_t mutex) {
602         
603    unsigned long wait_result;
604    int is_last_waiter;
605
606    /* lock the threads counter and increment it */
607    EnterCriticalSection (& cond->waiters_count_lock);
608    cond->waiters_count++;
609    LeaveCriticalSection (& cond->waiters_count_lock);
610                 
611    /* unlock the mutex associate with the condition */
612    LeaveCriticalSection (& mutex->lock);
613         
614    /* wait for a signal (broadcast or no) */
615    wait_result = WaitForMultipleObjects (2, cond->events, FALSE, INFINITE);
616         
617    if(wait_result == WAIT_FAILED)
618      THROW0(system_error,0,"WaitForMultipleObjects failed, so we cannot wait on the condition");
619         
620    /* we have a signal lock the condition */
621    EnterCriticalSection (& cond->waiters_count_lock);
622    cond->waiters_count--;
623         
624    /* it's the last waiter or it's a broadcast ? */
625    is_last_waiter = ((wait_result == WAIT_OBJECT_0 + BROADCAST - 1) && (cond->waiters_count == 0));
626         
627    LeaveCriticalSection (& cond->waiters_count_lock);
628         
629    /* yes it's the last waiter or it's a broadcast
630     * only reset the manual event (the automatic event is reset in the WaitForMultipleObjects() function
631     * by the system. 
632     */
633    if (is_last_waiter)
634       if(!ResetEvent (cond->events[BROADCAST]))
635         THROW0(system_error,0,"ResetEvent failed");
636         
637    /* relock the mutex associated with the condition in accordance with the posix thread specification */
638    EnterCriticalSection (& mutex->lock);
639 }
640 void xbt_os_cond_timedwait(xbt_os_cond_t cond, xbt_os_mutex_t mutex, double delay) {
641    
642          unsigned long wait_result = WAIT_TIMEOUT;
643    int is_last_waiter;
644    unsigned long end = (unsigned long)(delay * 1000);
645
646
647    if (delay < 0) {
648       xbt_os_cond_wait(cond,mutex);
649    } else {
650           DEBUG3("xbt_cond_timedwait(%p,%p,%ul)",&(cond->events),&(mutex->lock),end);
651
652    /* lock the threads counter and increment it */
653    EnterCriticalSection (& cond->waiters_count_lock);
654    cond->waiters_count++;
655    LeaveCriticalSection (& cond->waiters_count_lock);
656                 
657    /* unlock the mutex associate with the condition */
658    LeaveCriticalSection (& mutex->lock);
659    /* wait for a signal (broadcast or no) */
660         
661    wait_result = WaitForMultipleObjects (2, cond->events, FALSE, end);
662         
663    switch(wait_result) {
664      case WAIT_TIMEOUT:
665         THROW3(timeout_error,GetLastError(),"condition %p (mutex %p) wasn't signaled before timeout (%f)",cond,mutex, delay);
666         case WAIT_FAILED:
667      THROW0(system_error,GetLastError(),"WaitForMultipleObjects failed, so we cannot wait on the condition");
668    }
669         
670    /* we have a signal lock the condition */
671    EnterCriticalSection (& cond->waiters_count_lock);
672    cond->waiters_count--;
673         
674    /* it's the last waiter or it's a broadcast ? */
675    is_last_waiter = ((wait_result == WAIT_OBJECT_0 + BROADCAST - 1) && (cond->waiters_count == 0));
676         
677    LeaveCriticalSection (& cond->waiters_count_lock);
678         
679    /* yes it's the last waiter or it's a broadcast
680     * only reset the manual event (the automatic event is reset in the WaitForMultipleObjects() function
681     * by the system. 
682     */
683    if (is_last_waiter)
684       if(!ResetEvent (cond->events[BROADCAST]))
685         THROW0(system_error,0,"ResetEvent failed");
686         
687    /* relock the mutex associated with the condition in accordance with the posix thread specification */
688    EnterCriticalSection (& mutex->lock);
689    }
690         /*THROW_UNIMPLEMENTED;*/
691 }
692
693 void xbt_os_cond_signal(xbt_os_cond_t cond) {
694    int have_waiters;
695
696    EnterCriticalSection (& cond->waiters_count_lock);
697    have_waiters = cond->waiters_count > 0;
698    LeaveCriticalSection (& cond->waiters_count_lock);
699         
700    if (have_waiters)
701      if(!SetEvent(cond->events[SIGNAL]))
702        THROW0(system_error,0,"SetEvent failed");
703        
704    xbt_os_thread_yield();
705 }
706
707 void xbt_os_cond_broadcast(xbt_os_cond_t cond){
708    int have_waiters;
709
710    EnterCriticalSection (& cond->waiters_count_lock);
711    have_waiters = cond->waiters_count > 0;
712    LeaveCriticalSection (& cond->waiters_count_lock);
713         
714    if (have_waiters)
715      SetEvent(cond->events[BROADCAST]);
716 }
717
718 void xbt_os_cond_destroy(xbt_os_cond_t cond){
719    int error = 0;
720    
721    if (!cond) return;
722    
723    if(!CloseHandle(cond->events[SIGNAL]))
724      error = 1;
725         
726    if(!CloseHandle(cond->events[BROADCAST]))
727      error = 1;
728         
729    DeleteCriticalSection(& cond->waiters_count_lock);
730         
731    xbt_free(cond);
732    
733    if (error)
734      THROW0(system_error,0,"Error while destroying the condition");
735 }
736
737 typedef struct xbt_os_sem_ {
738    HANDLE h;
739    unsigned int value;
740    const char* name;
741    CRITICAL_SECTION value_lock;  /* protect access to value of the semaphore  */
742 }s_xbt_os_sem_t ;
743
744 xbt_os_sem_t
745 xbt_os_sem_init(int pshared, unsigned int value)
746 {
747         xbt_os_sem_t res;
748         
749         if(0 != pshared)
750         THROW1(arg_error,EPERM,"xbt_os_sem_init() failed: %s",
751             strerror(EPERM));
752             
753         if(value > INT_MAX)
754         THROW1(arg_error,EINVAL,"xbt_os_sem_init() failed: %s",
755             strerror(EINVAL));
756         
757         res = (xbt_os_sem_t)xbt_new0(s_xbt_os_sem_t,1);
758         
759         if(!(res->h = CreateSemaphore(NULL,value,(long)INT_MAX,NULL))) {
760                 THROW1(system_error,GetLastError(),"CreateSemaphore() failed: %s",
761             strerror(GetLastError()));
762             return NULL;
763         }
764   
765         res->value = value;
766         
767         InitializeCriticalSection(&(res->value_lock));
768    
769         return res;
770 }
771
772 void 
773 xbt_os_sem_wait(xbt_os_sem_t sem)
774 {
775         if(!sem)
776                 THROW1(arg_error,EINVAL,"xbt_os_sem_wait() failed: %s",
777             strerror(EINVAL));  
778
779         /* wait failure */
780         if(WAIT_OBJECT_0 != WaitForSingleObject(sem->h,INFINITE))
781                 THROW1(system_error,GetLastError(),"WaitForSingleObject() failed: %s",
782                 strerror(GetLastError()));
783         EnterCriticalSection(&(sem->value_lock));
784         sem->value--;
785         LeaveCriticalSection(&(sem->value_lock));
786 }
787
788 void xbt_os_sem_timedwait(xbt_os_sem_t sem,const struct timespec* abs_timeout)
789 {
790         long timeout;
791         struct timeval tv;
792         
793         if(!sem)
794                 THROW1(arg_error,EINVAL,"xbt_os_sem_timedwait() failed: %s",
795             strerror(EINVAL));  
796             
797         if(!abs_timeout)
798                 timeout = INFINITE;
799         else
800         {
801                 if(gettimeofday(&tv, NULL) < 0) 
802                         THROW1(system_error,errno,"gettimeofday() failed: %s",
803                 strerror(errno));       
804                         
805                  timeout = ((long) (abs_timeout->tv_sec - tv.tv_sec) * 1e3 + (long)((abs_timeout->tv_nsec / 1e3) - tv.tv_usec) / 1e3);          
806         }
807         
808         switch(WaitForSingleObject(sem->h,timeout))
809         {
810                 case WAIT_OBJECT_0:
811                 EnterCriticalSection(&(sem->value_lock));
812                 sem->value--;
813                 LeaveCriticalSection(&(sem->value_lock));
814                 return;
815                 
816                 case WAIT_TIMEOUT:
817                 /* it's not an exception : 
818                  * (semaphore could not be locked before the specified timeout expired)
819                  */
820                 return;
821                 
822                 default:
823                         
824                 THROW1(system_error,GetLastError(),"WaitForSingleObject() failed: %s",
825                 strerror(GetLastError()));
826         }
827 }
828
829 void 
830 xbt_os_sem_post(xbt_os_sem_t sem)
831 {
832         if(!sem)
833                 THROW1(arg_error,EINVAL,"xbt_os_sem_post() failed: %s",
834             strerror(EINVAL));
835         
836         if(!ReleaseSemaphore(sem->h,1, NULL)) 
837                 THROW1(system_error,GetLastError(),"ReleaseSemaphore() failed: %s",
838                 strerror(GetLastError()));
839         EnterCriticalSection (&(sem->value_lock));
840         sem->value++;
841         LeaveCriticalSection(&(sem->value_lock));
842 }
843
844 xbt_os_sem_t 
845 xbt_os_sem_open(const char *name, int oflag, mode_t mode, unsigned int value)
846 {
847         THROW_UNIMPLEMENTED;
848 }
849
850 void
851 xbt_os_sem_close(xbt_os_sem_t sem)
852 {
853         THROW_UNIMPLEMENTED;
854 }
855
856 void
857 xbt_os_sem_destroy(xbt_os_sem_t sem)
858 {
859         if(!sem)
860                 THROW1(arg_error,EINVAL,"xbt_os_sem_destroy() failed: %s",
861             strerror(EINVAL));
862         
863         if(!CloseHandle(sem->h)) 
864                 THROW1(system_error,GetLastError(),"CloseHandle() failed: %s",
865                 strerror(GetLastError()));
866          
867          DeleteCriticalSection(&(sem->value_lock));
868                 
869          xbt_free(sem);     
870                 
871 }
872
873 void
874 xbt_os_sem_get_value(xbt_os_sem_t sem, int* svalue)
875 {
876         if(!sem)
877                 THROW1(arg_error,EINVAL,"xbt_os_sem_get_value() failed: %s",
878             strerror(EINVAL));
879         
880         EnterCriticalSection(&(sem->value_lock));  
881         *svalue = sem->value;
882         LeaveCriticalSection(&(sem->value_lock));
883 }
884
885 #endif