Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
This is already exported from the corresponding header (include/xbt/ex.h), as it...
[simgrid.git] / src / xbt / win_thread.c
1 #include "win_thread.h"
2
3 #include <string.h>
4 #include <stdio.h>
5
6
7 static win_threads_t __win_threads = NULL;
8
9 static win_threads_t
10 __win_threads_instance(void);
11
12 static int
13 __win_threads_attach(win_thread_t thread);
14
15 static int
16 __win_threads_detach(win_thread_t thread);
17
18 static void
19 __win_threads_free(void);
20
21 static void
22 __win_threads_lock(void);
23
24 static void
25 __win_threads_unlock(void);
26
27 static win_thread_t
28 __win_thread_self(void);
29
30 static int
31 __win_thread_key_attach(win_thread_t thread,win_thread_key_t key);
32
33 static int
34 __win_thread_key_detach(win_thread_t thread,win_thread_key_t key);
35
36 int                       
37 win_thread_create(win_thread_t* thread,pfn_start_routine_t start_routine,void* param){
38
39         *thread = xbt_new0(s_win_thread_t,1);
40         
41         if(!*thread)
42                 return 1;
43                 
44         (*thread)->keys = xbt_new0(s_win_thread_keys_t,1);
45         
46         if(!((*thread)->keys)){
47                 xbt_free(*thread);
48                 return 1;
49         }
50         
51         (*thread)->handle = CreateThread(NULL,NULL,start_routine,param,0,&((*thread)->id));
52         
53         if(!((*thread)->handle)){
54                 xbt_free(*thread);
55                 *thread = NULL;
56                 return 1;
57         }
58         
59         __win_threads_attach(*thread);
60         
61         return 0;       
62 }
63
64 int
65 win_thread_exit(win_thread_t* thread,unsigned long exit_code)
66 {
67     win_thread_key_t cur,next;
68         win_thread_t ___thread = *thread;
69         
70         __win_threads_detach(*thread);
71         
72         CloseHandle(___thread->handle);
73     
74     cur = ___thread->keys->front;
75     
76          while(cur){
77                 
78                 next = cur->next;
79                 
80                 if(cur->dstr_func){
81                         
82                         (*(cur->dstr_func))(win_thread_getspecific(cur));
83                         win_thread_key_delete(cur);
84                         
85                 }
86                 
87                 cur = next;
88         }
89         
90         xbt_free(___thread->keys);
91     xbt_free(___thread);
92         ___thread = NULL;
93         
94         ExitThread(exit_code);
95
96     return 0;
97 }
98
99 win_thread_t
100 win_thread_self(void){
101         return __win_thread_self();
102 }
103
104 int
105 win_thread_mutex_init(win_thread_mutex_t* mutex)
106 {
107
108         *mutex = xbt_new0(s_win_thread_mutex_t,1);
109         
110         if(!*mutex)
111                 return 1;
112                 
113         /* initialize the critical section object */
114         InitializeCriticalSection(&((*mutex)->lock));
115         return 0;
116 }
117
118 int
119 win_thread_mutex_lock(win_thread_mutex_t* mutex){
120
121         EnterCriticalSection(&((*mutex)->lock));
122         
123         return 0;
124 }
125
126 int
127 win_thread_mutex_unlock(win_thread_mutex_t* mutex){
128
129         LeaveCriticalSection (&((*mutex)->lock));
130         return 0;               
131 }
132
133 int
134 win_thread_mutex_destroy(win_thread_mutex_t* mutex){
135
136         DeleteCriticalSection(&((*mutex)->lock));       
137                 
138         free(*mutex);
139         *mutex = NULL;
140         
141         return 0;
142 }
143
144 int
145 win_thread_cond_init(win_thread_cond_t* cond){
146
147         *cond = xbt_new0(s_win_thread_cond_t,1);
148         
149         if(!*cond)
150                 return 1;
151
152         memset(&((*cond)->waiters_count_lock),0,sizeof(CRITICAL_SECTION));
153         
154         /* initialize the critical section object */
155         InitializeCriticalSection(&((*cond)->waiters_count_lock));
156         
157         (*cond)->waiters_count = 0;
158         
159         /* Create an auto-reset event */
160         (*cond)->events[SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL); 
161         
162         if(!(*cond)->events[SIGNAL]){
163                 DeleteCriticalSection(&((*cond)->waiters_count_lock));
164                 free(*cond);
165                 return 1;
166         }
167         
168         /* Create a manual-reset event. */
169         (*cond)->events[BROADCAST] = CreateEvent (NULL, TRUE, FALSE,NULL);
170         
171         if(!(*cond)->events[BROADCAST]){
172                 
173                 DeleteCriticalSection(&((*cond)->waiters_count_lock));
174                 
175                 if(!CloseHandle((*cond)->events[SIGNAL]))
176                         return 1;
177                 
178                 free(*cond);
179                 return 1;
180         }
181
182         return 0;       
183 }
184
185 int
186 win_thread_cond_wait(win_thread_cond_t* cond,win_thread_mutex_t* mutex){
187         
188         unsigned long wait_result;
189         int is_last_waiter;
190
191          /* lock the threads counter and increment it */
192         EnterCriticalSection (&((*cond)->waiters_count_lock));
193         (*cond)->waiters_count++;
194         LeaveCriticalSection(&((*cond)->waiters_count_lock));
195         
196         
197          /* unlock the mutex associate with the condition */
198         LeaveCriticalSection(&(*mutex)->lock);
199         
200         /* wait for a signal (broadcast or no) */
201         wait_result = WaitForMultipleObjects (2, (*cond)->events, FALSE, INFINITE);
202         
203         if(WAIT_FAILED == wait_result)
204                 return 1;
205         
206         /* we have a signal lock the condition */
207         EnterCriticalSection (&((*cond)->waiters_count_lock));
208         (*cond)->waiters_count--;
209         
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));
212         
213         LeaveCriticalSection(&((*cond)->waiters_count_lock));
214         
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
217          * by the système. 
218          */
219         if (is_last_waiter){
220                 
221                 if(!ResetEvent ((*cond)->events[BROADCAST]))
222                         return 1;
223         } 
224         
225         /* relock the mutex associated with the condition in accordance with the posix thread specification */
226         EnterCriticalSection (&(*mutex)->lock);
227
228         return 0;
229 }
230
231 int
232 win_thread_cond_signal(win_thread_cond_t* cond)
233 {
234         int have_waiters;
235
236         EnterCriticalSection (&((*cond)->waiters_count_lock));
237         have_waiters = (*cond)->waiters_count > 0;
238         LeaveCriticalSection(&((*cond)->waiters_count_lock));
239         
240         if (have_waiters){
241                 
242                 if(!SetEvent((*cond)->events[SIGNAL]))
243                         return 1;
244                         
245         }
246         
247         return 0;
248 }
249
250 int 
251 win_thread_cond_broadcast(win_thread_cond_t* cond)
252 {
253         int have_waiters;
254
255         EnterCriticalSection (&((*cond)->waiters_count_lock));
256         have_waiters = (*cond)->waiters_count > 0;
257         LeaveCriticalSection(&((*cond)->waiters_count_lock));
258         
259         if (have_waiters)
260                 SetEvent((*cond)->events[BROADCAST]);
261         
262         return 0;
263 }
264
265
266
267 int
268 win_thread_cond_destroy(win_thread_cond_t* cond)
269 {
270         int result = 0;
271
272         if(!CloseHandle((*cond)->events[SIGNAL]))
273                 result= 1;
274         
275         if(!CloseHandle((*cond)->events[BROADCAST]))
276                 result = 1;
277         
278         DeleteCriticalSection(&((*cond)->waiters_count_lock));  
279         
280         xbt_free(*cond);
281         *cond = NULL;
282         
283         return result;
284 }
285
286 void
287 win_thread_yield(void)
288 {
289     Sleep(0);
290 }
291
292
293 int 
294 win_thread_key_create(win_thread_key_t* key, pfn_key_dstr_func_t dstr_func)
295 {
296         *key = xbt_new0(s_win_thread_key_t,1);
297         
298         if(!(*key))
299                 return 1;
300                 
301         if(__win_thread_key_attach(__win_thread_self(),*key){
302                 xbt_free(*key);
303                 *key = NULL;
304                 return 1;
305         }
306         
307         (*key)->value = TlsAlloc();
308         (*key)->dstr_func = dstr_func;
309         
310         return 0; 
311 }
312
313 int 
314 win_thread_key_delete(win_thread_key_t key)
315 {
316         void* p;
317         int success;
318         
319         if(!key)
320                 return 1;
321                 
322         if(!TlsFree(key->value))
323                 return 1;
324         
325         success = __win_thread_key_detach(__win_thread_self(),key);
326         
327         xbt_free(key);
328         
329         return success; 
330
331
332 int 
333 win_thread_setspecific(win_thread_key_t key, const void* p)
334 {
335         if(!key)
336                 return 1;
337                 
338         if(!TlsSetValue(key->key,(void*)p))
339                 return 1;
340         
341         return 0;
342
343
344 void* 
345 win_thread_getspecific(win_thread_key_t key)
346 {
347         if(!key)
348                 return NULL;
349                 
350         return TlsGetValue(key->value); 
351
352
353
354 static win_threads_t
355 __win_threads_instance(void){
356         
357         if(!__win_threads){
358                 __win_threads = xbt_new0(s_win_threads_t,1);
359                 
360                 if(!__win_threads)
361                         return NULL;
362                         
363                 InitializeCriticalSection(&(__win_threads->lock));
364         }
365         
366         return __win_threads;           
367 }
368
369 static int
370 __win_threads_attach(win_thread_t thread)
371 {
372         win_thread_entry_t entry;
373         win_threads_t threads;
374         
375         __win_threads_lock();
376         
377         threads = __win_threads_instance();
378         
379         if(!threads){
380                 __win_threads_unlock();
381                 return 1;
382         }
383         
384                 
385         entry = xbt_new0(win_thread_entry_t,1);
386         
387         if(!entry){
388                 __win_threads_unlock();
389                 return 1;
390         }
391                 
392         entry->thread = thread; 
393         
394         if(threads->front){
395                 entry->next = threads->front; 
396                 threads->front->prev = entry;
397         }
398         
399         threads->front = entry;
400         threads->size++;
401         
402         __win_threads_unlock(); 
403         return 0;       
404 }
405
406 static int
407 __win_threads_detach(win_thread_t thread)
408 {
409         win_thread_entry_t cur;
410         win_threads_t threads ;
411         
412         
413         __win_threads_lock();
414         
415         threads = __win_threads_instance();
416         
417         if(!threads){
418                 __win_threads_unlock();
419                 return 1;
420         }
421         
422         cur = threads->front;
423                 
424         while(cur){
425                 
426                 if(cur->thread == thread){
427                         
428                         if(cur->next)
429                                 cur->next->prev = cur->prev;
430                                 
431                         if(cur->prev)
432                                 cur->prev->next = cur->next;
433                                 
434                         xbt_free(cur); 
435                         
436                         threads->size--;
437                         
438                         if(!(threads->size))
439                                 __win_threads_free();
440                         else
441                                 __win_threads_unlock();
442                                 
443                         return 0;
444                 }
445                 
446                 cur = cur->next;
447         }
448         
449         __win_threads_unlock();
450         return 1;
451 }
452
453 static win_thread_t
454 __win_thread_self(void)
455 {
456         win_thread_entry_t cur;
457         win_threads_t threads ;
458         win_thread_t thread;
459         unsigned long thread_id;
460         
461         __win_threads_lock();
462         
463         thread_id = GetCurrentThreadId();
464         
465         threads = __win_threads_instance();
466         
467         if(!threads){
468                 __win_threads_unlock();
469                 return NULL;
470         }
471         
472         cur = threads->front;
473                 
474         while(cur){
475                 
476                 if(cur->thread->id == thread_id){
477                         
478                         thread = cur->thread;
479                         __win_threads_unlock();
480                         return thread;
481                 }
482                 
483                 cur = cur->next;
484         }
485         
486         __win_threads_unlock();
487         return NULL;
488 }
489
490 static void
491 __win_threads_free(void)
492 {
493         CRITICAL_SECTION lock;
494         
495         if(__win_threads){
496                 lock = __win_threads->lock;
497                 free(__win_threads);
498                 __win_threads = NULL;
499                 LeaveCriticalSection(&lock);
500                 DeleteCriticalSection(&lock);   
501         }                       
502 }
503
504 static void
505 __win_threads_lock(void)
506 {
507         EnterCriticalSection(&(__win_threads->lock));
508 }
509
510 static void
511 __win_threads_unlock(void)
512 {
513         LeaveCriticalSection(&(__win_threads->lock));
514 }
515
516 static int
517 __win_thread_key_attach(win_thread_t thread,win_thread_key_t key)
518 {
519         win_thread_keys_t keys;
520         
521         keys = thread->keys;
522         
523         if(!keys)
524                 return 1;
525         
526         
527         if(keys->front){
528                 key->next = keys->front; 
529                 keys->front->prev = key;
530         }
531         
532         keys->front = key;
533         
534         return 0;       
535 }
536
537 static int
538 __win_thread_key_detach(win_thread_t thread,win_thread_key_t key)
539 {
540         win_thread_key_t cur;
541         win_thread_keys_t keys ;
542         
543         keys = thread->keys;
544         
545         if(!keys)
546                 return 1;
547         
548         cur = keys->front;
549                 
550         while(cur){
551                 
552                 if(cur == key){
553                         
554                         if(cur->next)
555                                 cur->next->prev = cur->prev;
556                                 
557                         if(cur->prev)
558                                 cur->prev->next = cur->next;
559                                 
560                         return 0;
561                 }
562                 
563                 cur = cur->next;
564         }
565         
566         return 1;
567 }
568
569
570
571