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