Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Kill the s_xbt_thread_wrapper_for_restart__ structure and use xbt_thread_t to contain...
[simgrid.git] / src / xbt / xbt_thread.c
index adf3da7..3a6d8d0 100644 (file)
@@ -22,6 +22,8 @@
 
 typedef struct xbt_thread_ {
    pthread_t t;
+   void *param;
+   pvoid_f_pvoid_t *start_routine;
 } s_xbt_thread_t ;
 
 /* thread-specific data containing the xbt_thread_t structure */
@@ -35,33 +37,54 @@ static void xbt_thread_free_thread_data(void*d){
 void xbt_thread_mod_init(void) {
    int errcode;
    
-   if ((errcode=pthread_key_create(&xbt_self_thread_key, &xbt_thread_free_thread_data)))
+   if ((errcode=pthread_key_create(&xbt_self_thread_key, NULL)))
      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(xbt_self_thread_key)))
-     THROW0(system_error,errcode,"pthread_key_delete failed for xbt_self_thread_key");
+//   if ((errcode=pthread_key_delete(xbt_self_thread_key)))
+//     THROW0(system_error,errcode,"pthread_key_delete failed for xbt_self_thread_key");
 }
 
+static void * wrapper_start_routine(void *s) {
+  xbt_thread_t t = s;   
+  int errcode;
+
+  if ((errcode=pthread_setspecific(xbt_self_thread_key,t)))
+    THROW0(system_error,errcode,"pthread_setspecific failed for xbt_self_thread_key");   
+  return t->start_routine(t->param);
+}
 
 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);
    int errcode;
 
-   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");
+   xbt_thread_t res_thread=xbt_new(s_xbt_thread_t,1);
+   res_thread->start_routine = start_routine;
+   res_thread->param = param;
+
    
-   return res;
+   if ((errcode = pthread_create(&(res_thread->t), NULL, wrapper_start_routine, res_thread)))
+     THROW0(system_error,errcode, "pthread_create failed");
+
+   return res_thread;
+}
+
+void 
+xbt_thread_join(xbt_thread_t thread,void ** thread_return) {
+       
+       int errcode;   
+       
+       if ((errcode = pthread_join(thread->t,thread_return)))
+               THROW0(system_error,errcode, "pthread_join failed");
 }                     
+
 void xbt_thread_exit(int *retval) {
    pthread_exit(retval);
 }
+
 xbt_thread_t xbt_thread_self(void) {
    return pthread_getspecific(xbt_self_thread_key);
 }
@@ -102,6 +125,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);
@@ -140,6 +165,9 @@ 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);
@@ -154,6 +182,12 @@ typedef struct xbt_thread_ {
    unsigned long id;               /* the win thread id            */
 } s_xbt_thread_t ;
 
+typedef struct s_xbt_thread_wrapper_for_restart__ {
+  pvoid_f_pvoid_t *start_routine;
+  void* param;
+  xbt_thread_t res;
+} s_xbt_thread_wrapper_for_restart_t, *xbt_thread_wrapper_for_restart_t;
+
 /* key to the TLS containing the xbt_thread_t structure */
 static unsigned long xbt_self_thread_key;
 
@@ -161,38 +195,65 @@ 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");
+   
+   if (!TlsFree(xbt_self_thread_key)) 
+     THROW0(system_error,(int)GetLastError(),"TlsFree() failed to cleanup the thread submodule");
 }
 
+DWORD WINAPI  wrapper_start_routine(void *s) {
+  xbt_thread_wrapper_for_restart_t stub = (xbt_thread_wrapper_for_restart_t)s;
+    if(!TlsSetValue(xbt_self_thread_key,stub->res))
+     THROW0(system_error,(int)GetLastError(),"TlsSetValue of data describing the created thread failed");
+   
+   return (DWORD)stub->start_routine(stub->param);
+}
+
+
 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);
+   xbt_thread_wrapper_for_restart_t stub = xbt_new0(s_xbt_thread_wrapper_for_restart_t,1);
+
+   stub->start_routine = start_routine ;
+   stub->param = param;
+   stub->res = xbt_new(s_xbt_thread_t,1);
    
-   res->handle = CreateThread(NULL,0, 
-                             (LPTHREAD_START_ROUTINE)start_routine,
-                             param,0,& res->id);
+   stub->res->handle = CreateThread(NULL,0,
+                             (LPTHREAD_START_ROUTINE)wrapper_start_routine,
+                             stub,0,&(stub->res->id));
        
-   if(!res->handle) {
-     xbt_free(res);
-     THROW0(system_error,0,"CreateThread failed");
+   if(!stub->res->handle) {
+     xbt_free(stub->res);
+     THROW0(system_error,(int)GetLastError(),"CreateThread failed");
    }
    
-   if(!TlsSetValue(xbt_self_thread_key,res))
-     THROW0(system_error,0,"TlsSetValue of data describing the created thread failed");
-     
-   return res;
+   return stub->res;
+}
+
+void 
+xbt_thread_join(xbt_thread_t thread,void ** thread_return) {
+
+       if(WAIT_OBJECT_0 != WaitForSingleObject(thread->handle,INFINITE))  
+               THROW0(system_error,(int)GetLastError(), "WaitForSingleObject failed");
+               
+       if(thread_return){
+               
+               if(!GetExitCodeThread(thread->handle,(DWORD*)(*thread_return)))
+                       THROW0(system_error,(int)GetLastError(), "GetExitCodeThread failed");
+       }
+       
+       CloseHandle(thread->handle);
 }
 
 void xbt_thread_exit(int *retval) {
-   xbt_thread_t self = xbt_thread_self();
    
-   CloseHandle(self->handle);
-   free(self);
+   xbt_thread_t self = xbt_thread_self();
    
-   ExitThread(*retval);
+   if(retval)
+       ExitThread(*retval);
+   else
+       ExitThread(0);
 }
 
 xbt_thread_t xbt_thread_self(void) {
@@ -230,8 +291,9 @@ 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);
 }
 
@@ -349,6 +411,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;