findlanabyname-20040228
[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             new->event = CreateEvent((LPSECURITY_ATTRIBUTES) 0, FALSE,
715                                      FALSE, (LPCTSTR) 0);
716             if (new->event == NULL) {
717                 free(new);
718                 new = NULL;
719             }
720         }
721     } else {
722         new = queue_First(&waiter_cache, cond_waiter);
723         queue_Remove(new);
724     }
725  
726     LeaveCriticalSection(&waiter_cache_cs);
727     return new;
728  
729 }
730  
731 static void put_waiter(cond_waiters_t *old) {
732  
733     (waiter_cache_init || pthread_once(&waiter_cache_once, init_waiter_cache));
734  
735     EnterCriticalSection(&waiter_cache_cs);
736     queue_Prepend(&waiter_cache, old);
737     LeaveCriticalSection(&waiter_cache_cs);
738 }
739
740 static int cond_wait_internal(pthread_cond_t *cond, pthread_mutex_t *mutex, const DWORD time) {
741     int rc=0;
742     cond_waiters_t *my_entry = get_waiter();
743     cond_waiters_t *cur, *next;
744     int hasnt_been_signalled=0;
745
746     if ((cond != NULL) && (mutex != NULL) && (my_entry != NULL)) {
747         EnterCriticalSection(&cond->cs);
748         queue_Append(&cond->waiting_threads, my_entry);
749         LeaveCriticalSection(&cond->cs);
750
751         if (!pthread_mutex_unlock(mutex)) {
752             switch(WaitForSingleObject(my_entry->event, time)) {
753                 case WAIT_FAILED:
754                     rc = -1;
755                     break;
756                 case WAIT_TIMEOUT:
757                     rc = ETIME;
758                     /*
759                      * This is a royal pain.  We've timed out waiting
760                      * for the signal, but between the time out and here
761                      * it is possible that we were actually signalled by 
762                      * another thread.  So we grab the condition lock
763                      * and scan the waiting thread queue to see if we are
764                      * still there.  If we are, we just remove ourselves.
765                      *
766                      * If we are no longer listed in the waiter queue,
767                      * it means that we were signalled after the time
768                      * out occurred and so we have to do another wait
769                      * WHICH HAS TO SUCCEED!  In this case, we reset
770                      * rc to indicate that we were signalled.
771                      *
772                      * We have to wait or otherwise, the event
773                      * would be cached in the signalled state, which
774                      * is wrong.  It might be more efficient to just
775                      * close and reopen the event.
776                      */
777                     EnterCriticalSection(&cond->cs);
778                     for(queue_Scan(&cond->waiting_threads, cur,
779                                    next, cond_waiter)) {
780                         if (cur == my_entry) {
781                             hasnt_been_signalled = 1;
782                             break;
783                         }
784                     }
785                     if (hasnt_been_signalled) {
786                         queue_Remove(cur);
787                     } else {
788                         rc = 0;
789                         if (ResetEvent(my_entry->event)) {
790                             if (pthread_mutex_lock(mutex)) {
791                                 rc = -5;
792                             }
793                         } else {
794                             rc = -6;
795                         }
796                     }
797                     LeaveCriticalSection(&cond->cs);
798                     break;
799                 case WAIT_ABANDONED:
800                     rc = -2;
801                     break;
802                 case WAIT_OBJECT_0:
803                     if (pthread_mutex_lock(mutex)) {
804                         rc = -3;
805                     }
806                     break;
807                 default:
808                     rc = -4;
809                     break;
810             }
811         } else {
812             rc = EINVAL;
813         }
814     } else {
815         rc = EINVAL;
816     }
817
818     if (my_entry != NULL) {
819         put_waiter(my_entry);
820     }
821
822     return rc;
823 }
824
825 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
826     int rc = 0;
827
828     rc = cond_wait_internal(cond, mutex, INFINITE);
829     return rc;
830 }
831
832 int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) {
833     int rc = 0;
834     struct _timeb now, then;
835     short n_milli, t_milli;
836
837     if (abstime->tv_nsec < 1000000000) {
838
839         /*
840          * pthread timedwait uses an absolute time, NT uses relative so
841          * we convert here.  The millitm field in the timeb struct is
842          * unsigned, but we need to do subtraction preserving the sign, 
843          * so we copy the fields into temporary variables.
844          *
845          * WARNING:
846          * In NT 4.0 SP3, WaitForSingleObject can occassionally timeout
847          * earlier than requested.  Therefore, our pthread_cond_timedwait
848          * can also return early.
849          */
850
851         _ftime(&now);
852         n_milli = now.millitm;
853         then.time = abstime->tv_sec;
854         t_milli = abstime->tv_nsec/1000000;
855
856         if((then.time > now.time || 
857            (then.time == now.time && t_milli > n_milli))) {
858             if((t_milli -= n_milli) < 0) {
859                 t_milli += 1000;
860                 then.time--;
861             }
862             then.time -= now.time;
863
864             if ((then.time + (clock() / CLOCKS_PER_SEC)) <= 50000000) {
865                 /*
866                  * Under NT, we can only wait for milliseconds, so we
867                  * round up the wait time here.
868                  */
869                 rc = cond_wait_internal(cond, mutex, 
870                                  ((then.time * 1000) + (t_milli)));
871             } else {
872                 rc = EINVAL;
873             }
874         } else {
875             rc = ETIME;
876         }
877     } else {
878         rc = EINVAL;
879     }
880
881     return rc;
882 }
883
884 int pthread_cond_signal(pthread_cond_t *cond) {
885     int rc = 0;
886     cond_waiters_t *release_thread;
887
888     if (cond != NULL) {
889         EnterCriticalSection(&cond->cs);
890
891         /*
892          * remove the first waiting thread from the queue
893          * and resume his execution
894          */
895         if (queue_IsNotEmpty(&cond->waiting_threads)) {
896             release_thread = queue_First(&cond->waiting_threads,
897                                          cond_waiter);
898             queue_Remove(release_thread);
899             if (!SetEvent(release_thread->event)) {
900                 rc = -1;
901             }
902         }
903
904         LeaveCriticalSection(&cond->cs);
905     } else {
906         rc = EINVAL;
907     }
908
909     return rc;
910 }
911
912 int pthread_cond_broadcast(pthread_cond_t *cond) {
913     int rc = 0;
914     cond_waiters_t *release_thread, *next_thread;
915
916     if(cond != NULL) {
917         EnterCriticalSection(&cond->cs);
918
919         /*
920          * Empty the waiting_threads queue. 
921          */
922         if (queue_IsNotEmpty(&cond->waiting_threads)) {
923             for(queue_Scan(&cond->waiting_threads, release_thread,
924                            next_thread, cond_waiter)) {
925                 queue_Remove(release_thread);
926                 if (!SetEvent(release_thread->event)) {
927                     rc = -1;
928                 }
929             }
930         }
931
932         LeaveCriticalSection(&cond->cs);
933     } else {
934         rc = EINVAL;
935     }
936
937     return rc;
938 }
939
940 int pthread_cond_destroy(pthread_cond_t *cond) {
941     int rc = 0;
942
943     if (cond != NULL) {
944         DeleteCriticalSection(&cond->cs);
945     } else {
946         rc = EINVAL;
947     }
948         
949     /*
950      * A previous version of this file had code to check the waiter
951      * queue and empty it here.  This has been removed in the hopes
952      * that it will aid in debugging.
953      */
954
955     return rc;
956 }
957
958 int pthread_join(pthread_t target_thread, void **status) {
959     int rc = 0;
960     thread_p me, target;
961     thread_p cur, next;
962
963     target = (thread_p) target_thread;
964     me = (thread_p) pthread_self();
965
966     if (me != target) {
967         /*
968          * Check to see that the target thread is joinable and hasn't
969          * already been joined.
970          */
971
972         pthread_mutex_lock(&active_Q_mutex);
973
974         for(queue_Scan(&active_Q, cur, next, thread)) {
975             if (target == cur) break;
976         }
977
978         if (target == cur) {
979             if ((!target->is_joinable) || (target->has_been_joined)) {
980                 rc = ESRCH;
981             }
982         } else {
983             rc = ESRCH;
984         }
985
986         if (rc) {
987             pthread_mutex_unlock(&active_Q_mutex);
988             return rc;
989         }
990
991         target->waiter_count++;
992         while(target->running) {
993             pthread_cond_wait(&target->wait_terminate, &active_Q_mutex);
994         }
995
996         /*
997          * Only one waiter gets the status and is allowed to join, all the
998          * others get an error.
999          */
1000
1001         if (target->has_been_joined) {
1002             rc = ESRCH;
1003         } else {
1004             target->has_been_joined = 1;
1005             if (status) {
1006                 *status = target->rc;
1007             }
1008         }
1009
1010         /*
1011          * If we're the last waiter it is our responsibility to remove
1012          * this entry from the terminated list and put it back in the
1013          * cache.
1014          */
1015
1016         target->waiter_count--;
1017         if (target->waiter_count == 0) {
1018             queue_Remove(target);
1019             pthread_mutex_unlock(&active_Q_mutex);
1020             put_thread(target);
1021         } else {
1022             pthread_mutex_unlock(&active_Q_mutex);
1023         }
1024     } else {
1025         rc = EDEADLK;
1026     }
1027
1028     return rc;
1029 }
1030
1031 /*
1032  * Note that we can't return an error from pthread_getspecific so
1033  * we return a NULL pointer instead.
1034  */
1035
1036 void *pthread_getspecific(pthread_key_t key) {
1037     void *rc = NULL;
1038     char **tsd = TlsGetValue(tsd_index);
1039
1040     if ((key > -1) && (key < PTHREAD_KEYS_MAX )) {
1041         rc = (void *) *(tsd + key);
1042     }
1043
1044     return rc;
1045 }
1046
1047 static int p_tsd_done;
1048
1049 static void pthread_tsd_init(void) {
1050     pthread_mutex_init(&pthread_tsd_mutex, (const pthread_mutexattr_t*)0);
1051     p_tsd_done = 1;
1052 }
1053
1054 int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value)) {
1055     int rc = 0;
1056     int i;
1057
1058     if (p_tsd_done || (!pthread_once(&pthread_tsd_once, pthread_tsd_init))) {
1059         if (!pthread_mutex_lock(&pthread_tsd_mutex)) {
1060             for(i=0;i<PTHREAD_KEYS_MAX;i++) {
1061                 if (!keys[i].inuse) break;
1062             }
1063
1064             if (!keys[i].inuse) {
1065                 keys[i].inuse = 1;
1066                 keys[i].destructor = destructor;
1067                 *keyp = i;
1068             } else {
1069                 rc = EAGAIN;
1070             }
1071             pthread_mutex_unlock(&pthread_tsd_mutex);
1072         } else {
1073             rc = -1;
1074         }
1075     } else {
1076         rc = -2;
1077     }
1078
1079     return rc;
1080 }
1081
1082 int pthread_key_delete(pthread_key_t key) {
1083     int rc = 0;
1084
1085     if (p_tsd_done || (!pthread_once(&pthread_tsd_once, pthread_tsd_init))) {
1086         if ((key > -1) && (key < PTHREAD_KEYS_MAX )) {
1087             if (!pthread_mutex_lock(&pthread_tsd_mutex)) {
1088                 keys[key].inuse = 0;
1089                 keys[key].destructor = NULL;
1090                 pthread_mutex_unlock(&pthread_tsd_mutex);
1091             } else {
1092                 rc = -1;
1093             }
1094         } else {
1095             rc = EINVAL;
1096         }
1097     } else {
1098         rc = -2;
1099     }
1100
1101     return rc;
1102 }
1103
1104 int pthread_setspecific(pthread_key_t key, const void *value) {
1105     int rc = 0;
1106     char **tsd;
1107
1108     if (p_tsd_done || (!pthread_once(&pthread_tsd_once, pthread_tsd_init))) {
1109         if ((key > -1) && (key < PTHREAD_KEYS_MAX )) {
1110             if (!pthread_mutex_lock(&pthread_tsd_mutex)) {
1111                 if (keys[key].inuse) {
1112                     tsd = TlsGetValue(tsd_index);
1113                     *(tsd + key) = (char *) value;
1114                 } else {
1115                     rc = EINVAL;
1116                 }
1117                 pthread_mutex_unlock(&pthread_tsd_mutex);
1118             } else {
1119                 rc = -1;
1120             }
1121         } else {
1122             rc = EINVAL;
1123         }
1124     } else {
1125       rc = -2;
1126     }
1127
1128     return rc;
1129 }
1130
1131 pthread_t pthread_self(void) {
1132     thread_p cur;
1133     DWORD my_id = GetCurrentThreadId();
1134
1135     (pthread_cache_done || pthread_once(&pthread_cache_once, create_once));
1136     (tsd_done || pthread_once(&global_tsd_once, tsd_once));
1137
1138     pthread_mutex_lock(&active_Q_mutex);
1139
1140     cur = TlsGetValue (tsd_pthread_index);
1141
1142     if(!cur) {
1143         /*
1144          * This thread's ID was not found in our list of pthread-API client
1145          * threads (e.g., those threads created via pthread_create). Create
1146          * an entry for it.
1147          */
1148         if ((cur = get_thread()) != NULL) {
1149             cur->is_joinable = 0;
1150             cur->NT_id = my_id;
1151             cur->native_thread = 1;
1152             DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
1153              GetCurrentProcess(), &cur->t_handle, 0,
1154              TRUE, DUPLICATE_SAME_ACCESS);
1155
1156             /*
1157              * We'll also need a place to store key data for this thread
1158              */
1159             if ((cur->tsd = malloc(sizeof(char*) * PTHREAD_KEYS_MAX)) != NULL) {
1160                 memset(cur->tsd, 0, (sizeof(char*) * PTHREAD_KEYS_MAX));
1161             }
1162             TlsSetValue(tsd_index, (LPVOID)cur->tsd);
1163             TlsSetValue(tsd_pthread_index, (LPVOID)cur);
1164
1165             /*
1166              * The thread_t structure is complete; add it to the active_Q
1167              */
1168             queue_Prepend(&active_Q, cur);
1169
1170             /*
1171              * We were able to successfully insert a new entry into the
1172              * active_Q; however, when this thread terminates, we will need
1173              * to know about it. The pthread_sync_terminate_thread() routine
1174              * will make sure there is a dedicated thread waiting for any
1175              * native-thread entries in the active_Q to terminate.
1176              */
1177             pthread_sync_terminate_thread();
1178         }
1179     }
1180
1181     pthread_mutex_unlock(&active_Q_mutex);
1182
1183     return (void *) cur;
1184 }
1185
1186 int pthread_equal(pthread_t t1, pthread_t t2) {
1187     return (t1 == t2);
1188 }
1189
1190 int pthread_attr_destroy(pthread_attr_t *attr) {
1191     int rc = 0;
1192
1193     return rc;
1194 }
1195
1196 int pthread_attr_init(pthread_attr_t *attr) {
1197     int rc = 0;
1198
1199     if (attr != NULL) {
1200         attr->is_joinable = PTHREAD_CREATE_JOINABLE;
1201     } else {
1202         rc = EINVAL;
1203     }
1204
1205     return rc;
1206 }
1207
1208 int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate) {
1209     int rc = 0;
1210
1211     if ((attr != NULL) && (detachstate != NULL)) {
1212             *detachstate = attr->is_joinable;
1213     } else {
1214         rc = EINVAL;
1215     }
1216     return rc;
1217 }
1218
1219 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) {
1220     int rc = 0;
1221
1222     if ((attr != NULL) && ((detachstate == PTHREAD_CREATE_JOINABLE) ||
1223         (detachstate == PTHREAD_CREATE_DETACHED))) {
1224         attr->is_joinable = detachstate;
1225     } else {
1226         rc = EINVAL;
1227     }
1228     return rc;
1229 }
1230
1231 void pthread_exit(void *status) {
1232     thread_p me = (thread_p) pthread_self();
1233
1234     /*
1235      * Support pthread_exit for thread's created by calling pthread_create
1236      * only.  Do this by using an exception that will transfer control
1237      * back to afs_pthread_create_stub.  Store away our status before
1238      * returning.
1239      *
1240      * If this turns out to be a native thread, the exception will be
1241      * unhandled and the process will terminate.
1242      */
1243
1244     me->rc = status;
1245     RaiseException(PTHREAD_EXIT_EXCEPTION, 0, 0, NULL);
1246
1247 }