From 079fc72766f21657cb49d9a183f0e35c0223e0f1 Mon Sep 17 00:00:00 2001 From: cherierm Date: Thu, 8 Mar 2007 20:23:04 +0000 Subject: [PATCH] add some thread functions git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@3213 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- src/xbt/win_thread.c | 365 +++++++++++++++++++++++++++++++++++++++++-- src/xbt/win_thread.h | 97 +++++++++++- 2 files changed, 446 insertions(+), 16 deletions(-) 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; +} + + + + diff --git a/src/xbt/win_thread.h b/src/xbt/win_thread.h index f6c47e6d9f..536d2b20c0 100644 --- a/src/xbt/win_thread.h +++ b/src/xbt/win_thread.h @@ -19,15 +19,44 @@ extern "C" { /* type of function pointeur used */ typedef DWORD WINAPI (*pfn_start_routine_t)(void*); +typedef struct s_win_thread_key s_win_thread_key_t,* win_thread_key_t; +typedef struct s_win_thread_keys s_win_thread_keys_t,* win_thread_keys_t; + /* * This structure represents a windows thread. */ typedef struct s_win_thread { HANDLE handle; /* the win thread handle */ - unsigned long id; /* the win thread id */ + unsigned long id; /* the win thread id */ + win_thread_keys_t keys; }s_win_thread_t,* win_thread_t; +struct s_win_thread_keys +{ + win_thread_key_t* keys; + win_thread_key_t front; + win_thread_key_t back; +}; + +typedef struct s_win_thread_entry +{ + HANDLE handle; + win_thread_t thread; + win_thread_t next; + win_thread_t prev; +}s_win_thread_entry_t,win_thread_entry_t; + +typedef struct s_win_threads +{ + win_thread_entry_t* threads; + win_thread_entry_t front; + win_thread_entry_t back; + unsigned int size; + CRITICAL_SECTION lock; +}s_win_threads_t,* win_threads_t; + + /* * This structure simulates a pthread cond. */ @@ -47,6 +76,24 @@ typedef struct s_win_thread_cond CRITICAL_SECTION waiters_count_lock;/* protect access to waiters_count */ }s_win_thread_cond_t,* win_thread_cond_t; + +/* type of pointer function used by the + * win_thread_key_create() function. + */ +typedef void (*pfn_key_dstr_func_t) (void*); + +/* + * This structure represents a windows key + */ +struct s_win_thread_key +{ + unsigned long value; /* the key value */ + pfn_key_dstr_func_t dstr_func; /* the pointer to the destruction function */ + win_thread_key_t next; + win_thread_key_t prev; +}; + + /* * This structure represents a windows mutext * remark : only encapsulate the mutext handle. @@ -83,7 +130,7 @@ win_thread_exit(win_thread_t* thread,unsigned long exit_code); /* * Return the identifier of the current thread. */ -unsigned long +win_thread_t win_thread_self(void); /* @@ -183,6 +230,52 @@ win_thread_cond_destroy(win_thread_cond_t* cond); void win_thread_yield(void); + +/* + * windows thread key connected functions + */ + +/* + * Create a windows thread key. + * @param key The pointer to the key to create. + * @param dstr_func The pointer to the cleanup function. + * @return If successful the function returns .Otherwise + * the function returns 1. + */ +int +win_thread_key_create(win_thread_key_t* key, pfn_key_dstr_func_t dstr_func); +/* + * Destroy a key. + * @param key The key to delete. + * @return If successful the function returns 0. + * Otherwise the function returns 1. + */ +int +win_thread_key_delete(win_thread_key_t key); + +/* + * Update or set the value associated to a key. + * @param key The key concerned by the operation. + * @param value The value to set or update. + * @return If successful the function returns 0. + * Otherwise the function returns 1. + */ +int +win_thread_setspecific(win_thread_key_t key, const void* p); + +/* + * Return the value associated to a key. + * @param key The key concerned by the operation. + * @return If successful the function returns the value. + * Otherwise the function returns NULL. + */ +void* +win_thread_getspecific(win_thread_key_t key); + + + + + #ifdef __cplusplus extern } #endif -- 2.20.1