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