24949a23447edb005039224691443b87fd41deaf
[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 = EDEADLK;
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 #ifdef PTHREAD_DEBUG
165             DebugBreak();
166 #endif
167         }
168     } else {
169 #ifdef PTHREAD_DEBUG
170         DebugBreak();
171 #endif
172         rc = EINVAL;
173     }
174         
175     return rc;
176 }
177
178 int pthread_mutex_unlock(pthread_mutex_t *mp) {
179     int rc = 0;
180
181     if (mp != NULL) {
182         if (mp->tid == GetCurrentThreadId()) {
183             mp->isLocked = 0;
184             mp->tid = 0;
185             LeaveCriticalSection(&mp->cs);
186         } else {
187 #ifdef PTHREAD_DEBUG
188             DebugBreak();
189 #endif
190             rc = EPERM;
191         }
192     } else {
193 #ifdef PTHREAD_DEBUG
194         DebugBreak();
195 #endif
196         rc = EINVAL;
197     }
198     return rc;
199 }
200
201 int pthread_mutex_destroy(pthread_mutex_t *mp) {
202     int rc = 0;
203
204     if (mp != NULL) {
205         DeleteCriticalSection(&mp->cs);
206     } else {
207 #ifdef PTHREAD_DEBUG
208         DebugBreak();
209 #endif
210         rc = EINVAL;
211     }
212
213     return rc;
214 }
215
216 /*
217  * keys is used to keep track of which keys are currently
218  * in use by the threads library.  pthread_tsd_mutex is used
219  * to protect keys.
220  *
221  * The bookkeeping for keys in use and destructor function/key is
222  * at the library level.  Each individual thread only keeps its
223  * per key data value.  This implies that the keys array and the
224  * tsd array in the pthread_t structure need to always be exactly
225  * the same size since the same index is used for both arrays.
226  */
227
228 typedef struct {
229     int inuse;
230     void (*destructor)(void *);
231 } pthread_tsd_table_t;
232
233 static pthread_tsd_table_t keys[PTHREAD_KEYS_MAX];
234 static pthread_mutex_t pthread_tsd_mutex;
235 static pthread_once_t pthread_tsd_once = PTHREAD_ONCE_INIT;
236
237 /*
238  * In order to support p_self() and p_join() under NT,
239  * we have to keep our own list of active threads and provide a mapping
240  * function that maps the NT thread id to our internal structure.
241  * The main reason that this is necessary is that GetCurrentThread
242  * returns a special constant not an actual handle to the thread.
243  * This makes it impossible to write a p_self() function that works
244  * with only the native NT functions.
245  */
246
247 static struct rx_queue active_Q;
248 static struct rx_queue cache_Q;
249
250 static pthread_mutex_t active_Q_mutex;
251 static pthread_mutex_t cache_Q_mutex;
252
253 static pthread_once_t pthread_cache_once = PTHREAD_ONCE_INIT;
254 static int pthread_cache_done;
255
256 typedef struct thread {
257     struct rx_queue thread_queue;
258     void *rc;
259     int running;
260     pthread_cond_t wait_terminate;
261     int waiter_count;
262     int is_joinable;
263     int has_been_joined;
264     HANDLE t_handle;
265     DWORD NT_id;
266     int native_thread;
267     char **tsd;
268 } thread_t, *thread_p;
269
270 static void create_once(void) {
271     queue_Init(&active_Q);
272     queue_Init(&cache_Q);
273     pthread_mutex_init(&active_Q_mutex, (const pthread_mutexattr_t*)0);
274     pthread_mutex_init(&cache_Q_mutex, (const pthread_mutexattr_t*)0);
275     pthread_cache_done = 1;
276 }
277
278 static void cleanup_pthread_cache(void) {
279     thread_p cur = NULL, next = NULL;
280
281     if (pthread_cache_done) {
282         for(queue_Scan(&active_Q, cur, next, thread)) {
283             queue_Remove(cur);
284         }
285         for(queue_Scan(&cache_Q, cur, next, thread)) {
286             queue_Remove(cur);
287         }
288
289         pthread_mutex_destroy(&active_Q_mutex);
290         pthread_mutex_destroy(&cache_Q_mutex);
291
292         pthread_cache_done = 0;
293     }
294 }       
295
296 static void put_thread(thread_p old) {
297  
298     CloseHandle(old->t_handle);
299     pthread_mutex_lock(&cache_Q_mutex);
300     queue_Prepend(&cache_Q, old);
301     pthread_mutex_unlock(&cache_Q_mutex);
302 }
303
304 static thread_p get_thread() {
305     thread_p new = NULL;
306  
307     pthread_mutex_lock(&cache_Q_mutex);
308  
309     if (queue_IsEmpty(&cache_Q)) {
310         new = (thread_p) malloc(sizeof(thread_t));
311         if (new != NULL) {
312             /*
313              * One time initialization - we assume threads put back have
314              * unlocked mutexes and condition variables with no waiters
315              *
316              * These functions cannot fail currently.
317              */
318             pthread_cond_init(&new->wait_terminate,(const pthread_condattr_t *)0);
319         }
320     } else {
321         new = queue_First(&cache_Q, thread);
322         queue_Remove(new);
323     }
324  
325     pthread_mutex_unlock(&cache_Q_mutex);
326
327     /* 
328      * Initialization done every time we hand out a thread_t
329      */
330
331     if (new != NULL) {
332         new->rc = NULL;
333         new->running = 1;
334         new->waiter_count = 0;
335         new->has_been_joined = 0;
336     }
337     return new;
338  
339 }
340  
341 /*
342  * The thread start function signature is different on NT than the pthread
343  * spec so we create a tiny stub to map from one signature to the next.
344  * This assumes that a void * can be stored within a DWORD.
345  */
346
347 typedef struct {
348     void *(*func)(void *);
349     void *arg;
350     char *tsd[PTHREAD_KEYS_MAX];
351     thread_p me;
352 } pthread_create_t;
353
354 static DWORD tsd_index = 0xffffffff;
355 static DWORD tsd_pthread_index = 0xffffffff;
356 static pthread_once_t global_tsd_once = PTHREAD_ONCE_INIT;
357 static int tsd_done;
358
359 static void tsd_once(void) {
360     while(tsd_index == 0xffffffff) {
361         tsd_index = TlsAlloc();
362     }
363     while(tsd_pthread_index == 0xffffffff) {
364         tsd_pthread_index = TlsAlloc();
365     }
366     tsd_done = 1;
367 }
368
369 static void tsd_free_all(char *tsd[PTHREAD_KEYS_MAX]) {
370     int call_more_destructors = 0;
371     do {
372         int i;
373         void *value;
374         void (*destructor)(void *);
375         call_more_destructors = 0;
376         for(i=0;i<PTHREAD_KEYS_MAX;i++) {
377             if (tsd[i] != NULL) {
378                 destructor = keys[i].destructor;
379                 value = (void *)tsd[i];
380                 tsd[i] = NULL;
381                 if (destructor != NULL) {
382                     (destructor)(value);
383                     /*
384                      * A side-effect of calling a destructor function is that
385                      * more thread specific may be created for this thread.
386                      * If we call a destructor, we must recycle through the
387                      * entire list again and run any new destructors.
388                      */
389                     call_more_destructors = 1;
390                 }
391             }
392         }
393     } while(call_more_destructors);
394 }
395
396 static void cleanup_global_tsd(void)
397 {
398     thread_p cur = NULL, next = NULL;
399
400     if (tsd_done) {
401         for(queue_Scan(&active_Q, cur, next, thread)) {
402             tsd_free_all(cur->tsd);
403         }
404
405         TlsFree(tsd_pthread_index);
406         tsd_pthread_index = 0xFFFFFFFF;
407         TlsFree(tsd_index);
408         tsd_index = 0xFFFFFFFF;
409         tsd_done = 0;
410     }
411 }
412
413 static DWORD WINAPI afs_pthread_create_stub(LPVOID param) {
414     pthread_create_t *t = (pthread_create_t *) param;
415     void *rc;
416
417     /* 
418      * Initialize thread specific storage structures.
419      */
420
421     memset(t->tsd, 0, (sizeof(char *) * PTHREAD_KEYS_MAX));
422     (tsd_done || pthread_once(&global_tsd_once, tsd_once));
423     TlsSetValue(tsd_index, (LPVOID) (t->tsd));
424     TlsSetValue(tsd_pthread_index, (LPVOID) (t->me));
425
426     /*
427      * Call the function the user passed to pthread_create and catch the
428      * pthread exit exception if it is raised.
429      */
430
431     __try {
432         rc = (*(t->func))(t->arg);
433     } __except(GetExceptionCode() == PTHREAD_EXIT_EXCEPTION) {
434         rc = t->me->rc; /* rc is set at pthread_exit */
435     }
436
437     /*
438      * Cycle through the thread specific data for this thread and
439      * call the destructor function for each non-NULL datum
440      */
441
442     tsd_free_all (t->tsd);
443     t->me->tsd = NULL;
444
445     /*
446      * If we are joinable, signal any waiters.
447      */
448
449     pthread_mutex_lock(&active_Q_mutex);
450     if (t->me->is_joinable) {
451         t->me->running = 0;
452         t->me->rc = rc;
453         if (t->me->waiter_count) {
454             pthread_cond_broadcast(&t->me->wait_terminate);
455         }
456     } else {
457         queue_Remove(t->me);
458         put_thread(t->me);
459     }
460     pthread_mutex_unlock(&active_Q_mutex);
461
462     free(t);
463     return 0;
464 }
465
466 /*
467  * If a pthread function is called on a thread which was not created by
468  * pthread_create(), that thread will have an entry added to the active_Q
469  * by pthread_self(). When the thread terminates, we need to know
470  * about it, so that we can perform cleanup. A dedicated thread is therefore
471  * maintained, which watches for any thread marked "native_thread==1"
472  * in the active_Q to terminate. The thread spends most of its time sleeping:
473  * it can be signalled by a dedicated event in order to alert it to the
474  * presense of a new thread to watch, or will wake up automatically when
475  * a native thread terminates.
476  */
477
478 static DWORD terminate_thread_id = 0;
479 static HANDLE terminate_thread_handle = INVALID_HANDLE_VALUE;
480 static HANDLE terminate_thread_wakeup_event = INVALID_HANDLE_VALUE;
481 static HANDLE *terminate_thread_wakeup_list = NULL;
482 static size_t terminate_thread_wakeup_list_size = 0;
483
484 static DWORD WINAPI terminate_thread_routine(LPVOID param) {
485     thread_p cur, next;
486     DWORD native_thread_count;
487     int should_terminate;
488     int terminate_thread_wakeup_list_index;
489
490     for (;;) {
491         /*
492          * Grab the active_Q_mutex, and while we hold it, scan the active_Q
493          * to see how many native threads we need to watch. If we don't need
494          * to watch any, we can stop this watcher thread entirely (or not);
495          * if we do need to watch some, fill the terminate_thread_wakeup_list
496          * array and go to sleep.
497          */
498         cur = NULL;
499         next = NULL;
500         native_thread_count = 0;
501         should_terminate = FALSE;
502         pthread_mutex_lock(&active_Q_mutex);
503
504         for(queue_Scan(&active_Q, cur, next, thread)) {
505             if (cur->native_thread)
506                 ++native_thread_count;
507         }
508
509         /*
510          * At this point we could decide to terminate this watcher thread
511          * whenever there are no longer any native threads to watch--however,
512          * since thread creation is a time-consuming thing, and since this
513          * thread spends all its time sleeping anyway, there's no real
514          * compelling reason to do so. Thus, the following statement is
515          * commented out:
516          *
517          * if (!native_thread_count) {
518          *    should_terminate = TRUE;
519          * }
520          *
521          * Restore the snippet above to cause this watcher thread to only
522          * live whenever there are native threads to watch.
523          *
524          */
525
526         /*
527          * Make sure that our wakeup_list array is large enough to contain
528          * the handles of all the native threads /and/ to contain an
529          * entry for our wakeup_event (in case another native thread comes
530          * along).
531          */
532         if (terminate_thread_wakeup_list_size < (1+native_thread_count)) {
533             if (terminate_thread_wakeup_list)
534                 free (terminate_thread_wakeup_list);
535             terminate_thread_wakeup_list = (HANDLE*)malloc (sizeof(HANDLE) *
536                                 (1+native_thread_count));
537             if (terminate_thread_wakeup_list == NULL) {
538                 should_terminate = TRUE;
539             } else {
540                 terminate_thread_wakeup_list_size = 1+native_thread_count;
541             }
542         }
543
544         if (should_terminate) {
545             /*
546              * Here, we've decided to terminate this watcher thread.
547              * Free our wakeup event and wakeup list, then release the
548              * active_Q_mutex and break this loop.
549              */
550             if (terminate_thread_wakeup_list)
551                 free (terminate_thread_wakeup_list);
552             CloseHandle (terminate_thread_wakeup_event);
553             terminate_thread_id = 0;
554             terminate_thread_handle = INVALID_HANDLE_VALUE;
555             terminate_thread_wakeup_event = INVALID_HANDLE_VALUE;
556             terminate_thread_wakeup_list = NULL;
557             terminate_thread_wakeup_list_size = 0;
558             pthread_mutex_unlock(&active_Q_mutex);
559             break;
560         } else {
561             /*
562              * Here, we've decided to wait for native threads et al.
563              * Fill out the wakeup_list.
564              */
565             memset(terminate_thread_wakeup_list, 0x00, (sizeof(HANDLE) * 
566                                 (1+native_thread_count)));
567
568             terminate_thread_wakeup_list[0] = terminate_thread_wakeup_event;
569             terminate_thread_wakeup_list_index = 1;
570
571             cur = NULL;
572             next = NULL;
573             for(queue_Scan(&active_Q, cur, next, thread)) {
574                 if (cur->native_thread) {
575                     terminate_thread_wakeup_list[terminate_thread_wakeup_list_index]
576                         = cur->t_handle;
577                     ++terminate_thread_wakeup_list_index;
578                 }
579             }
580
581             ResetEvent (terminate_thread_wakeup_event);
582         }
583
584         pthread_mutex_unlock(&active_Q_mutex);
585
586         /*
587          * Time to sleep. We'll wake up if either of the following happen:
588          * 1) Someone sets the terminate_thread_wakeup_event (this will
589          *    happen if another native thread gets added to the active_Q)
590          * 2) One or more of the native threads terminate
591          */
592         terminate_thread_wakeup_list_index = WaitForMultipleObjects(
593                                         1+native_thread_count,
594                                         terminate_thread_wakeup_list,
595                                         FALSE,
596                                         INFINITE);
597
598         /*
599          * If we awoke from sleep because an event other than
600          * terminate_thread_wakeup_event was triggered, it means the
601          * specified thread has terminated. (If more than one thread
602          * terminated, we'll handle this first one and loop around--
603          * the event's handle will still be triggered, so we just won't
604          * block at all when we sleep next time around.)
605          */
606         if (terminate_thread_wakeup_list_index > 0) {
607             pthread_mutex_lock(&active_Q_mutex);
608
609             cur = NULL;
610             next = NULL;
611             for(queue_Scan(&active_Q, cur, next, thread)) {
612                 if (cur->t_handle == terminate_thread_wakeup_list[ terminate_thread_wakeup_list_index ])
613                     break;
614             }
615
616             if(cur != NULL) {
617                 /*
618                  * Cycle through the thread specific data for the specified
619                  * thread and call the destructor function for each non-NULL
620                  * datum. Then remove the thread_t from active_Q and put it
621                  * back on cache_Q for possible later re-use.
622                  */
623                 if(cur->tsd != NULL) {
624                     tsd_free_all(cur->tsd);
625                     free(cur->tsd);
626                     cur->tsd = NULL;
627                 }
628                 queue_Remove(cur);
629                 put_thread(cur);
630             }
631
632             pthread_mutex_unlock(&active_Q_mutex);
633         }
634     }
635     return 0;
636 }
637
638
639 static void pthread_sync_terminate_thread(void) {
640     (pthread_cache_done || pthread_once(&pthread_cache_once, create_once));
641
642     if (terminate_thread_handle == INVALID_HANDLE_VALUE) {
643         CHAR eventName[MAX_PATH];
644         static eventCount = 0;
645         sprintf(eventName, "terminate_thread_wakeup_event %d::%d", _getpid(), eventCount++);
646         terminate_thread_wakeup_event = CreateEvent((LPSECURITY_ATTRIBUTES) 0,
647                                                      TRUE, FALSE, (LPCTSTR) eventName);
648         terminate_thread_handle = CreateThread((LPSECURITY_ATTRIBUTES) 0, 0, 
649                                                 terminate_thread_routine, (LPVOID) 0, 0, 
650                                                 &terminate_thread_id);
651     } else {
652         SetEvent (terminate_thread_wakeup_event);
653     }
654 }
655
656
657 /*
658  * Only support the detached attribute specifier for pthread_create.
659  * Under NT, thread stacks grow automatically as needed.
660  */
661
662 int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func)(void *), void *arg) {
663     int rc = 0;
664     pthread_create_t *t = NULL;
665
666     (pthread_cache_done || pthread_once(&pthread_cache_once, create_once));
667
668     if ((tid != NULL) && (func != NULL)) {
669         if ((t = (pthread_create_t *) malloc(sizeof(pthread_create_t))) &&
670             (t->me = get_thread()) ) {
671             t->func = func;
672             t->arg = arg;
673             *tid = (pthread_t) t->me;
674             if (attr != NULL) {
675                 t->me->is_joinable = attr->is_joinable;
676             } else {
677                 t->me->is_joinable = PTHREAD_CREATE_JOINABLE;
678             }
679             t->me->native_thread = 0;
680             t->me->tsd = t->tsd;
681             /*
682              * At the point (before we actually create the thread)
683              * we need to add our entry to the active queue.  This ensures
684              * us that other threads who may run after this thread returns
685              * will find an entry for the create thread regardless of
686              * whether the newly created thread has run or not.
687              * In the event the thread create fails, we will have temporarily
688              * added an entry to the list that was never valid, but we
689              * (i.e. the thread that is calling thread_create) are the
690              * only one who could possibly know about the bogus entry
691              * since we hold the active_Q_mutex.
692              */
693             pthread_mutex_lock(&active_Q_mutex);
694             queue_Prepend(&active_Q, t->me);
695             t->me->t_handle = CreateThread((LPSECURITY_ATTRIBUTES) 0, 0, 
696                                 afs_pthread_create_stub, (LPVOID) t, 0, 
697                                 &t->me->NT_id);
698             if (t->me->t_handle == 0) {
699                 /* 
700                  * we only free t if the thread wasn't created, otherwise
701                  * it's free'd by the new thread.
702                  */
703                 queue_Remove(t->me);
704                 put_thread(t->me);
705                 free(t);
706                 rc = EAGAIN;
707             }
708             pthread_mutex_unlock(&active_Q_mutex);
709         } else {
710             if (t != NULL) {
711                 free(t);
712             }
713             rc = ENOMEM;
714         }
715     } else {
716         rc = EINVAL;
717     }
718     return rc;
719 }
720
721 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) {
722     int rc = 0;
723
724     /*
725      * Only support default attribute -> must pass a NULL pointer for
726      * attr parameter.
727      */
728     if ((attr == NULL) && (cond != NULL)) {
729         InitializeCriticalSection(&cond->cs);
730         queue_Init(&cond->waiting_threads);
731     } else {
732         rc = EINVAL;
733     }
734
735     return rc;
736 }
737
738 /*
739  * In order to optimize the performance of condition variables,
740  * we maintain a pool of cond_waiter_t's that have been dynamically
741  * allocated.  There is no attempt made to garbage collect these -
742  * once they have been created, they stay in the cache for the life
743  * of the process.
744  */
745  
746 static struct rx_queue waiter_cache;
747 static CRITICAL_SECTION waiter_cache_cs;
748 static int waiter_cache_init;
749 static pthread_once_t waiter_cache_once = PTHREAD_ONCE_INIT;
750  
751 static void init_waiter_cache(void) {
752     InitializeCriticalSection(&waiter_cache_cs);
753     queue_Init(&waiter_cache);
754     waiter_cache_init = 1;
755 }
756  
757 static void cleanup_waiter_cache(void)
758 {
759     cond_waiters_t * cur = NULL, * next = NULL;
760
761     if (waiter_cache_init) {
762         for(queue_Scan(&waiter_cache, cur, next, cond_waiter)) {
763             queue_Remove(cur);
764
765             CloseHandle(cur->event);
766             free(cur);
767         }
768
769         DeleteCriticalSection(&waiter_cache_cs);
770         waiter_cache_init = 0;
771     }
772 }
773
774 static cond_waiters_t *get_waiter() {
775     cond_waiters_t *new = NULL;
776  
777     (waiter_cache_init || pthread_once(&waiter_cache_once, init_waiter_cache));
778  
779     EnterCriticalSection(&waiter_cache_cs);
780  
781     if (queue_IsEmpty(&waiter_cache)) {
782         new = (cond_waiters_t *) malloc(sizeof(cond_waiters_t));
783         if (new != NULL) {
784         CHAR eventName[MAX_PATH];
785         static eventCount = 0;
786         sprintf(eventName, "cond_waiters_t %d::%d", _getpid(), eventCount++);
787         new->event = CreateEvent((LPSECURITY_ATTRIBUTES) 0, FALSE,
788                                   FALSE, (LPCTSTR) eventName);
789             if (new->event == NULL) {
790                 free(new);
791                 new = NULL;
792             }
793         }
794     } else {
795         new = queue_First(&waiter_cache, cond_waiter);
796         queue_Remove(new);
797     }
798  
799     LeaveCriticalSection(&waiter_cache_cs);
800     return new;
801  
802 }
803  
804 static void put_waiter(cond_waiters_t *old) {
805  
806     (waiter_cache_init || pthread_once(&waiter_cache_once, init_waiter_cache));
807  
808     EnterCriticalSection(&waiter_cache_cs);
809     queue_Prepend(&waiter_cache, old);
810     LeaveCriticalSection(&waiter_cache_cs);
811 }
812
813 static int cond_wait_internal(pthread_cond_t *cond, pthread_mutex_t *mutex, const DWORD time) {
814     int rc=0;
815     cond_waiters_t *my_entry = get_waiter();
816     cond_waiters_t *cur, *next;
817     int hasnt_been_signalled=0;
818
819     if ((cond != NULL) && (mutex != NULL) && (my_entry != NULL)) {
820         EnterCriticalSection(&cond->cs);
821         queue_Append(&cond->waiting_threads, my_entry);
822         LeaveCriticalSection(&cond->cs);
823
824         if (pthread_mutex_unlock(mutex) == 0) {
825             switch(WaitForSingleObject(my_entry->event, time)) {
826             case WAIT_FAILED:
827                 rc = -1;
828                 break;
829             case WAIT_TIMEOUT:
830                 rc = ETIMEDOUT;
831                 /*
832                  * This is a royal pain.  We've timed out waiting
833                  * for the signal, but between the time out and here
834                  * it is possible that we were actually signalled by 
835                  * another thread.  So we grab the condition lock
836                  * and scan the waiting thread queue to see if we are
837                  * still there.  If we are, we just remove ourselves.
838                  *
839                  * If we are no longer listed in the waiter queue,
840                  * it means that we were signalled after the time
841                  * out occurred and so we have to do another wait
842                  * WHICH HAS TO SUCCEED!  In this case, we reset
843                  * rc to indicate that we were signalled.
844                  *
845                  * We have to wait or otherwise, the event
846                  * would be cached in the signalled state, which
847                  * is wrong.  It might be more efficient to just
848                  * close and reopen the event.
849                  */
850                 EnterCriticalSection(&cond->cs);
851                 for(queue_Scan(&cond->waiting_threads, cur,
852                                 next, cond_waiter)) {
853                     if (cur == my_entry) {
854                         hasnt_been_signalled = 1;
855                         break;
856                     }
857                 }
858                 if (hasnt_been_signalled) {
859                     queue_Remove(cur);
860                 } else {
861                     rc = 0;
862                     if (!ResetEvent(my_entry->event)) {
863                         rc = -6;
864                     }
865                 }
866                 LeaveCriticalSection(&cond->cs);
867                 break;
868             case WAIT_ABANDONED:
869                 rc = -2;
870                 break;
871             case WAIT_OBJECT_0:
872                 rc = 0;
873                 break;
874             default:
875                 rc = -4;
876                 break;
877             }
878             if (pthread_mutex_lock(mutex) != 0) {
879                 rc = -3;
880             }   
881         } else {
882             rc = EINVAL;
883         }
884     } else {
885         rc = EINVAL;
886     }
887
888     if (my_entry != NULL) {
889         put_waiter(my_entry);
890     }
891
892     return rc;
893 }
894
895 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
896     int rc = 0;
897
898     rc = cond_wait_internal(cond, mutex, INFINITE);
899     return rc;
900 }
901
902 int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) {
903     int rc = 0;
904     struct _timeb now, then;
905     afs_uint32 n_milli, t_milli;
906
907     if (abstime->tv_nsec < 1000000000) {
908
909         /*
910          * pthread timedwait uses an absolute time, NT uses relative so
911          * we convert here.  The millitm field in the timeb struct is
912          * unsigned, but we need to do subtraction preserving the sign, 
913          * so we copy the fields into temporary variables.
914          *
915          * WARNING:
916          * In NT 4.0 SP3, WaitForSingleObject can occassionally timeout
917          * earlier than requested.  Therefore, our pthread_cond_timedwait
918          * can also return early.
919          */
920
921         _ftime(&now);
922         n_milli = now.millitm;
923         then.time = abstime->tv_sec;
924         t_milli = abstime->tv_nsec/1000000;
925
926         if((then.time > now.time || 
927            (then.time == now.time && t_milli > n_milli))) {
928             if((t_milli -= n_milli) < 0) {
929                 t_milli += 1000;
930                 then.time--;
931             }
932             then.time -= now.time;
933
934             if ((then.time + (clock() / CLOCKS_PER_SEC)) <= 50000000) {
935                 /*
936                  * Under NT, we can only wait for milliseconds, so we
937                  * round up the wait time here.
938                  */
939                 rc = cond_wait_internal(cond, mutex, 
940                                  (DWORD)((then.time * 1000) + (t_milli)));
941             } else {
942                 rc = EINVAL;
943             }
944         } else {
945             rc = ETIME;
946         }
947     } else {
948         rc = EINVAL;
949     }
950
951     return rc;
952 }
953
954 int pthread_cond_signal(pthread_cond_t *cond) {
955     int rc = 0;
956     cond_waiters_t *release_thread;
957
958     if (cond != NULL) {
959         EnterCriticalSection(&cond->cs);
960
961         /*
962          * remove the first waiting thread from the queue
963          * and resume his execution
964          */
965         if (queue_IsNotEmpty(&cond->waiting_threads)) {
966             release_thread = queue_First(&cond->waiting_threads,
967                                          cond_waiter);
968             queue_Remove(release_thread);
969             if (!SetEvent(release_thread->event)) {
970                 rc = -1;
971             }
972         }
973
974         LeaveCriticalSection(&cond->cs);
975     } else {
976         rc = EINVAL;
977     }
978
979     return rc;
980 }
981
982 int pthread_cond_broadcast(pthread_cond_t *cond) {
983     int rc = 0;
984     cond_waiters_t *release_thread, *next_thread;
985
986     if(cond != NULL) {
987         EnterCriticalSection(&cond->cs);
988
989         /*
990          * Empty the waiting_threads queue. 
991          */
992         if (queue_IsNotEmpty(&cond->waiting_threads)) {
993             for(queue_Scan(&cond->waiting_threads, release_thread,
994                            next_thread, cond_waiter)) {
995                 queue_Remove(release_thread);
996                 if (!SetEvent(release_thread->event)) {
997                     rc = -1;
998                 }
999             }
1000         }
1001
1002         LeaveCriticalSection(&cond->cs);
1003     } else {
1004         rc = EINVAL;
1005     }
1006
1007     return rc;
1008 }
1009
1010 int pthread_cond_destroy(pthread_cond_t *cond) {
1011     int rc = 0;
1012
1013     if (cond != NULL) {
1014         DeleteCriticalSection(&cond->cs);
1015     } else {
1016         rc = EINVAL;
1017     }
1018         
1019     /*
1020      * A previous version of this file had code to check the waiter
1021      * queue and empty it here.  This has been removed in the hopes
1022      * that it will aid in debugging.
1023      */
1024
1025     return rc;
1026 }
1027
1028 int pthread_join(pthread_t target_thread, void **status) {
1029     int rc = 0;
1030     thread_p me, target;
1031     thread_p cur, next;
1032
1033     target = (thread_p) target_thread;
1034     me = (thread_p) pthread_self();
1035
1036     if (me != target) {
1037         /*
1038          * Check to see that the target thread is joinable and hasn't
1039          * already been joined.
1040          */
1041
1042         pthread_mutex_lock(&active_Q_mutex);
1043
1044         for(queue_Scan(&active_Q, cur, next, thread)) {
1045             if (target == cur) break;
1046         }
1047
1048         if (target == cur) {
1049             if ((!target->is_joinable) || (target->has_been_joined)) {
1050                 rc = ESRCH;
1051             }
1052         } else {
1053             rc = ESRCH;
1054         }
1055
1056         if (rc) {
1057             pthread_mutex_unlock(&active_Q_mutex);
1058             return rc;
1059         }
1060
1061         target->waiter_count++;
1062         while(target->running) {
1063             pthread_cond_wait(&target->wait_terminate, &active_Q_mutex);
1064         }
1065
1066         /*
1067          * Only one waiter gets the status and is allowed to join, all the
1068          * others get an error.
1069          */
1070
1071         if (target->has_been_joined) {
1072             rc = ESRCH;
1073         } else {
1074             target->has_been_joined = 1;
1075             if (status) {
1076                 *status = target->rc;
1077             }
1078         }
1079
1080         /*
1081          * If we're the last waiter it is our responsibility to remove
1082          * this entry from the terminated list and put it back in the
1083          * cache.
1084          */
1085
1086         target->waiter_count--;
1087         if (target->waiter_count == 0) {
1088             queue_Remove(target);
1089             pthread_mutex_unlock(&active_Q_mutex);
1090             put_thread(target);
1091         } else {
1092             pthread_mutex_unlock(&active_Q_mutex);
1093         }
1094     } else {
1095         rc = EDEADLK;
1096     }
1097
1098     return rc;
1099 }
1100
1101 /*
1102  * Note that we can't return an error from pthread_getspecific so
1103  * we return a NULL pointer instead.
1104  */
1105
1106 void *pthread_getspecific(pthread_key_t key) {
1107     void *rc = NULL;
1108     char **tsd = TlsGetValue(tsd_index);
1109
1110     if (tsd == NULL)
1111         return NULL;
1112
1113     if ((key > -1) && (key < PTHREAD_KEYS_MAX )) {
1114         rc = (void *) *(tsd + key);
1115     }
1116
1117     return rc;
1118 }
1119
1120 static int p_tsd_done;
1121
1122 static void pthread_tsd_init(void) {
1123     pthread_mutex_init(&pthread_tsd_mutex, (const pthread_mutexattr_t*)0);
1124     p_tsd_done = 1;
1125 }
1126
1127 int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value)) {
1128     int rc = 0;
1129     int i;
1130
1131     if (p_tsd_done || (!pthread_once(&pthread_tsd_once, pthread_tsd_init))) {
1132         if (!pthread_mutex_lock(&pthread_tsd_mutex)) {
1133             for(i=0;i<PTHREAD_KEYS_MAX;i++) {
1134                 if (!keys[i].inuse) break;
1135             }
1136
1137             if (!keys[i].inuse) {
1138                 keys[i].inuse = 1;
1139                 keys[i].destructor = destructor;
1140                 *keyp = i;
1141             } else {
1142                 rc = EAGAIN;
1143             }
1144             pthread_mutex_unlock(&pthread_tsd_mutex);
1145         } else {
1146             rc = -1;
1147         }
1148     } else {
1149         rc = -2;
1150     }
1151
1152     return rc;
1153 }
1154
1155 int pthread_key_delete(pthread_key_t key) {
1156     int rc = 0;
1157
1158     if (p_tsd_done || (!pthread_once(&pthread_tsd_once, pthread_tsd_init))) {
1159         if ((key > -1) && (key < PTHREAD_KEYS_MAX )) {
1160             if (!pthread_mutex_lock(&pthread_tsd_mutex)) {
1161                 keys[key].inuse = 0;
1162                 keys[key].destructor = NULL;
1163                 pthread_mutex_unlock(&pthread_tsd_mutex);
1164             } else {
1165                 rc = -1;
1166             }
1167         } else {
1168             rc = EINVAL;
1169         }
1170     } else {
1171         rc = -2;
1172     }
1173
1174     return rc;
1175 }
1176
1177 int pthread_setspecific(pthread_key_t key, const void *value) {
1178     int rc = 0;
1179     char **tsd;
1180
1181     /* make sure all thread-local storage has been allocated */
1182     pthread_self();
1183
1184     if (p_tsd_done || (!pthread_once(&pthread_tsd_once, pthread_tsd_init))) {
1185         if ((key > -1) && (key < PTHREAD_KEYS_MAX )) {
1186             if (!pthread_mutex_lock(&pthread_tsd_mutex)) {
1187                 if (keys[key].inuse) {
1188                     tsd = TlsGetValue(tsd_index);
1189                     *(tsd + key) = (char *) value;
1190                 } else {
1191                     rc = EINVAL;
1192                 }
1193                 pthread_mutex_unlock(&pthread_tsd_mutex);
1194             } else {
1195                 rc = -1;
1196             }
1197         } else {
1198             rc = EINVAL;
1199         }
1200     } else {
1201       rc = -2;
1202     }
1203
1204     return rc;
1205 }
1206
1207 pthread_t pthread_self(void) {
1208     thread_p cur;
1209     DWORD my_id = GetCurrentThreadId();
1210
1211     (pthread_cache_done || pthread_once(&pthread_cache_once, create_once));
1212     (tsd_done || pthread_once(&global_tsd_once, tsd_once));
1213
1214     pthread_mutex_lock(&active_Q_mutex);
1215
1216     cur = TlsGetValue (tsd_pthread_index);
1217
1218     if(!cur) {
1219         /*
1220          * This thread's ID was not found in our list of pthread-API client
1221          * threads (e.g., those threads created via pthread_create). Create
1222          * an entry for it.
1223          */
1224         if ((cur = get_thread()) != NULL) {
1225             cur->is_joinable = 0;
1226             cur->NT_id = my_id;
1227             cur->native_thread = 1;
1228             DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
1229              GetCurrentProcess(), &cur->t_handle, 0,
1230              TRUE, DUPLICATE_SAME_ACCESS);
1231
1232             /*
1233              * We'll also need a place to store key data for this thread
1234              */
1235             if ((cur->tsd = malloc(sizeof(char*) * PTHREAD_KEYS_MAX)) != NULL) {
1236                 memset(cur->tsd, 0, (sizeof(char*) * PTHREAD_KEYS_MAX));
1237             }
1238             TlsSetValue(tsd_index, (LPVOID)cur->tsd);
1239             TlsSetValue(tsd_pthread_index, (LPVOID)cur);
1240
1241             /*
1242              * The thread_t structure is complete; add it to the active_Q
1243              */
1244             queue_Prepend(&active_Q, cur);
1245
1246             /*
1247              * We were able to successfully insert a new entry into the
1248              * active_Q; however, when this thread terminates, we will need
1249              * to know about it. The pthread_sync_terminate_thread() routine
1250              * will make sure there is a dedicated thread waiting for any
1251              * native-thread entries in the active_Q to terminate.
1252              */
1253             pthread_sync_terminate_thread();
1254         }
1255     }
1256
1257     pthread_mutex_unlock(&active_Q_mutex);
1258
1259     return (void *) cur;
1260 }
1261
1262 int pthread_equal(pthread_t t1, pthread_t t2) {
1263     return (t1 == t2);
1264 }
1265
1266 int pthread_attr_destroy(pthread_attr_t *attr) {
1267     int rc = 0;
1268
1269     return rc;
1270 }
1271
1272 int pthread_attr_init(pthread_attr_t *attr) {
1273     int rc = 0;
1274
1275     if (attr != NULL) {
1276         attr->is_joinable = PTHREAD_CREATE_JOINABLE;
1277     } else {
1278         rc = EINVAL;
1279     }
1280
1281     return rc;
1282 }
1283
1284 int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate) {
1285     int rc = 0;
1286
1287     if ((attr != NULL) && (detachstate != NULL)) {
1288             *detachstate = attr->is_joinable;
1289     } else {
1290         rc = EINVAL;
1291     }
1292     return rc;
1293 }
1294
1295 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) {
1296     int rc = 0;
1297
1298     if ((attr != NULL) && ((detachstate == PTHREAD_CREATE_JOINABLE) ||
1299         (detachstate == PTHREAD_CREATE_DETACHED))) {
1300         attr->is_joinable = detachstate;
1301     } else {
1302         rc = EINVAL;
1303     }
1304     return rc;
1305 }
1306
1307 void pthread_exit(void *status) {
1308     thread_p me = (thread_p) pthread_self();
1309
1310     /*
1311      * Support pthread_exit for thread's created by calling pthread_create
1312      * only.  Do this by using an exception that will transfer control
1313      * back to afs_pthread_create_stub.  Store away our status before
1314      * returning.
1315      *
1316      * If this turns out to be a native thread, the exception will be
1317      * unhandled and the process will terminate.
1318      */
1319
1320     me->rc = status;
1321     RaiseException(PTHREAD_EXIT_EXCEPTION, 0, 0, NULL);
1322
1323 }
1324
1325 /*
1326  * DllMain() -- Entry-point function called by the DllMainCRTStartup()
1327  *     function in the MSVC runtime DLL (msvcrt.dll).
1328  *
1329  *     Note: the system serializes calls to this function.
1330  */
1331 BOOL WINAPI
1332 DllMain(HINSTANCE dllInstHandle,/* instance handle for this DLL module */
1333         DWORD reason,           /* reason function is being called */
1334         LPVOID reserved)
1335 {                               /* reserved for future use */
1336     switch (reason) {
1337     case DLL_PROCESS_ATTACH:
1338         /* library is being attached to a process */
1339         /* disable thread attach/detach notifications */
1340         (void)DisableThreadLibraryCalls(dllInstHandle);
1341
1342         pthread_once(&pthread_cache_once, create_once);
1343         pthread_once(&global_tsd_once, tsd_once);
1344         pthread_once(&waiter_cache_once, init_waiter_cache);
1345         return TRUE;
1346
1347     case DLL_PROCESS_DETACH:
1348         cleanup_waiter_cache();
1349         cleanup_global_tsd();
1350         cleanup_pthread_cache();
1351         return TRUE;
1352
1353     default:
1354         return FALSE;
1355     }
1356 }
1357