name-event-objects-20040301
[openafs.git] / src / WINNT / pthread / pthread.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * This file contains a skeleton pthread implementation for NT.
12  * This is not intended to be a fully compliant pthread implementation
13  * The purpose of this file is to only implement those functions that
14  * are truly needed to support the afs code base.
15  *
16  * A secondary goal is to allow a "real" pthread implementation to 
17  * replace this file without any modification to code that depends upon
18  * this file
19  *
20  * The function signatures and argument types are meant to be the same
21  * as their UNIX prototypes.
22  * Where possible, the POSIX specified return values are used.
23  * For situations where an error can occur, but no corresponding
24  * POSIX error value exists, unique (within a given function) negative 
25  * numbers are used for errors to avoid collsions with the errno
26  * style values.
27  */
28
29 #include <afs/param.h>
30 #include <afs/stds.h>
31
32 #include <pthread.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <sys/timeb.h>
38
39 #define PTHREAD_EXIT_EXCEPTION 0x1
40
41 /*
42  * Posix threads uses static initialization for pthread_once control
43  * objects, and under NT, every sophisticated synchronization primitive
44  * uses procedural initialization.  This forces the use of CompareExchange
45  * (aka test and set) and busy waiting for threads that compete to run
46  * a pthread_once'd function.  We make these "busy" threads give up their
47  * timeslice - which should cause acceptable behavior on a single processor
48  * machine, but on a multiprocessor machine this could very well result
49  * in busy waiting.
50  */
51
52 int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) {
53     int rc = 0;
54
55     if ((once_control != NULL) && (init_routine != NULL)) {
56         if (InterlockedExchange((LPLONG)&once_control->call_started,
57                                 (LONG) 1) == 0) {
58             (*init_routine)();
59             once_control->call_running = 0;
60         } else {
61             /* use Sleep() since SwitchToThread() not available on Win95 */
62             while(once_control->call_running) Sleep(20);
63         }
64     } else {
65         rc = EINVAL;
66     }
67     return rc;
68 }
69
70 /*
71  * For now only support PTHREAD_PROCESS_PRIVATE mutexes.
72  * if PTHREAD_PROCESS_SHARED are required later they can be added
73  */
74
75 int pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *attr) {
76     int rc = 0;
77
78     if ((mp != NULL) && (attr == NULL)) {
79         InitializeCriticalSection(&mp->cs);
80         mp->isLocked = 0;
81         mp->tid = 0;
82     } else {
83         rc = EINVAL;
84     }
85     return rc;
86 }
87
88 /*
89  * Under NT, critical sections can be locked recursively by the owning
90  * thread.  This is opposite of the pthread spec, and so we keep track
91  * of the thread that has locked a critical section.  If the same thread
92  * tries to lock a critical section more than once we fail.
93  */
94 int pthread_mutex_trylock(pthread_mutex_t *mp) {
95     int rc = 0;
96
97 #ifdef AFS_WIN95_ENV
98     /* TryEnterCriticalSection() not available on Win95, so just wait for
99      * the lock.  Correct code generally can't depend on how long the
100      * function takes to return, so the only code that will be broken is
101      * that for which 1) the mutex *mp is obtained and never released or
102      * 2) the mutex *mp is intentionally held until trylock() returns.
103      * These cases are unusual and don't appear in normal (non-test) AFS
104      * code; furthermore, we can reduce (but not eliminate!) the problem by
105      * sneaking a look at isLocked even though we don't hold the
106      * CRITICAL_SECTION in mutex *mp and are thus vulnerable to race
107      * conditions.  Note that self-deadlock isn't a problem since
108      * CRITICAL_SECTION objects are recursive.
109      *
110      * Given the very restricted usage of the pthread library on Windows 95,
111      * we can live with these limitations.
112      */
113     if (mp != NULL) {
114         if (mp->isLocked) {
115             rc = EBUSY;
116         } else {
117             rc = pthread_mutex_lock(mp);
118         }
119     } else {
120         rc = EINVAL;
121     }
122 #else
123     /* TryEnterCriticalSection() provided on other MS platforms of interest */
124     if (mp != NULL) {
125         if (TryEnterCriticalSection(&mp->cs)) {
126             if (mp->isLocked) {
127                 /* same thread tried to recursively lock, fail */
128                 LeaveCriticalSection(&mp->cs);
129                 rc = EBUSY;
130             } else {
131                 mp->isLocked = 1;
132                 mp->tid = GetCurrentThreadId();
133                 rc = 0;
134             }
135         } else {
136             rc = EBUSY;
137         }
138     } else {
139         rc = EINVAL;
140     }
141 #endif /* AFS_WIN95_ENV */
142
143     return rc;
144 }
145
146
147 int pthread_mutex_lock(pthread_mutex_t *mp) {
148     int rc = 0;
149
150     if (mp != NULL) {
151         EnterCriticalSection(&mp->cs);
152         if (!mp->isLocked) {
153             mp->isLocked = 1;
154             mp->tid = GetCurrentThreadId();
155         } else {
156             /* 
157              * same thread tried to recursively lock this mutex.
158              * Under real POSIX, this would cause a deadlock, but NT only 
159              * supports recursive mutexes so we indicate the situation
160              * by returning EDEADLK.
161              */
162             LeaveCriticalSection(&mp->cs);
163             rc = EDEADLK;
164         }
165     } else {
166         rc = EINVAL;
167     }
168         
169     return rc;
170 }
171
172 int pthread_mutex_unlock(pthread_mutex_t *mp) {
173     int rc = 0;
174
175     if (mp != NULL) {
176         if (mp->tid == GetCurrentThreadId()) {
177             mp->isLocked = 0;
178             mp->tid = 0;
179             LeaveCriticalSection(&mp->cs);
180         } else {
181             rc = 0;
182         }
183     } else {
184         rc = EINVAL;
185     }
186     return rc;
187 }
188
189 int pthread_mutex_destroy(pthread_mutex_t *mp) {
190     int rc = 0;
191
192     if (mp != NULL) {
193         DeleteCriticalSection(&mp->cs);
194     } else {
195         rc = EINVAL;
196     }
197
198     return rc;
199 }
200
201 /*
202  * keys is used to keep track of which keys are currently
203  * in use by the threads library.  pthread_tsd_mutex is used
204  * to protect keys.
205  *
206  * The bookkeeping for keys in use and destructor function/key is
207  * at the library level.  Each individual thread only keeps its
208  * per key data value.  This implies that the keys array and the
209  * tsd array in the pthread_t structure need to always be exactly
210  * the same size since the same index is used for both arrays.
211  */
212
213 typedef struct {
214     int inuse;
215     void (*destructor)(void *);
216 } pthread_tsd_table_t;
217
218 static pthread_tsd_table_t keys[PTHREAD_KEYS_MAX];
219 static pthread_mutex_t pthread_tsd_mutex;
220 static pthread_once_t pthread_tsd_once = PTHREAD_ONCE_INIT;
221
222 /*
223  * In order to support p_self() and p_join() under NT,
224  * we have to keep our own list of active threads and provide a mapping
225  * function that maps the NT thread id to our internal structure.
226  * The main reason that this is necessary is that GetCurrentThread
227  * returns a special constant not an actual handle to the thread.
228  * This makes it impossible to write a p_self() function that works
229  * with only the native NT functions.
230  */
231
232 static struct rx_queue active_Q;
233 static struct rx_queue cache_Q;
234
235 static pthread_mutex_t active_Q_mutex;
236 static pthread_mutex_t cache_Q_mutex;
237
238 static pthread_once_t pthread_cache_once = PTHREAD_ONCE_INIT;
239 static int pthread_cache_done;
240
241 typedef struct thread {
242     struct rx_queue thread_queue;
243     void *rc;
244     int running;
245     pthread_cond_t wait_terminate;
246     int waiter_count;
247     int is_joinable;
248     int has_been_joined;
249     HANDLE t_handle;
250     DWORD NT_id;
251     int native_thread;
252     char **tsd;
253 } thread_t, *thread_p;
254
255 static void create_once(void) {
256     queue_Init(&active_Q);
257     queue_Init(&cache_Q);
258     pthread_mutex_init(&active_Q_mutex, (const pthread_mutexattr_t*)0);
259     pthread_mutex_init(&cache_Q_mutex, (const pthread_mutexattr_t*)0);
260     pthread_cache_done = 1;
261 }
262
263 static void put_thread(thread_p old) {
264  
265     CloseHandle(old->t_handle);
266     pthread_mutex_lock(&cache_Q_mutex);
267     queue_Prepend(&cache_Q, old);
268     pthread_mutex_unlock(&cache_Q_mutex);
269 }
270
271 static thread_p get_thread() {
272     thread_p new = NULL;
273  
274     pthread_mutex_lock(&cache_Q_mutex);
275  
276     if (queue_IsEmpty(&cache_Q)) {
277         new = (thread_p) malloc(sizeof(thread_t));
278         if (new != NULL) {
279             /*
280              * One time initialization - we assume threads put back have
281              * unlocked mutexes and condition variables with no waiters
282              *
283              * These functions cannot fail currently.
284              */
285             pthread_cond_init(&new->wait_terminate,(const pthread_condattr_t *)0);
286         }
287     } else {
288         new = queue_First(&cache_Q, thread);
289         queue_Remove(new);
290     }
291  
292     pthread_mutex_unlock(&cache_Q_mutex);
293
294     /* 
295      * Initialization done every time we hand out a thread_t
296      */
297
298     if (new != NULL) {
299         new->rc = NULL;
300         new->running = 1;
301         new->waiter_count = 0;
302         new->has_been_joined = 0;
303     }
304     return new;
305  
306 }
307  
308 /*
309  * The thread start function signature is different on NT than the pthread
310  * spec so we create a tiny stub to map from one signature to the next.
311  * This assumes that a void * can be stored within a DWORD.
312  */
313
314 typedef struct {
315     void *(*func)(void *);
316     void *arg;
317     char *tsd[PTHREAD_KEYS_MAX];
318     thread_p me;
319 } pthread_create_t;
320
321 static DWORD tsd_index = 0xffffffff;
322 static DWORD tsd_pthread_index = 0xffffffff;
323 static pthread_once_t global_tsd_once = PTHREAD_ONCE_INIT;
324 static int tsd_done;
325
326 static void tsd_once(void) {
327     while(tsd_index == 0xffffffff) {
328         tsd_index = TlsAlloc();
329     }
330     while(tsd_pthread_index == 0xffffffff) {
331         tsd_pthread_index = TlsAlloc();
332     }
333     tsd_done = 1;
334 }
335
336 static void tsd_free_all(char *tsd[PTHREAD_KEYS_MAX]) {
337     int call_more_destructors = 0;
338     do {
339         int i;
340         void *value;
341         void (*destructor)(void *);
342         call_more_destructors = 0;
343         for(i=0;i<PTHREAD_KEYS_MAX;i++) {
344             if (tsd[i] != NULL) {
345                 destructor = keys[i].destructor;
346                 value = (void *)tsd[i];
347                 tsd[i] = NULL;
348                 if (destructor != NULL) {
349                     (destructor)(value);
350                     /*
351                      * A side-effect of calling a destructor function is that
352                      * more thread specific may be created for this thread.
353                      * If we call a destructor, we must recycle through the
354                      * entire list again and run any new destructors.
355                      */
356                     call_more_destructors = 1;
357                 }
358             }
359         }
360     } while(call_more_destructors);
361 }
362
363 static DWORD WINAPI afs_pthread_create_stub(LPVOID param) {
364     pthread_create_t *t = (pthread_create_t *) param;
365     void *rc;
366
367     /* 
368      * Initialize thread specific storage structures.
369      */
370
371     memset(t->tsd, 0, (sizeof(char *) * PTHREAD_KEYS_MAX));
372     (tsd_done || pthread_once(&global_tsd_once, tsd_once));
373     TlsSetValue(tsd_index, (LPVOID) (t->tsd));
374     TlsSetValue(tsd_pthread_index, (LPVOID) (t->me));
375
376     /*
377      * Call the function the user passed to pthread_create and catch the
378      * pthread exit exception if it is raised.
379      */
380
381     __try {
382         rc = (*(t->func))(t->arg);
383     } __except(GetExceptionCode() == PTHREAD_EXIT_EXCEPTION) {
384         rc = t->me->rc; /* rc is set at pthread_exit */
385     }
386
387     /*
388      * Cycle through the thread specific data for this thread and
389      * call the destructor function for each non-NULL datum
390      */
391
392     tsd_free_all (t->tsd);
393     t->me->tsd = NULL;
394
395     /*
396      * If we are joinable, signal any waiters.
397      */
398
399     pthread_mutex_lock(&active_Q_mutex);
400     if (t->me->is_joinable) {
401         t->me->running = 0;
402         t->me->rc = rc;
403         if (t->me->waiter_count) {
404             pthread_cond_broadcast(&t->me->wait_terminate);
405         }
406     } else {
407         queue_Remove(t->me);
408         put_thread(t->me);
409     }
410     pthread_mutex_unlock(&active_Q_mutex);
411
412     free(t);
413     return 0;
414 }
415
416 /*
417  * If a pthread function is called on a thread which was not created by
418  * pthread_create(), that thread will have an entry added to the active_Q
419  * by pthread_self(). When the thread terminates, we need to know
420  * about it, so that we can perform cleanup. A dedicated thread is therefore
421  * maintained, which watches for any thread marked "native_thread==1"
422  * in the active_Q to terminate. The thread spends most of its time sleeping:
423  * it can be signalled by a dedicated event in order to alert it to the
424  * presense of a new thread to watch, or will wake up automatically when
425  * a native thread terminates.
426  */
427
428 static DWORD terminate_thread_id = 0;
429 static HANDLE terminate_thread_handle = INVALID_HANDLE_VALUE;
430 static HANDLE terminate_thread_wakeup_event = INVALID_HANDLE_VALUE;
431 static HANDLE *terminate_thread_wakeup_list = NULL;
432 static size_t terminate_thread_wakeup_list_size = 0;
433
434 static DWORD WINAPI terminate_thread_routine(LPVOID param) {
435     thread_p cur, next;
436     size_t native_thread_count;
437     int should_terminate;
438     int terminate_thread_wakeup_list_index;
439
440     for (;;) {
441         /*
442          * Grab the active_Q_mutex, and while we hold it, scan the active_Q
443          * to see how many native threads we need to watch. If we don't need
444          * to watch any, we can stop this watcher thread entirely (or not);
445          * if we do need to watch some, fill the terminate_thread_wakeup_list
446          * array and go to sleep.
447          */
448         cur = NULL;
449         next = NULL;
450         native_thread_count = 0;
451         should_terminate = FALSE;
452         pthread_mutex_lock(&active_Q_mutex);
453
454         for(queue_Scan(&active_Q, cur, next, thread)) {
455             if (cur->native_thread)
456                 ++native_thread_count;
457         }
458
459         /*
460          * At this point we could decide to terminate this watcher thread
461          * whenever there are no longer any native threads to watch--however,
462          * since thread creation is a time-consuming thing, and since this
463          * thread spends all its time sleeping anyway, there's no real
464          * compelling reason to do so. Thus, the following statement is
465          * commented out:
466          *
467          * if (!native_thread_count) {
468          *    should_terminate = TRUE;
469          * }
470          *
471          * Restore the snippet above to cause this watcher thread to only
472          * live whenever there are native threads to watch.
473          *
474          */
475
476         /*
477          * Make sure that our wakeup_list array is large enough to contain
478          * the handles of all the native threads /and/ to contain an
479          * entry for our wakeup_event (in case another native thread comes
480          * along).
481          */
482         if (terminate_thread_wakeup_list_size < (1+native_thread_count)) {
483             if (terminate_thread_wakeup_list)
484                 free (terminate_thread_wakeup_list);
485             terminate_thread_wakeup_list = (HANDLE*)malloc (sizeof(HANDLE) *
486                                 (1+native_thread_count));
487             if (terminate_thread_wakeup_list == NULL) {
488                 should_terminate = TRUE;
489             } else {
490                 terminate_thread_wakeup_list_size = 1+native_thread_count;
491             }
492         }
493
494         if (should_terminate) {
495             /*
496              * Here, we've decided to terminate this watcher thread.
497              * Free our wakeup event and wakeup list, then release the
498              * active_Q_mutex and break this loop.
499              */
500             if (terminate_thread_wakeup_list)
501                 free (terminate_thread_wakeup_list);
502             CloseHandle (terminate_thread_wakeup_event);
503             terminate_thread_id = 0;
504             terminate_thread_handle = INVALID_HANDLE_VALUE;
505             terminate_thread_wakeup_event = INVALID_HANDLE_VALUE;
506             terminate_thread_wakeup_list = NULL;
507             terminate_thread_wakeup_list_size = 0;
508             pthread_mutex_unlock(&active_Q_mutex);
509             break;
510         } else {
511             /*
512              * Here, we've decided to wait for native threads et al.
513              * Fill out the wakeup_list.
514              */
515             memset(terminate_thread_wakeup_list, 0x00, (sizeof(HANDLE) * 
516                                 (1+native_thread_count)));
517
518             terminate_thread_wakeup_list[0] = terminate_thread_wakeup_event;
519             terminate_thread_wakeup_list_index = 1;
520
521             cur = NULL;
522             next = NULL;
523             for(queue_Scan(&active_Q, cur, next, thread)) {
524                 if (cur->native_thread) {
525                     terminate_thread_wakeup_list[terminate_thread_wakeup_list_index]
526                         = cur->t_handle;
527                     ++terminate_thread_wakeup_list_index;
528                 }
529             }
530
531             ResetEvent (terminate_thread_wakeup_event);
532         }
533
534         pthread_mutex_unlock(&active_Q_mutex);
535
536         /*
537          * Time to sleep. We'll wake up if either of the following happen:
538          * 1) Someone sets the terminate_thread_wakeup_event (this will
539          *    happen if another native thread gets added to the active_Q)
540          * 2) One or more of the native threads terminate
541          */
542         terminate_thread_wakeup_list_index = WaitForMultipleObjects(
543                                         1+native_thread_count,
544                                         terminate_thread_wakeup_list,
545                                         FALSE,
546                                         INFINITE);
547
548         /*
549          * If we awoke from sleep because an event other than
550          * terminate_thread_wakeup_event was triggered, it means the
551          * specified thread has terminated. (If more than one thread
552          * terminated, we'll handle this first one and loop around--
553          * the event's handle will still be triggered, so we just won't
554          * block at all when we sleep next time around.)
555          */
556         if (terminate_thread_wakeup_list_index > 0) {
557             pthread_mutex_lock(&active_Q_mutex);
558
559             cur = NULL;
560             next = NULL;
561             for(queue_Scan(&active_Q, cur, next, thread)) {
562                 if (cur->t_handle == terminate_thread_wakeup_list[ terminate_thread_wakeup_list_index ])
563                     break;
564             }
565
566             if(cur != NULL) {
567                 /*
568                  * Cycle through the thread specific data for the specified
569                  * thread and call the destructor function for each non-NULL
570                  * datum. Then remove the thread_t from active_Q and put it
571                  * back on cache_Q for possible later re-use.
572                  */
573                 if(cur->tsd != NULL) {
574                     tsd_free_all(cur->tsd);
575                     free(cur->tsd);
576                     cur->tsd = NULL;
577                 }
578                 queue_Remove(cur);
579                 put_thread(cur);
580             }
581
582             pthread_mutex_unlock(&active_Q_mutex);
583         }
584     }
585     return 0;
586 }
587
588
589 static void pthread_sync_terminate_thread(void) {
590     (pthread_cache_done || pthread_once(&pthread_cache_once, create_once));
591
592     if (terminate_thread_handle == INVALID_HANDLE_VALUE) {
593         terminate_thread_wakeup_event = CreateEvent((LPSECURITY_ATTRIBUTES) 0,
594                                 TRUE, FALSE, (LPCTSTR) 0);
595         terminate_thread_handle = CreateThread((LPSECURITY_ATTRIBUTES) 0, 0, 
596                                 terminate_thread_routine, (LPVOID) 0, 0, 
597                                 &terminate_thread_id);
598     } else {
599         SetEvent (terminate_thread_wakeup_event);
600     }
601 }
602
603
604 /*
605  * Only support the detached attribute specifier for pthread_create.
606  * Under NT, thread stacks grow automatically as needed.
607  */
608
609 int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func)(void *), void *arg) {
610     int rc = 0;
611     pthread_create_t *t = NULL;
612
613     (pthread_cache_done || pthread_once(&pthread_cache_once, create_once));
614
615     if ((tid != NULL) && (func != NULL)) {
616         if ((t = (pthread_create_t *) malloc(sizeof(pthread_create_t))) &&
617             (t->me = get_thread()) ) {
618             t->func = func;
619             t->arg = arg;
620             *tid = (pthread_t) t->me;
621             if (attr != NULL) {
622                 t->me->is_joinable = attr->is_joinable;
623             } else {
624                 t->me->is_joinable = PTHREAD_CREATE_JOINABLE;
625             }
626             t->me->native_thread = 0;
627             t->me->tsd = t->tsd;
628             /*
629              * At the point (before we actually create the thread)
630              * we need to add our entry to the active queue.  This ensures
631              * us that other threads who may run after this thread returns
632              * will find an entry for the create thread regardless of
633              * whether the newly created thread has run or not.
634              * In the event the thread create fails, we will have temporarily
635              * added an entry to the list that was never valid, but we
636              * (i.e. the thread that is calling thread_create) are the
637              * only one who could possibly know about the bogus entry
638              * since we hold the active_Q_mutex.
639              */
640             pthread_mutex_lock(&active_Q_mutex);
641             queue_Prepend(&active_Q, t->me);
642             t->me->t_handle = CreateThread((LPSECURITY_ATTRIBUTES) 0, 0, 
643                                 afs_pthread_create_stub, (LPVOID) t, 0, 
644                                 &t->me->NT_id);
645             if (t->me->t_handle == 0) {
646                 /* 
647                  * we only free t if the thread wasn't created, otherwise
648                  * it's free'd by the new thread.
649                  */
650                 queue_Remove(t->me);
651                 put_thread(t->me);
652                 free(t);
653                 rc = EAGAIN;
654             }
655             pthread_mutex_unlock(&active_Q_mutex);
656         } else {
657             if (t != NULL) {
658                 free(t);
659             }
660             rc = ENOMEM;
661         }
662     } else {
663         rc = EINVAL;
664     }
665     return rc;
666 }
667
668 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) {
669     int rc = 0;
670
671     /*
672      * Only support default attribute -> must pass a NULL pointer for
673      * attr parameter.
674      */
675     if ((attr == NULL) && (cond != NULL)) {
676         InitializeCriticalSection(&cond->cs);
677         queue_Init(&cond->waiting_threads);
678     } else {
679         rc = EINVAL;
680     }
681
682     return rc;
683 }
684
685 /*
686  * In order to optimize the performance of condition variables,
687  * we maintain a pool of cond_waiter_t's that have been dynamically
688  * allocated.  There is no attempt made to garbage collect these -
689  * once they have been created, they stay in the cache for the life
690  * of the process.
691  */
692  
693 static struct rx_queue waiter_cache;
694 static CRITICAL_SECTION waiter_cache_cs;
695 static int waiter_cache_init;
696 static pthread_once_t waiter_cache_once = PTHREAD_ONCE_INIT;
697  
698 static void init_waiter_cache(void) {
699     InitializeCriticalSection(&waiter_cache_cs);
700     waiter_cache_init = 1;
701     queue_Init(&waiter_cache);
702 }
703  
704 static cond_waiters_t *get_waiter() {
705     cond_waiters_t *new = NULL;
706  
707     (waiter_cache_init || pthread_once(&waiter_cache_once, init_waiter_cache));
708  
709     EnterCriticalSection(&waiter_cache_cs);
710  
711     if (queue_IsEmpty(&waiter_cache)) {
712         new = (cond_waiters_t *) malloc(sizeof(cond_waiters_t));
713         if (new != NULL) {
714 #if 1
715             CHAR eventName[MAX_PATH];
716             static eventCount = 0;
717             sprintf(eventName, "cond_waiters_t %d::%d", _getpid(), eventCount++);
718             new->event = CreateEvent((LPSECURITY_ATTRIBUTES) 0, FALSE,
719                                       FALSE, (LPCTSTR) eventName);
720 #else
721             new->event = CreateEvent((LPSECURITY_ATTRIBUTES) 0, FALSE,
722                                       FALSE, (LPCTSTR) 0);
723             if (new->event == NULL) {
724                 free(new);
725                 new = NULL;
726             }
727 #endif
728         }
729     } else {
730         new = queue_First(&waiter_cache, cond_waiter);
731         queue_Remove(new);
732     }
733  
734     LeaveCriticalSection(&waiter_cache_cs);
735     return new;
736 }
737  
738 static void put_waiter(cond_waiters_t *old) {
739  
740     (waiter_cache_init || pthread_once(&waiter_cache_once, init_waiter_cache));
741  
742     EnterCriticalSection(&waiter_cache_cs);
743     queue_Prepend(&waiter_cache, old);
744     LeaveCriticalSection(&waiter_cache_cs);
745 }
746
747 static int cond_wait_internal(pthread_cond_t *cond, pthread_mutex_t *mutex, const DWORD time) {
748     int rc=0;
749     cond_waiters_t *my_entry = get_waiter();
750     cond_waiters_t *cur, *next;
751     int hasnt_been_signalled=0;
752
753     if ((cond != NULL) && (mutex != NULL) && (my_entry != NULL)) {
754         EnterCriticalSection(&cond->cs);
755         queue_Append(&cond->waiting_threads, my_entry);
756         LeaveCriticalSection(&cond->cs);
757
758         if (!pthread_mutex_unlock(mutex)) {
759             switch(WaitForSingleObject(my_entry->event, time)) {
760                 case WAIT_FAILED:
761                     rc = -1;
762                     break;
763                 case WAIT_TIMEOUT:
764                     rc = ETIME;
765                     /*
766                      * This is a royal pain.  We've timed out waiting
767                      * for the signal, but between the time out and here
768                      * it is possible that we were actually signalled by 
769                      * another thread.  So we grab the condition lock
770                      * and scan the waiting thread queue to see if we are
771                      * still there.  If we are, we just remove ourselves.
772                      *
773                      * If we are no longer listed in the waiter queue,
774                      * it means that we were signalled after the time
775                      * out occurred and so we have to do another wait
776                      * WHICH HAS TO SUCCEED!  In this case, we reset
777                      * rc to indicate that we were signalled.
778                      *
779                      * We have to wait or otherwise, the event
780                      * would be cached in the signalled state, which
781                      * is wrong.  It might be more efficient to just
782                      * close and reopen the event.
783                      */
784                     EnterCriticalSection(&cond->cs);
785                     for(queue_Scan(&cond->waiting_threads, cur,
786                                    next, cond_waiter)) {
787                         if (cur == my_entry) {
788                             hasnt_been_signalled = 1;
789                             break;
790                         }
791                     }
792                     if (hasnt_been_signalled) {
793                         queue_Remove(cur);
794                     } else {
795                         rc = 0;
796                         if (ResetEvent(my_entry->event)) {
797                             if (pthread_mutex_lock(mutex)) {
798                                 rc = -5;
799                             }
800                         } else {
801                             rc = -6;
802                         }
803                     }
804                     LeaveCriticalSection(&cond->cs);
805                     break;
806                 case WAIT_ABANDONED:
807                     rc = -2;
808                     break;
809                 case WAIT_OBJECT_0:
810                     if (pthread_mutex_lock(mutex)) {
811                         rc = -3;
812                     }
813                     break;
814                 default:
815                     rc = -4;
816                     break;
817             }
818         } else {
819             rc = EINVAL;
820         }
821     } else {
822         rc = EINVAL;
823     }
824
825     if (my_entry != NULL) {
826         put_waiter(my_entry);
827     }
828
829     return rc;
830 }
831
832 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
833     int rc = 0;
834
835     rc = cond_wait_internal(cond, mutex, INFINITE);
836     return rc;
837 }
838
839 int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) {
840     int rc = 0;
841     struct _timeb now, then;
842     short n_milli, t_milli;
843
844     if (abstime->tv_nsec < 1000000000) {
845
846         /*
847          * pthread timedwait uses an absolute time, NT uses relative so
848          * we convert here.  The millitm field in the timeb struct is
849          * unsigned, but we need to do subtraction preserving the sign, 
850          * so we copy the fields into temporary variables.
851          *
852          * WARNING:
853          * In NT 4.0 SP3, WaitForSingleObject can occassionally timeout
854          * earlier than requested.  Therefore, our pthread_cond_timedwait
855          * can also return early.
856          */
857
858         _ftime(&now);
859         n_milli = now.millitm;
860         then.time = abstime->tv_sec;
861         t_milli = abstime->tv_nsec/1000000;
862
863         if((then.time > now.time || 
864            (then.time == now.time && t_milli > n_milli))) {
865             if((t_milli -= n_milli) < 0) {
866                 t_milli += 1000;
867                 then.time--;
868             }
869             then.time -= now.time;
870
871             if ((then.time + (clock() / CLOCKS_PER_SEC)) <= 50000000) {
872                 /*
873                  * Under NT, we can only wait for milliseconds, so we
874                  * round up the wait time here.
875                  */
876                 rc = cond_wait_internal(cond, mutex, 
877                                  ((then.time * 1000) + (t_milli)));
878             } else {
879                 rc = EINVAL;
880             }
881         } else {
882             rc = ETIME;
883         }
884     } else {
885         rc = EINVAL;
886     }
887
888     return rc;
889 }
890
891 int pthread_cond_signal(pthread_cond_t *cond) {
892     int rc = 0;
893     cond_waiters_t *release_thread;
894
895     if (cond != NULL) {
896         EnterCriticalSection(&cond->cs);
897
898         /*
899          * remove the first waiting thread from the queue
900          * and resume his execution
901          */
902         if (queue_IsNotEmpty(&cond->waiting_threads)) {
903             release_thread = queue_First(&cond->waiting_threads,
904                                          cond_waiter);
905             queue_Remove(release_thread);
906             if (!SetEvent(release_thread->event)) {
907                 rc = -1;
908             }
909         }
910
911         LeaveCriticalSection(&cond->cs);
912     } else {
913         rc = EINVAL;
914     }
915
916     return rc;
917 }
918
919 int pthread_cond_broadcast(pthread_cond_t *cond) {
920     int rc = 0;
921     cond_waiters_t *release_thread, *next_thread;
922
923     if(cond != NULL) {
924         EnterCriticalSection(&cond->cs);
925
926         /*
927          * Empty the waiting_threads queue. 
928          */
929         if (queue_IsNotEmpty(&cond->waiting_threads)) {
930             for(queue_Scan(&cond->waiting_threads, release_thread,
931                            next_thread, cond_waiter)) {
932                 queue_Remove(release_thread);
933                 if (!SetEvent(release_thread->event)) {
934                     rc = -1;
935                 }
936             }
937         }
938
939         LeaveCriticalSection(&cond->cs);
940     } else {
941         rc = EINVAL;
942     }
943
944     return rc;
945 }
946
947 int pthread_cond_destroy(pthread_cond_t *cond) {
948     int rc = 0;
949
950     if (cond != NULL) {
951         DeleteCriticalSection(&cond->cs);
952     } else {
953         rc = EINVAL;
954     }
955         
956     /*
957      * A previous version of this file had code to check the waiter
958      * queue and empty it here.  This has been removed in the hopes
959      * that it will aid in debugging.
960      */
961
962     return rc;
963 }
964
965 int pthread_join(pthread_t target_thread, void **status) {
966     int rc = 0;
967     thread_p me, target;
968     thread_p cur, next;
969
970     target = (thread_p) target_thread;
971     me = (thread_p) pthread_self();
972
973     if (me != target) {
974         /*
975          * Check to see that the target thread is joinable and hasn't
976          * already been joined.
977          */
978
979         pthread_mutex_lock(&active_Q_mutex);
980
981         for(queue_Scan(&active_Q, cur, next, thread)) {
982             if (target == cur) break;
983         }
984
985         if (target == cur) {
986             if ((!target->is_joinable) || (target->has_been_joined)) {
987                 rc = ESRCH;
988             }
989         } else {
990             rc = ESRCH;
991         }
992
993         if (rc) {
994             pthread_mutex_unlock(&active_Q_mutex);
995             return rc;
996         }
997
998         target->waiter_count++;
999         while(target->running) {
1000             pthread_cond_wait(&target->wait_terminate, &active_Q_mutex);
1001         }
1002
1003         /*
1004          * Only one waiter gets the status and is allowed to join, all the
1005          * others get an error.
1006          */
1007
1008         if (target->has_been_joined) {
1009             rc = ESRCH;
1010         } else {
1011             target->has_been_joined = 1;
1012             if (status) {
1013                 *status = target->rc;
1014             }
1015         }
1016
1017         /*
1018          * If we're the last waiter it is our responsibility to remove
1019          * this entry from the terminated list and put it back in the
1020          * cache.
1021          */
1022
1023         target->waiter_count--;
1024         if (target->waiter_count == 0) {
1025             queue_Remove(target);
1026             pthread_mutex_unlock(&active_Q_mutex);
1027             put_thread(target);
1028         } else {
1029             pthread_mutex_unlock(&active_Q_mutex);
1030         }
1031     } else {
1032         rc = EDEADLK;
1033     }
1034
1035     return rc;
1036 }
1037
1038 /*
1039  * Note that we can't return an error from pthread_getspecific so
1040  * we return a NULL pointer instead.
1041  */
1042
1043 void *pthread_getspecific(pthread_key_t key) {
1044     void *rc = NULL;
1045     char **tsd = TlsGetValue(tsd_index);
1046
1047     if ((key > -1) && (key < PTHREAD_KEYS_MAX )) {
1048         rc = (void *) *(tsd + key);
1049     }
1050
1051     return rc;
1052 }
1053
1054 static int p_tsd_done;
1055
1056 static void pthread_tsd_init(void) {
1057     pthread_mutex_init(&pthread_tsd_mutex, (const pthread_mutexattr_t*)0);
1058     p_tsd_done = 1;
1059 }
1060
1061 int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value)) {
1062     int rc = 0;
1063     int i;
1064
1065     if (p_tsd_done || (!pthread_once(&pthread_tsd_once, pthread_tsd_init))) {
1066         if (!pthread_mutex_lock(&pthread_tsd_mutex)) {
1067             for(i=0;i<PTHREAD_KEYS_MAX;i++) {
1068                 if (!keys[i].inuse) break;
1069             }
1070
1071             if (!keys[i].inuse) {
1072                 keys[i].inuse = 1;
1073                 keys[i].destructor = destructor;
1074                 *keyp = i;
1075             } else {
1076                 rc = EAGAIN;
1077             }
1078             pthread_mutex_unlock(&pthread_tsd_mutex);
1079         } else {
1080             rc = -1;
1081         }
1082     } else {
1083         rc = -2;
1084     }
1085
1086     return rc;
1087 }
1088
1089 int pthread_key_delete(pthread_key_t key) {
1090     int rc = 0;
1091
1092     if (p_tsd_done || (!pthread_once(&pthread_tsd_once, pthread_tsd_init))) {
1093         if ((key > -1) && (key < PTHREAD_KEYS_MAX )) {
1094             if (!pthread_mutex_lock(&pthread_tsd_mutex)) {
1095                 keys[key].inuse = 0;
1096                 keys[key].destructor = NULL;
1097                 pthread_mutex_unlock(&pthread_tsd_mutex);
1098             } else {
1099                 rc = -1;
1100             }
1101         } else {
1102             rc = EINVAL;
1103         }
1104     } else {
1105         rc = -2;
1106     }
1107
1108     return rc;
1109 }
1110
1111 int pthread_setspecific(pthread_key_t key, const void *value) {
1112     int rc = 0;
1113     char **tsd;
1114
1115     if (p_tsd_done || (!pthread_once(&pthread_tsd_once, pthread_tsd_init))) {
1116         if ((key > -1) && (key < PTHREAD_KEYS_MAX )) {
1117             if (!pthread_mutex_lock(&pthread_tsd_mutex)) {
1118                 if (keys[key].inuse) {
1119                     tsd = TlsGetValue(tsd_index);
1120                     *(tsd + key) = (char *) value;
1121                 } else {
1122                     rc = EINVAL;
1123                 }
1124                 pthread_mutex_unlock(&pthread_tsd_mutex);
1125             } else {
1126                 rc = -1;
1127             }
1128         } else {
1129             rc = EINVAL;
1130         }
1131     } else {
1132       rc = -2;
1133     }
1134
1135     return rc;
1136 }
1137
1138 pthread_t pthread_self(void) {
1139     thread_p cur;
1140     DWORD my_id = GetCurrentThreadId();
1141
1142     (pthread_cache_done || pthread_once(&pthread_cache_once, create_once));
1143     (tsd_done || pthread_once(&global_tsd_once, tsd_once));
1144
1145     pthread_mutex_lock(&active_Q_mutex);
1146
1147     cur = TlsGetValue (tsd_pthread_index);
1148
1149     if(!cur) {
1150         /*
1151          * This thread's ID was not found in our list of pthread-API client
1152          * threads (e.g., those threads created via pthread_create). Create
1153          * an entry for it.
1154          */
1155         if ((cur = get_thread()) != NULL) {
1156             cur->is_joinable = 0;
1157             cur->NT_id = my_id;
1158             cur->native_thread = 1;
1159             DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
1160              GetCurrentProcess(), &cur->t_handle, 0,
1161              TRUE, DUPLICATE_SAME_ACCESS);
1162
1163             /*
1164              * We'll also need a place to store key data for this thread
1165              */
1166             if ((cur->tsd = malloc(sizeof(char*) * PTHREAD_KEYS_MAX)) != NULL) {
1167                 memset(cur->tsd, 0, (sizeof(char*) * PTHREAD_KEYS_MAX));
1168             }
1169             TlsSetValue(tsd_index, (LPVOID)cur->tsd);
1170             TlsSetValue(tsd_pthread_index, (LPVOID)cur);
1171
1172             /*
1173              * The thread_t structure is complete; add it to the active_Q
1174              */
1175             queue_Prepend(&active_Q, cur);
1176
1177             /*
1178              * We were able to successfully insert a new entry into the
1179              * active_Q; however, when this thread terminates, we will need
1180              * to know about it. The pthread_sync_terminate_thread() routine
1181              * will make sure there is a dedicated thread waiting for any
1182              * native-thread entries in the active_Q to terminate.
1183              */
1184             pthread_sync_terminate_thread();
1185         }
1186     }
1187
1188     pthread_mutex_unlock(&active_Q_mutex);
1189
1190     return (void *) cur;
1191 }
1192
1193 int pthread_equal(pthread_t t1, pthread_t t2) {
1194     return (t1 == t2);
1195 }
1196
1197 int pthread_attr_destroy(pthread_attr_t *attr) {
1198     int rc = 0;
1199
1200     return rc;
1201 }
1202
1203 int pthread_attr_init(pthread_attr_t *attr) {
1204     int rc = 0;
1205
1206     if (attr != NULL) {
1207         attr->is_joinable = PTHREAD_CREATE_JOINABLE;
1208     } else {
1209         rc = EINVAL;
1210     }
1211
1212     return rc;
1213 }
1214
1215 int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate) {
1216     int rc = 0;
1217
1218     if ((attr != NULL) && (detachstate != NULL)) {
1219             *detachstate = attr->is_joinable;
1220     } else {
1221         rc = EINVAL;
1222     }
1223     return rc;
1224 }
1225
1226 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) {
1227     int rc = 0;
1228
1229     if ((attr != NULL) && ((detachstate == PTHREAD_CREATE_JOINABLE) ||
1230         (detachstate == PTHREAD_CREATE_DETACHED))) {
1231         attr->is_joinable = detachstate;
1232     } else {
1233         rc = EINVAL;
1234     }
1235     return rc;
1236 }
1237
1238 void pthread_exit(void *status) {
1239     thread_p me = (thread_p) pthread_self();
1240
1241     /*
1242      * Support pthread_exit for thread's created by calling pthread_create
1243      * only.  Do this by using an exception that will transfer control
1244      * back to afs_pthread_create_stub.  Store away our status before
1245      * returning.
1246      *
1247      * If this turns out to be a native thread, the exception will be
1248      * unhandled and the process will terminate.
1249      */
1250
1251     me->rc = status;
1252     RaiseException(PTHREAD_EXIT_EXCEPTION, 0, 0, NULL);
1253
1254 }