X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/007e84eaf7247e8987d9cf6f795cb4a93ea66aa5..079fc72766f21657cb49d9a183f0e35c0223e0f1:/src/xbt/win_thread.c diff --git a/src/xbt/win_thread.c b/src/xbt/win_thread.c index 0e6e3c467c..72d1ae8401 100644 --- a/src/xbt/win_thread.c +++ b/src/xbt/win_thread.c @@ -3,6 +3,36 @@ #include #include + +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; +} + + + +