1 #include "win_thread.h"
7 static win_threads_t __win_threads = NULL;
10 __win_threads_instance(void);
13 __win_threads_attach(win_thread_t thread);
16 __win_threads_detach(win_thread_t thread);
19 __win_threads_free(void);
22 __win_threads_lock(void);
25 __win_threads_unlock(void);
28 __win_thread_self(void);
31 __win_thread_key_attach(win_thread_t thread,win_thread_key_t key);
34 __win_thread_key_detach(win_thread_t thread,win_thread_key_t key);
37 win_thread_create(win_thread_t* thread,pfn_start_routine_t start_routine,void* param){
39 *thread = xbt_new0(s_win_thread_t,1);
44 (*thread)->keys = xbt_new0(s_win_thread_keys_t,1);
46 if(!((*thread)->keys)){
51 (*thread)->handle = CreateThread(NULL,NULL,start_routine,param,0,&((*thread)->id));
53 if(!((*thread)->handle)){
59 __win_threads_attach(*thread);
65 win_thread_exit(win_thread_t* thread,unsigned long exit_code)
67 win_thread_key_t cur,next;
68 win_thread_t ___thread = *thread;
70 __win_threads_detach(*thread);
72 CloseHandle(___thread->handle);
74 cur = ___thread->keys->front;
82 (*(cur->dstr_func))(win_thread_getspecific(cur));
83 win_thread_key_delete(cur);
90 xbt_free(___thread->keys);
94 ExitThread(exit_code);
100 win_thread_self(void){
101 return __win_thread_self();
105 win_thread_mutex_init(win_thread_mutex_t* mutex)
108 *mutex = xbt_new0(s_win_thread_mutex_t,1);
113 /* initialize the critical section object */
114 InitializeCriticalSection(&((*mutex)->lock));
119 win_thread_mutex_lock(win_thread_mutex_t* mutex){
121 EnterCriticalSection(&((*mutex)->lock));
127 win_thread_mutex_unlock(win_thread_mutex_t* mutex){
129 LeaveCriticalSection (&((*mutex)->lock));
134 win_thread_mutex_destroy(win_thread_mutex_t* mutex){
136 DeleteCriticalSection(&((*mutex)->lock));
145 win_thread_cond_init(win_thread_cond_t* cond){
147 *cond = xbt_new0(s_win_thread_cond_t,1);
152 memset(&((*cond)->waiters_count_lock),0,sizeof(CRITICAL_SECTION));
154 /* initialize the critical section object */
155 InitializeCriticalSection(&((*cond)->waiters_count_lock));
157 (*cond)->waiters_count = 0;
159 /* Create an auto-reset event */
160 (*cond)->events[SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL);
162 if(!(*cond)->events[SIGNAL]){
163 DeleteCriticalSection(&((*cond)->waiters_count_lock));
168 /* Create a manual-reset event. */
169 (*cond)->events[BROADCAST] = CreateEvent (NULL, TRUE, FALSE,NULL);
171 if(!(*cond)->events[BROADCAST]){
173 DeleteCriticalSection(&((*cond)->waiters_count_lock));
175 if(!CloseHandle((*cond)->events[SIGNAL]))
186 win_thread_cond_wait(win_thread_cond_t* cond,win_thread_mutex_t* mutex){
188 unsigned long wait_result;
191 /* lock the threads counter and increment it */
192 EnterCriticalSection (&((*cond)->waiters_count_lock));
193 (*cond)->waiters_count++;
194 LeaveCriticalSection(&((*cond)->waiters_count_lock));
197 /* unlock the mutex associate with the condition */
198 LeaveCriticalSection(&(*mutex)->lock);
200 /* wait for a signal (broadcast or no) */
201 wait_result = WaitForMultipleObjects (2, (*cond)->events, FALSE, INFINITE);
203 if(WAIT_FAILED == wait_result)
206 /* we have a signal lock the condition */
207 EnterCriticalSection (&((*cond)->waiters_count_lock));
208 (*cond)->waiters_count--;
210 /* it's the last waiter or it's a broadcast ? */
211 is_last_waiter = ((wait_result == WAIT_OBJECT_0 + BROADCAST - 1) && ((*cond)->waiters_count == 0));
213 LeaveCriticalSection(&((*cond)->waiters_count_lock));
215 /* yes it's the last waiter or it's a broadcast
216 * only reset the manual event (the automatic event is reset in the WaitForMultipleObjects() function
221 if(!ResetEvent ((*cond)->events[BROADCAST]))
225 /* relock the mutex associated with the condition in accordance with the posix thread specification */
226 EnterCriticalSection (&(*mutex)->lock);
232 win_thread_cond_signal(win_thread_cond_t* cond)
236 EnterCriticalSection (&((*cond)->waiters_count_lock));
237 have_waiters = (*cond)->waiters_count > 0;
238 LeaveCriticalSection(&((*cond)->waiters_count_lock));
242 if(!SetEvent((*cond)->events[SIGNAL]))
251 win_thread_cond_broadcast(win_thread_cond_t* cond)
255 EnterCriticalSection (&((*cond)->waiters_count_lock));
256 have_waiters = (*cond)->waiters_count > 0;
257 LeaveCriticalSection(&((*cond)->waiters_count_lock));
260 SetEvent((*cond)->events[BROADCAST]);
268 win_thread_cond_destroy(win_thread_cond_t* cond)
272 if(!CloseHandle((*cond)->events[SIGNAL]))
275 if(!CloseHandle((*cond)->events[BROADCAST]))
278 DeleteCriticalSection(&((*cond)->waiters_count_lock));
287 win_thread_yield(void)
294 win_thread_key_create(win_thread_key_t* key, pfn_key_dstr_func_t dstr_func)
296 *key = xbt_new0(s_win_thread_key_t,1);
301 if(__win_thread_key_attach(__win_thread_self(),*key){
307 (*key)->value = TlsAlloc();
308 (*key)->dstr_func = dstr_func;
314 win_thread_key_delete(win_thread_key_t key)
322 if(!TlsFree(key->value))
325 success = __win_thread_key_detach(__win_thread_self(),key);
333 win_thread_setspecific(win_thread_key_t key, const void* p)
338 if(!TlsSetValue(key->key,(void*)p))
345 win_thread_getspecific(win_thread_key_t key)
350 return TlsGetValue(key->value);
355 __win_threads_instance(void){
358 __win_threads = xbt_new0(s_win_threads_t,1);
363 InitializeCriticalSection(&(__win_threads->lock));
366 return __win_threads;
370 __win_threads_attach(win_thread_t thread)
372 win_thread_entry_t entry;
373 win_threads_t threads;
375 __win_threads_lock();
377 threads = __win_threads_instance();
380 __win_threads_unlock();
385 entry = xbt_new0(win_thread_entry_t,1);
388 __win_threads_unlock();
392 entry->thread = thread;
395 entry->next = threads->front;
396 threads->front->prev = entry;
399 threads->front = entry;
402 __win_threads_unlock();
407 __win_threads_detach(win_thread_t thread)
409 win_thread_entry_t cur;
410 win_threads_t threads ;
413 __win_threads_lock();
415 threads = __win_threads_instance();
418 __win_threads_unlock();
422 cur = threads->front;
426 if(cur->thread == thread){
429 cur->next->prev = cur->prev;
432 cur->prev->next = cur->next;
439 __win_threads_free();
441 __win_threads_unlock();
449 __win_threads_unlock();
454 __win_thread_self(void)
456 win_thread_entry_t cur;
457 win_threads_t threads ;
459 unsigned long thread_id;
461 __win_threads_lock();
463 thread_id = GetCurrentThreadId();
465 threads = __win_threads_instance();
468 __win_threads_unlock();
472 cur = threads->front;
476 if(cur->thread->id == thread_id){
478 thread = cur->thread;
479 __win_threads_unlock();
486 __win_threads_unlock();
491 __win_threads_free(void)
493 CRITICAL_SECTION lock;
496 lock = __win_threads->lock;
498 __win_threads = NULL;
499 LeaveCriticalSection(&lock);
500 DeleteCriticalSection(&lock);
505 __win_threads_lock(void)
507 EnterCriticalSection(&(__win_threads->lock));
511 __win_threads_unlock(void)
513 LeaveCriticalSection(&(__win_threads->lock));
517 __win_thread_key_attach(win_thread_t thread,win_thread_key_t key)
519 win_thread_keys_t keys;
528 key->next = keys->front;
529 keys->front->prev = key;
538 __win_thread_key_detach(win_thread_t thread,win_thread_key_t key)
540 win_thread_key_t cur;
541 win_thread_keys_t keys ;
555 cur->next->prev = cur->prev;
558 cur->prev->next = cur->next;