Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
add some thread functions
[simgrid.git] / src / xbt / win_thread.c
index 0e6e3c4..72d1ae8 100644 (file)
@@ -3,6 +3,36 @@
 #include <string.h>
 #include <stdio.h>
 
+
+static win_threads_t __win_threads = NULL;
+
+static win_threads_t
+__win_threads_instance(void);
+
+static int
+__win_threads_attach(win_thread_t thread);
+
+static int
+__win_threads_detach(win_thread_t thread);
+
+static void
+__win_threads_free(void);
+
+static void
+__win_threads_lock(void);
+
+static void
+__win_threads_unlock(void);
+
+static win_thread_t
+__win_thread_self(void);
+
+static int
+__win_thread_key_attach(win_thread_t thread,win_thread_key_t key);
+
+static int
+__win_thread_key_detach(win_thread_t thread,win_thread_key_t key);
+
 int                       
 win_thread_create(win_thread_t* thread,pfn_start_routine_t start_routine,void* param){
 
@@ -11,6 +41,13 @@ win_thread_create(win_thread_t* thread,pfn_start_routine_t start_routine,void* p
        if(!*thread)
                return 1;
                
+       (*thread)->keys = xbt_new0(s_win_thread_keys_t,1);
+       
+       if(!((*thread)->keys)){
+               xbt_free(*thread);
+               return 1;
+       }
+       
        (*thread)->handle = CreateThread(NULL,NULL,start_routine,param,0,&((*thread)->id));
        
        if(!((*thread)->handle)){
@@ -19,28 +56,49 @@ win_thread_create(win_thread_t* thread,pfn_start_routine_t start_routine,void* p
                return 1;
        }
        
+       __win_threads_attach(*thread);
+       
        return 0;       
 }
 
 int
 win_thread_exit(win_thread_t* thread,unsigned long exit_code)
 {
-    win_thread_t ___thread = *thread;
-
+    win_thread_key_t cur,next;
+       win_thread_t ___thread = *thread;
+       
+       __win_threads_detach(*thread);
+       
        CloseHandle(___thread->handle);
-    free(___thread);
+    
+    cur = ___thread->keys->front;
+    
+        while(cur){
+               
+               next = cur->next;
+               
+               if(cur->dstr_func){
+                       
+                       (*(cur->dstr_func))(win_thread_getspecific(cur));
+                       win_thread_key_delete(cur);
+                       
+               }
+               
+               cur = next;
+       }
+       
+       xbt_free(___thread->keys);
+    xbt_free(___thread);
        ___thread = NULL;
-
+       
        ExitThread(exit_code);
 
-
-    
     return 0;
 }
 
-unsigned long
+win_thread_t
 win_thread_self(void){
-       return GetCurrentThreadId();
+       return __win_thread_self();
 }
 
 int
@@ -68,7 +126,7 @@ win_thread_mutex_lock(win_thread_mutex_t* mutex){
 int
 win_thread_mutex_unlock(win_thread_mutex_t* mutex){
 
-       LeaveCriticalSection (&(*mutex)->lock);
+       LeaveCriticalSection (&((*mutex)->lock));
        return 0;               
 }
 
@@ -133,11 +191,11 @@ win_thread_cond_wait(win_thread_cond_t* cond,win_thread_mutex_t* mutex){
         /* lock the threads counter and increment it */
        EnterCriticalSection (&((*cond)->waiters_count_lock));
        (*cond)->waiters_count++;
-       LeaveCriticalSection (&((*cond)->waiters_count_lock));
+       LeaveCriticalSection(&((*cond)->waiters_count_lock));
        
        
         /* unlock the mutex associate with the condition */
-       LeaveCriticalSection (&(*mutex)->lock);
+       LeaveCriticalSection(&(*mutex)->lock);
        
        /* wait for a signal (broadcast or no) */
        wait_result = WaitForMultipleObjects (2, (*cond)->events, FALSE, INFINITE);
@@ -152,7 +210,7 @@ win_thread_cond_wait(win_thread_cond_t* cond,win_thread_mutex_t* mutex){
        /* it's the last waiter or it's a broadcast ? */
        is_last_waiter = ((wait_result == WAIT_OBJECT_0 + BROADCAST - 1) && ((*cond)->waiters_count == 0));
        
-       LeaveCriticalSection (&((*cond)->waiters_count_lock));
+       LeaveCriticalSection(&((*cond)->waiters_count_lock));
        
        /* yes it's the last waiter or it's a broadcast
         * only reset the manual event (the automatic event is reset in the WaitForMultipleObjects() function
@@ -177,7 +235,7 @@ win_thread_cond_signal(win_thread_cond_t* cond)
 
        EnterCriticalSection (&((*cond)->waiters_count_lock));
        have_waiters = (*cond)->waiters_count > 0;
-       LeaveCriticalSection (&((*cond)->waiters_count_lock));
+       LeaveCriticalSection(&((*cond)->waiters_count_lock));
        
        if (have_waiters){
                
@@ -196,7 +254,7 @@ win_thread_cond_broadcast(win_thread_cond_t* cond)
 
        EnterCriticalSection (&((*cond)->waiters_count_lock));
        have_waiters = (*cond)->waiters_count > 0;
-       LeaveCriticalSection (&((*cond)->waiters_count_lock));
+       LeaveCriticalSection(&((*cond)->waiters_count_lock));
        
        if (have_waiters)
                SetEvent((*cond)->events[BROADCAST]);
@@ -232,3 +290,282 @@ win_thread_yield(void)
 }
 
 
+int 
+win_thread_key_create(win_thread_key_t* key, pfn_key_dstr_func_t dstr_func)
+{
+       *key = xbt_new0(s_win_thread_key_t,1);
+       
+       if(!(*key))
+               return 1;
+               
+       if(__win_thread_key_attach(__win_thread_self(),*key){
+               xbt_free(*key);
+               *key = NULL;
+               return 1;
+       }
+       
+       (*key)->value = TlsAlloc();
+       (*key)->dstr_func = dstr_func;
+       
+       return 0; 
+}
+
+int 
+win_thread_key_delete(win_thread_key_t key)
+{
+       void* p;
+       int success;
+       
+       if(!key)
+               return 1;
+               
+       if(!TlsFree(key->value))
+               return 1;
+       
+       success = __win_thread_key_detach(__win_thread_self(),key);
+       
+       xbt_free(key);
+       
+       return success; 
+} 
+
+int 
+win_thread_setspecific(win_thread_key_t key, const void* p)
+{
+       if(!key)
+               return 1;
+               
+       if(!TlsSetValue(key->key,(void*)p))
+               return 1;
+       
+       return 0;
+} 
+
+void* 
+win_thread_getspecific(win_thread_key_t key)
+{
+       if(!key)
+               return NULL;
+               
+       return TlsGetValue(key->value); 
+} 
+
+
+static win_threads_t
+__win_threads_instance(void){
+       
+       if(!__win_threads){
+               __win_threads = xbt_new0(s_win_threads_t,1);
+               
+               if(!__win_threads)
+                       return NULL;
+                       
+               InitializeCriticalSection(&(__win_threads->lock));
+       }
+       
+       return __win_threads;           
+}
+
+static int
+__win_threads_attach(win_thread_t thread)
+{
+       win_thread_entry_t entry;
+       win_threads_t threads;
+       
+       __win_threads_lock();
+       
+       threads = __win_threads_instance();
+       
+       if(!threads){
+               __win_threads_unlock();
+               return 1;
+       }
+       
+               
+       entry = xbt_new0(win_thread_entry_t,1);
+       
+       if(!entry){
+               __win_threads_unlock();
+               return 1;
+       }
+               
+       entry->thread = thread; 
+       
+       if(threads->front){
+               entry->next = threads->front; 
+               threads->front->prev = entry;
+       }
+       
+       threads->front = entry;
+       threads->size++;
+       
+       __win_threads_unlock(); 
+       return 0;       
+}
+
+static int
+__win_threads_detach(win_thread_t thread)
+{
+       win_thread_entry_t cur;
+       win_threads_t threads ;
+       
+       
+       __win_threads_lock();
+       
+       threads = __win_threads_instance();
+       
+       if(!threads){
+               __win_threads_unlock();
+               return 1;
+       }
+       
+       cur = threads->front;
+               
+       while(cur){
+               
+               if(cur->thread == thread){
+                       
+                       if(cur->next)
+                               cur->next->prev = cur->prev;
+                               
+                       if(cur->prev)
+                               cur->prev->next = cur->next;
+                               
+                       xbt_free(cur); 
+                       
+                       threads->size--;
+                       
+                       if(!(threads->size))
+                               __win_threads_free();
+                       else
+                               __win_threads_unlock();
+                               
+                       return 0;
+               }
+               
+               cur = cur->next;
+       }
+       
+       __win_threads_unlock();
+       return 1;
+}
+
+static win_thread_t
+__win_thread_self(void)
+{
+       win_thread_entry_t cur;
+       win_threads_t threads ;
+       win_thread_t thread;
+       unsigned long thread_id;
+       
+       __win_threads_lock();
+       
+       thread_id = GetCurrentThreadId();
+       
+       threads = __win_threads_instance();
+       
+       if(!threads){
+               __win_threads_unlock();
+               return NULL;
+       }
+       
+       cur = threads->front;
+               
+       while(cur){
+               
+               if(cur->thread->id == thread_id){
+                       
+                       thread = cur->thread;
+                       __win_threads_unlock();
+                       return thread;
+               }
+               
+               cur = cur->next;
+       }
+       
+       __win_threads_unlock();
+       return NULL;
+}
+
+static void
+__win_threads_free(void)
+{
+       CRITICAL_SECTION lock;
+       
+       if(__win_threads){
+               lock = __win_threads->lock;
+               free(__win_threads);
+               __win_threads = NULL;
+               LeaveCriticalSection(&lock);
+               DeleteCriticalSection(&lock);   
+       }                       
+}
+
+static void
+__win_threads_lock(void)
+{
+       EnterCriticalSection(&(__win_threads->lock));
+}
+
+static void
+__win_threads_unlock(void)
+{
+       LeaveCriticalSection(&(__win_threads->lock));
+}
+
+static int
+__win_thread_key_attach(win_thread_t thread,win_thread_key_t key)
+{
+       win_thread_keys_t keys;
+       
+       keys = thread->keys;
+       
+       if(!keys)
+               return 1;
+       
+       
+       if(keys->front){
+               key->next = keys->front; 
+               keys->front->prev = key;
+       }
+       
+       keys->front = key;
+       
+       return 0;       
+}
+
+static int
+__win_thread_key_detach(win_thread_t thread,win_thread_key_t key)
+{
+       win_thread_key_t cur;
+       win_thread_keys_t keys ;
+       
+       keys = thread->keys;
+       
+       if(!keys)
+               return 1;
+       
+       cur = keys->front;
+               
+       while(cur){
+               
+               if(cur == key){
+                       
+                       if(cur->next)
+                               cur->next->prev = cur->prev;
+                               
+                       if(cur->prev)
+                               cur->prev->next = cur->next;
+                               
+                       return 0;
+               }
+               
+               cur = cur->next;
+       }
+       
+       return 1;
+}
+
+
+
+