Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
This is already exported from the corresponding .h (./src/include/surf/surf.h)
[simgrid.git] / src / xbt / xbt_thread.c
index 2ca9e91..024e50f 100644 (file)
@@ -14,6 +14,9 @@
 #include "xbt/xbt_thread.h" /* This module */
 #include "xbt_modinter.h" /* Initialization/finalization of this module */
 
+
+
+/* ********************************* PTHREAD IMPLEMENTATION ************************************ */
 #ifdef HAVE_PTHREAD_H
 #include <pthread.h>
 
@@ -21,23 +24,26 @@ typedef struct xbt_thread_ {
    pthread_t t;
 } s_xbt_thread_t ;
 
+/* thread-specific data containing the xbt_thread_t structure */
+static pthread_key_t xbt_self_thread_key;
+
 /* frees the xbt_thread_t corresponding to the current thread */
 static void xbt_thread_free_thread_data(void*d){
    free(d);
 }
 
-pthread_key_t thread_data; /* thread-specific data containing the xbt_thread_t structure */
 void xbt_thread_mod_init(void) {
    int errcode;
    
-   if ((errcode=pthread_key_create(&thread_data, &xbt_thread_free_thread_data)))
-     THROW0(system_error,errcode,"pthread_key_create failed for thread_data");
+   if ((errcode=pthread_key_create(&xbt_self_thread_key, &xbt_thread_free_thread_data)))
+     THROW0(system_error,errcode,"pthread_key_create failed for xbt_self_thread_key");
 }
 void xbt_thread_mod_exit(void) {
-   int errcode;
+   /* FIXME: don't try to free our key on shutdown. Valgrind detects no leak if we don't, and whine if we try to */
+//   int errcode;
    
-   if ((errcode=pthread_key_delete(thread_data)))
-     THROW0(system_error,errcode,"pthread_key_delete failed for thread_data");
+//   if ((errcode=pthread_key_delete(xbt_self_thread_key)))
+//     THROW0(system_error,errcode,"pthread_key_delete failed for xbt_self_thread_key");
 }
 
 
@@ -46,8 +52,8 @@ xbt_thread_t xbt_thread_create(pvoid_f_pvoid_t start_routine,
    xbt_thread_t res = xbt_new(s_xbt_thread_t,1);
    int errcode;
 
-   if ((errcode=pthread_setspecific(thread_data,res)))
-     THROW0(system_error,errcode,"pthread_setspecific failed for thread_data");
+   if ((errcode=pthread_setspecific(xbt_self_thread_key,res)))
+     THROW0(system_error,errcode,"pthread_setspecific failed for xbt_self_thread_key");
       
    if ((errcode = pthread_create(&(res->t), NULL, start_routine, param)))
      THROW0(system_error,errcode, "pthread_create failed");
@@ -58,7 +64,7 @@ void xbt_thread_exit(int *retval) {
    pthread_exit(retval);
 }
 xbt_thread_t xbt_thread_self(void) {
-   return pthread_getspecific(thread_data);
+   return pthread_getspecific(xbt_self_thread_key);
 }
 
 #include <sched.h>
@@ -97,6 +103,8 @@ void xbt_mutex_unlock(xbt_mutex_t mutex) {
 void xbt_mutex_destroy(xbt_mutex_t mutex) {
    int errcode;
    
+   if (!mutex) return;
+   
    if ((errcode=pthread_mutex_destroy(&(mutex->m))))
      THROW1(system_error,errcode,"pthread_mutex_destroy(%p) failed",mutex);
    free(mutex);
@@ -135,33 +143,52 @@ void xbt_thcond_broadcast(xbt_thcond_t cond){
 }
 void xbt_thcond_destroy(xbt_thcond_t cond){
    int errcode;
+
+   if (!cond) return;
+
    if ((errcode=pthread_cond_destroy(&(cond->c))))
      THROW1(system_error,errcode,"pthread_cond_destroy(%p) failed",cond);
    free(cond);
 }
 
+/* ********************************* WINDOWS IMPLEMENTATION ************************************ */
 
 #elif defined(WIN32)
+
 typedef struct xbt_thread_ {
    HANDLE handle;                  /* the win thread handle        */
    unsigned long id;               /* the win thread id            */
 } s_xbt_thread_t ;
 
-void xbt_thread_mod_init(void) {}
-void xbt_thread_mod_exit(void) {}
+/* key to the TLS containing the xbt_thread_t structure */
+static unsigned long xbt_self_thread_key;
+
+void xbt_thread_mod_init(void) {
+   xbt_self_thread_key = TlsAlloc();
+}
+void xbt_thread_mod_exit(void) {
+   int errcode;
+   if (!(errcode = TlsFree(xbt_self_thread_key))) 
+     THROW0(system_error,errcode,"TlsFree() failed to cleanup the thread submodule");
+}
 
 xbt_thread_t xbt_thread_create(pvoid_f_pvoid_t start_routine,
                               void* param)  {
    
    xbt_thread_t res = xbt_new(s_xbt_thread_t,1);
    
-   res->handle = CreateThread(NULL,NULL,start_routine,param,0,&((*thread)->id));
+   res->handle = CreateThread(NULL,0, 
+                             (LPTHREAD_START_ROUTINE)start_routine,
+                             param,0,& res->id);
        
    if(!res->handle) {
      xbt_free(res);
-     THROW0(system_error,errcode,"CreateThread failed");
+     THROW0(system_error,0,"CreateThread failed");
    }
    
+   if(!TlsSetValue(xbt_self_thread_key,res))
+     THROW0(system_error,0,"TlsSetValue of data describing the created thread failed");
+     
    return res;
 }
 
@@ -175,7 +202,7 @@ void xbt_thread_exit(int *retval) {
 }
 
 xbt_thread_t xbt_thread_self(void) {
-   return GetCurrentThreadId();
+   return TlsGetValue(xbt_self_thread_key);
 }
 
 void xbt_thread_yield(void) {
@@ -209,12 +236,19 @@ void xbt_mutex_unlock(xbt_mutex_t mutex) {
 
 void xbt_mutex_destroy(xbt_mutex_t mutex) {
 
-   DeleteCriticalSection(& mutex->lock);
-               
+   if (!mutex) return;
+   
+   DeleteCriticalSection(& mutex->lock);               
    free(mutex);
 }
 
 /***** condition related functions *****/
+ enum {
+    SIGNAL = 0,
+    BROADCAST = 1,
+    MAX_EVENTS = 2
+ };
+
 typedef struct xbt_thcond_ {
    HANDLE events[MAX_EVENTS];
    
@@ -237,7 +271,7 @@ xbt_thcond_t xbt_thcond_init(void) {
    res->events[SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL); 
        
    if(!res->events[SIGNAL]){
-      DeleteCriticalSection(&((*cond)->waiters_count_lock));
+      DeleteCriticalSection(& res->waiters_count_lock);
       free(res);
       THROW0(system_error,0,"CreateEvent failed for the signals");
    }
@@ -322,6 +356,8 @@ void xbt_thcond_broadcast(xbt_thcond_t cond){
 void xbt_thcond_destroy(xbt_thcond_t cond){
    int error = 0;
    
+   if (!cond) return;
+   
    if(!CloseHandle(cond->events[SIGNAL]))
      error = 1;