1dad63ef47614f575acff6b9415dd9d38e07efdd
[npth.git] / w32 / npth.c
1 /* npth.c - a lightweight implementation of pth over native threads
2  * Copyright (C) 2011, 2014 g10 Code GmbH
3  *
4  * This file is part of nPth.
5  *
6  * nPth is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * nPth is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14  * the GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <https://www.gnu.org/licenses/>.
18  */
19
20 /* We implement the join mechanism ourself.  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <assert.h>
27 #include <errno.h>
28 #include <io.h>
29
30 #include "npth.h"
31
32 #include <stdio.h>
33 #define DEBUG_CALLS 1
34 #define _npth_debug(x, ...) fprintf(stderr, __VA_ARGS__)
35
36 #ifndef TEST
37 #undef  DEBUG_CALLS
38 #define DEBUG_CALLS 0
39 #undef _npth_debug
40 #define _npth_debug(x, ...)
41 #endif
42
43 /* This seems to be a common standard.  */
44 #define THREAD_NAME_MAX 15
45
46 /* The global lock that excludes all threads but one.  Note that this
47    implements the single-user-thread policy, but also protects all our
48    global data such as the thread_table.  GOT_SCEPTRE is a flag used
49    for debugging to tell wether we hold SCEPTRE.  */
50 static CRITICAL_SECTION sceptre;
51 static int got_sceptre;
52
53
54 /* This flag is set as soon as npth_init has been called or if any
55  * thread has been created.  It will never be cleared again.  The only
56  * purpose is to make npth_protect and npth_unprotect more robust in
57  * that they can be shortcut when npth_init has not yet been called.
58  * This is important for libraries which want to support nPth by using
59  * those two functions but may have been initialized before nPth. */
60 static int initialized_or_any_threads;
61
62
63 typedef struct npth_impl_s *npth_impl_t;
64 #define MAX_THREADS 1024
65 #define INVALID_THREAD_ID 0
66 /* Thread ID to thread context table.  We never allocate ID 0.  */
67 static npth_impl_t thread_table[MAX_THREADS];
68
69 /* The TLS index to store thread ID of the current thread.  Used to
70    make faster lookups of the thread data.  */
71 DWORD tls_index;
72
73
74 \f
75 /* Map a windows error value (GetLastError) to a POSIX error value.  */
76 static int
77 map_error (int winerr)
78 {
79   /* FIXME */
80   return EIO;
81 }
82
83
84 static int
85 wait_for_single_object (HANDLE obj, DWORD msecs)
86 {
87   DWORD res;
88
89   res = WaitForSingleObject(obj, msecs);
90
91   if (res == WAIT_ABANDONED)
92     return EDEADLK;
93   else if (res == WAIT_TIMEOUT)
94     return ETIMEDOUT;
95   else if (res == WAIT_FAILED)
96     return map_error (GetLastError());
97   else if (res != WAIT_OBJECT_0)
98     return EINTR;
99   else
100     return 0;
101 }
102
103 \f
104 int
105 npth_clock_gettime(struct timespec *tp)
106 {
107   FILETIME ftime;
108   ULARGE_INTEGER systime;
109   unsigned long long usecs;
110
111   GetSystemTimeAsFileTime (&ftime);
112   systime.LowPart = ftime.dwLowDateTime;
113   systime.HighPart = ftime.dwHighDateTime;
114
115   /* systime.QuadPart has the 100-nanosecond intervals since Jan 1, 1601.  */
116   tp->tv_sec = systime.QuadPart / 10000000ULL;
117   tp->tv_nsec = (systime.QuadPart * 100ULL) % 1000000000ULL;
118   return 0;
119 }
120
121
122 static int
123 calculate_timeout (const struct timespec *abstime, DWORD *msecs_r)
124 {
125   struct timespec tp;
126   struct timespec tp_delta;
127   DWORD msecs;
128
129   npth_clock_gettime (&tp);
130   /* Make sure there is a positive time delta.  */
131   if (!(npth_timercmp (&tp, abstime, <)))
132     return ETIMEDOUT;
133
134   npth_timersub (abstime, &tp, &tp_delta);
135   /* Make sure to round up to at least one millisecond.  Note that
136      within reasonable timeouts and the above macros, we should always
137      end up with a positive wait time here.  */
138   msecs = (tp_delta.tv_sec * 1000) + (tp_delta.tv_nsec + 999999) / 1000000;
139   if (msecs < 1)
140     {
141       /* Log a critical error here.  */
142       return ETIMEDOUT;
143     }
144
145   *msecs_r = msecs;
146   return 0;
147 }
148
149 \f
150 static void
151 enter_npth (const char *function)
152 {
153   int res;
154
155   if (DEBUG_CALLS)
156     _npth_debug (DEBUG_CALLS, "tid %lu: enter_npth (%s)\n",
157                  npth_self (), function ? function : "unknown");
158   got_sceptre = 0;
159   LeaveCriticalSection (&sceptre);
160 }
161
162
163 static void
164 leave_npth (const char *function)
165 {
166   EnterCriticalSection (&sceptre);
167   got_sceptre = 1;
168
169   if (DEBUG_CALLS)
170     _npth_debug (DEBUG_CALLS, "tid %lu: leave_npth (%s)\n",
171                  npth_self (), function ? function : "");
172 }
173
174 #define ENTER() enter_npth(__FUNCTION__)
175 #define LEAVE() leave_npth(__FUNCTION__)
176
177 \f
178 struct npth_impl_s
179 {
180   /* Usually there is one ref owned by the thread as long as it is
181      running, and one ref for everybody else as long as the thread is
182      joinable.  */
183   int refs;
184
185   HANDLE handle;
186
187   /* True if thread is detached.  */
188   int detached;
189
190   /* The start routine and arg.  */
191   void *(*start_routine) (void *);
192   void *start_arg;
193
194   char name[THREAD_NAME_MAX + 1];
195
196   /* Doubly-linked list for the waiter queue in condition
197      variables.  */
198   npth_impl_t next;
199   npth_impl_t *prev_ptr;
200
201   /* The event on which this thread waits when it is queued.  */
202   HANDLE event;
203
204   void *result;
205 };
206
207
208 static void
209 dequeue_thread (npth_impl_t thread)
210 {
211   /* Unlink the thread from any condition waiter queue.  */
212   if (thread->next)
213     {
214       thread->next->prev_ptr = thread->prev_ptr;
215       thread->next = NULL;
216     }
217   if (thread->prev_ptr)
218     {
219       *(thread->prev_ptr) = thread->next;
220       thread->prev_ptr = NULL;
221     }
222 }
223
224
225 /* Enqueue THREAD to come after the thread whose next pointer is
226    prev_ptr.  */
227 static void
228 enqueue_thread (npth_impl_t thread, npth_impl_t *prev_ptr)
229 {
230   if (*prev_ptr)
231     (*prev_ptr)->prev_ptr = &thread->next;
232   thread->prev_ptr = prev_ptr;
233   thread->next = *prev_ptr;
234   *prev_ptr = thread;
235 }
236
237
238 static int
239 find_thread (npth_t thread_id, npth_impl_t *thread)
240 {
241   if (thread_id < 1 || thread_id >= MAX_THREADS)
242     return ESRCH;
243
244   if (! thread_table[thread_id])
245     return ESRCH;
246
247   *thread = thread_table[thread_id];
248   return 0;
249 }
250
251
252 static int
253 new_thread (npth_t *thread_id)
254 {
255   npth_impl_t thread;
256   int id;
257
258   /* ID 0 is never allocated.  */
259   for (id = 1; id < MAX_THREADS; id++)
260     if (! thread_table[id])
261       break;
262   if (id == MAX_THREADS)
263     return EAGAIN;
264
265   thread = malloc (sizeof (*thread));
266   if (! thread)
267     return errno;
268
269   thread->refs = 1;
270   thread->handle = INVALID_HANDLE_VALUE;
271   thread->detached = 0;
272   thread->start_routine = NULL;
273   thread->start_arg = NULL;
274   thread->next = NULL;
275   thread->prev_ptr = NULL;
276   /* We create the event when it is first needed (not all threads wait
277      on conditions).  */
278   thread->event = INVALID_HANDLE_VALUE;
279   memset (thread->name, '\0', sizeof (thread->name));
280
281   thread_table[id] = thread;
282
283   *thread_id = id;
284   return 0;
285 }
286
287
288 static void
289 free_thread (npth_t thread_id)
290 {
291   npth_impl_t thread = thread_table[thread_id];
292
293   if (thread->handle)
294     CloseHandle (thread->handle);
295
296   /* Unlink the thread from any condition waiter queue.  */
297   dequeue_thread (thread);
298
299   free (thread);
300
301   thread_table[thread_id] = NULL;
302 }
303
304
305 static void
306 deref_thread (npth_t thread_id)
307 {
308   npth_impl_t thread = thread_table[thread_id];
309
310   thread->refs -= 1;
311   if (thread->refs == 0)
312     free_thread (thread_id);
313 }
314
315
316 \f
317 int
318 npth_init (void)
319 {
320   int err;
321   npth_t thread_id;
322   BOOL res;
323   HANDLE handle;
324   npth_impl_t thread;
325
326   InitializeCriticalSection (&sceptre);
327
328   /* Track that we have been initialized.  */
329   initialized_or_any_threads = 1;
330
331   /* Fake a thread table item for the main thread.  */
332   tls_index = TlsAlloc();
333   if (tls_index == TLS_OUT_OF_INDEXES)
334     return map_error (GetLastError());
335
336   err = new_thread(&thread_id);
337   if (err)
338     return err;
339
340   /* GetCurrentThread() is not usable by other threads, so it needs to
341      be duplicated.  */
342   res = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
343                         GetCurrentProcess(), &handle,
344                         0, FALSE, DUPLICATE_SAME_ACCESS);
345   if (!res)
346     {
347       free_thread (thread_id);
348       return map_error(GetLastError());
349     }
350
351   thread = thread_table[thread_id];
352   thread->handle = handle;
353
354   if (! TlsSetValue(tls_index, (LPVOID) thread_id))
355     return map_error (GetLastError());
356
357   LEAVE();
358   return 0;
359 }
360
361 \f
362 struct npth_attr_s
363 {
364   int detachstate;
365 };
366
367
368 int
369 npth_attr_init (npth_attr_t *attr_r)
370 {
371   npth_attr_t attr;
372
373   attr = malloc (sizeof *attr);
374   if (!attr)
375     return errno;
376
377   attr->detachstate = NPTH_CREATE_JOINABLE;
378   *attr_r = attr;
379   return 0;
380 }
381
382
383 int
384 npth_attr_destroy (npth_attr_t *attr)
385 {
386   free (*attr);
387   return 0;
388 }
389
390
391 int
392 npth_attr_getdetachstate (npth_attr_t *attr,
393                           int *detachstate)
394 {
395   *detachstate = (*attr)->detachstate;
396   return 0;
397 }
398
399
400 int
401 npth_attr_setdetachstate (npth_attr_t *attr, int detachstate)
402 {
403   if (detachstate != NPTH_CREATE_JOINABLE
404       && detachstate != NPTH_CREATE_DETACHED)
405     return EINVAL;
406
407   (*attr)->detachstate = detachstate;
408   return 0;
409 }
410
411
412 int
413 npth_getname_np (npth_t target_thread, char *buf, size_t buflen)
414 {
415   npth_impl_t thread;
416   int err;
417
418   if (buflen < THREAD_NAME_MAX + 1)
419     return ERANGE;
420
421   err = find_thread (target_thread, &thread);
422   if (err)
423     return err;
424
425   strcpy (buf, thread->name);
426   return 0;
427 }
428
429
430 int
431 npth_setname_np (npth_t target_thread, const char *name)
432 {
433   npth_impl_t thread;
434   int err;
435
436   if (strlen(name) > THREAD_NAME_MAX)
437     return ERANGE;
438
439   err = find_thread (target_thread, &thread);
440   if (err)
441     return err;
442
443   strcpy (thread->name, name);
444   return 0;
445 }
446
447
448 static DWORD
449 thread_start (void *arg)
450 {
451   npth_t thread_id = (npth_t) arg;
452   npth_impl_t thread;
453   void *result;
454
455   if (! TlsSetValue(tls_index, (LPVOID) thread_id))
456     /* FIXME: There is not much we can do here.  */
457     ;
458
459   LEAVE();
460   /* We must be protected here, because we access the global
461      thread_table.  */
462
463   thread = thread_table[thread_id];
464   result = thread->start_routine (thread->start_arg);
465   /* We might not return here if the thread calls npth_exit().  */
466
467   thread->result = result;
468
469   /* Any joiner will be signaled once we terminate.  */
470   deref_thread (thread_id);
471
472   ENTER();
473
474   /* We can not return result, as that is a void*, not a DWORD.  */
475   return 0;
476 }
477
478
479 int
480 npth_create (npth_t *newthread, const npth_attr_t *user_attr,
481              void *(*start_routine) (void *), void *start_arg)
482 {
483   int err = 0;
484   npth_t thread_id = INVALID_THREAD_ID;
485   npth_attr_t attr;
486   int attr_allocated;
487   npth_impl_t thread;
488   HANDLE handle;
489
490   /* We must stay protected here, because we access the global
491      thread_table.  Also, creating a new thread is not a blocking
492      operation.  */
493   if (user_attr)
494     {
495       attr = *user_attr;
496       attr_allocated = 0;
497     }
498   else
499     {
500       err = npth_attr_init (&attr);
501       if (err)
502         return err;
503       attr_allocated = 1;
504     }
505
506   err = new_thread (&thread_id);
507   if (err)
508     goto err_out;
509
510   thread = thread_table[thread_id];
511   if (attr->detachstate == NPTH_CREATE_DETACHED)
512     thread->detached = 1;
513   else
514     thread->refs += 1;
515
516   thread->start_routine = start_routine;
517   thread->start_arg = start_arg;
518
519   handle = CreateThread (NULL, 0,
520                          (LPTHREAD_START_ROUTINE)thread_start,
521                          (void *) thread_id, CREATE_SUSPENDED,
522                          NULL);
523   if (handle == NULL)
524     {
525       err = map_error (GetLastError());
526       goto err_out;
527     }
528
529   thread->handle = handle;
530   *newthread = thread_id;
531
532   ResumeThread (thread->handle);
533
534   return 0;
535
536  err_out:
537   if (thread_id)
538     free_thread (thread_id);
539   if (attr_allocated)
540     npth_attr_destroy (&attr);
541
542   return err;
543 }
544
545
546 npth_t
547 npth_self (void)
548 {
549   LPVOID thread_id;
550
551   thread_id = TlsGetValue (tls_index);
552   if (thread_id == 0 && GetLastError() != ERROR_SUCCESS)
553     /* FIXME: Log the error.  */
554     ;
555   return (npth_t) thread_id;
556 }
557
558
559 /* Not part of the public interface at the moment, thus static.  */
560 static int
561 npth_tryjoin_np (npth_t thread_id, void **thread_return)
562 {
563   int err;
564   npth_impl_t thread;
565   int res;
566
567   err = find_thread (thread_id, &thread);
568   if (err)
569     return err;
570
571   if (thread->detached)
572     return EINVAL;
573
574   /* No need to allow competing threads to enter when we can get the
575      lock immediately.  */
576   err = wait_for_single_object (thread->handle, 0);
577   if (err == ETIMEDOUT)
578     err = EBUSY;
579
580   if (err)
581     return err;
582
583   if (thread_return)
584     *thread_return = thread->result;
585   deref_thread (thread_id);
586
587   return 0;
588 }
589
590
591 int
592 npth_join (npth_t thread_id, void **thread_return)
593 {
594   int err;
595   npth_impl_t thread;
596   int res;
597
598   /* No need to allow competing threads to enter when we can get the
599      lock immediately.  */
600   err = npth_tryjoin_np (thread_id, thread_return);
601   if (err != EBUSY)
602     return err;
603
604   err = find_thread (thread_id, &thread);
605   if (err)
606     return err;
607
608   if (thread->detached)
609     return EINVAL;
610
611   ENTER();
612   err = wait_for_single_object (thread->handle, INFINITE);
613   LEAVE();
614
615   if (err)
616     return err;
617
618   if (thread_return)
619     *thread_return = thread->result;
620   deref_thread (thread_id);
621
622   return 0;
623 }
624
625
626 int
627 npth_detach (npth_t thread_id)
628 {
629   int err;
630   npth_impl_t thread;
631
632   err = find_thread (thread_id, &thread);
633   if (err)
634     return err;
635
636   if (thread->detached)
637     return EINVAL;
638
639   /* The detached flag indicates to other thread that the outside
640      reference in the global thread table has been consumed.  */
641   thread->detached = 1;
642   deref_thread (thread_id);
643
644   return 0;
645 }
646
647
648 void
649 npth_exit (void *retval)
650 {
651   int err;
652   npth_t thread_id;
653   npth_impl_t thread;
654
655   thread_id = npth_self();
656   err = find_thread (thread_id, &thread);
657   if (err)
658     /* FIXME: log this?  */
659     return;
660
661   thread->result = retval;
662   /* Any joiner will be signaled once we terminate.  */
663   deref_thread (thread_id);
664
665   ENTER();
666
667   /* We can not use retval here, as that is a void*, not a DWORD.  */
668   ExitThread(0);
669
670   /* Never reached.  But just in case ExitThread does return... */
671   LEAVE();
672 }
673
674
675 \f
676 int
677 npth_key_create (npth_key_t *key,
678                  void (*destr_function) (void *))
679 {
680   DWORD idx;
681
682   if (destr_function)
683     return EOPNOTSUPP;
684
685   idx = TlsAlloc ();
686   if (idx == TLS_OUT_OF_INDEXES)
687     return map_error (GetLastError());
688
689   *key = idx;
690   return 0;
691 }
692
693
694 int
695 npth_key_delete (npth_key_t key)
696 {
697   BOOL res;
698
699   res = TlsFree (key);
700   if (res == 0)
701     return map_error (GetLastError());
702   return 0;
703 }
704
705
706 void *
707 npth_getspecific (npth_key_t key)
708 {
709   /* Pthread doesn't support error reporting beyond returning NULL for
710      an invalid key, which is also what TlsGetValue returns in that
711      case.  */
712   return TlsGetValue (key);
713 }
714
715
716 int
717 npth_setspecific (npth_key_t key, const void *pointer)
718 {
719   BOOL res;
720
721   res = TlsSetValue (key, (void *) pointer);
722   if (res == 0)
723     return map_error (GetLastError());
724
725   return 0;
726 }
727
728 \f
729 struct npth_mutexattr_s
730 {
731   int kind;
732 };
733
734
735 int
736 npth_mutexattr_init (npth_mutexattr_t *attr_r)
737 {
738   npth_mutexattr_t attr;
739
740   attr = malloc (sizeof *attr);
741   if (!attr)
742     return errno;
743
744   attr->kind = NPTH_MUTEX_DEFAULT;
745   *attr_r = attr;
746   return 0;
747 }
748
749
750 int
751 npth_mutexattr_destroy (npth_mutexattr_t *attr)
752 {
753   free (*attr);
754   *attr = NULL;
755   return 0;
756 }
757
758
759 int
760 npth_mutexattr_gettype (const npth_mutexattr_t *attr,
761                         int *kind)
762 {
763   *kind = (*attr)->kind;
764   return 0;
765 }
766
767
768 int
769 npth_mutexattr_settype (npth_mutexattr_t *attr, int kind)
770 {
771   if (kind != NPTH_MUTEX_NORMAL && kind != NPTH_MUTEX_RECURSIVE
772       && kind != NPTH_MUTEX_ERRORCHECK)
773     return EINVAL;
774
775   (*attr)->kind = kind;
776   return 0;
777 }
778
779 \f
780 struct npth_mutex_s
781 {
782   /* We have to use a mutex, not a CRITICAL_SECTION, because the
783      latter can not be used with timed waits.  */
784   HANDLE mutex;
785 };
786
787
788 int
789 npth_mutex_init (npth_mutex_t *mutex_r, const npth_mutexattr_t *mutex_attr)
790 {
791   npth_mutex_t mutex;
792
793   /* We can not check *mutex_r here, as it may contain random data.  */
794   mutex = malloc (sizeof (*mutex));
795   if (!mutex)
796     return errno;
797
798   /* We ignore MUTEX_ATTR.  */
799   mutex->mutex = CreateMutex (NULL, FALSE, NULL);
800   if (!mutex->mutex)
801     {
802       int err = map_error (GetLastError());
803       free (mutex);
804       return err;
805     }
806
807   *mutex_r = mutex;
808   return 0;
809 }
810
811
812 int
813 npth_mutex_destroy (npth_mutex_t *mutex)
814 {
815   BOOL res;
816
817   if (*mutex == 0 || *mutex == NPTH_MUTEX_INITIALIZER
818       || *mutex == NPTH_RECURSIVE_MUTEX_INITIALIZER_NP)
819     return EINVAL;
820
821   res = CloseHandle ((*mutex)->mutex);
822   if (res == 0)
823     return map_error (GetLastError());
824
825   free (*mutex);
826   *mutex = NULL;
827
828   return 0;
829 }
830
831
832 /* Must be called with global lock held.  */
833 static int
834 mutex_init_check (npth_mutex_t *mutex)
835 {
836   int err;
837   npth_mutexattr_t attr;
838   int kind;
839
840   if (*mutex == 0)
841     return EINVAL;
842
843   if ((*mutex) == NPTH_MUTEX_INITIALIZER)
844     kind = NPTH_MUTEX_NORMAL;
845   else if ((*mutex) == NPTH_RECURSIVE_MUTEX_INITIALIZER_NP)
846     kind = NPTH_MUTEX_RECURSIVE;
847   else if ((*mutex) == NPTH_ERRORCHECK_MUTEX_INITIALIZER_NP)
848     kind = NPTH_MUTEX_ERRORCHECK;
849   else
850     /* Already initialized.  */
851     return 0;
852
853   /* Make sure we don't try again in case of error.  */
854   *mutex = 0;
855
856   err = npth_mutexattr_init (&attr);
857   if (err)
858     return err;
859
860   err = npth_mutexattr_settype (&attr, kind);
861   if (err)
862     {
863       npth_mutexattr_destroy (&attr);
864       return err;
865     }
866
867   err = npth_mutex_init (mutex, &attr);
868   npth_mutexattr_destroy (&attr);
869
870   return err;
871 }
872
873
874 int
875 npth_mutex_lock (npth_mutex_t *mutex)
876 {
877   int err;
878
879   /* While we are protected, let's check for a static initializer.  */
880   err = mutex_init_check (mutex);
881   if (err)
882     return err;
883
884   /* No need to allow competing threads to enter when we can get the
885      lock immediately.  */
886   err = npth_mutex_trylock (mutex);
887   if (err != EBUSY)
888     return err;
889
890   ENTER();
891   err = wait_for_single_object ((*mutex)->mutex, INFINITE);
892   LEAVE();
893
894   if (err)
895     return err;
896
897   return 0;
898 }
899
900
901 int
902 npth_mutex_trylock (npth_mutex_t *mutex)
903 {
904   int err;
905   DWORD res;
906
907   /* While we are protected, let's check for a static initializer.  */
908   err = mutex_init_check (mutex);
909   if (err)
910     return err;
911
912   /* We do not leave the global lock for a quick try.  */
913   err = wait_for_single_object ((*mutex)->mutex, 0);
914   if (err == ETIMEDOUT)
915     err = EBUSY;
916
917   if (err)
918     return err;
919
920   return 0;
921 }
922
923
924 int
925 npth_mutex_timedlock (npth_mutex_t *mutex, const struct timespec *abstime)
926 {
927   int err;
928   DWORD msecs;
929
930   /* While we are protected, let's check for a static initializer.  */
931   err = mutex_init_check (mutex);
932   if (err)
933     return err;
934
935   /* No need to allow competing threads to enter when we can get the
936      lock immediately.  */
937   err = npth_mutex_trylock (mutex);
938   if (err != EBUSY)
939     return err;
940
941   err = calculate_timeout (abstime, &msecs);
942   if (err)
943     return err;
944
945   ENTER();
946   err = wait_for_single_object ((*mutex)->mutex, msecs);
947   LEAVE();
948
949   if (err)
950     return err;
951
952   return 0;
953 }
954
955
956 int
957 npth_mutex_unlock (npth_mutex_t *mutex)
958 {
959   BOOL res;
960
961   if (*mutex == 0 || *mutex == NPTH_MUTEX_INITIALIZER
962       || *mutex == NPTH_RECURSIVE_MUTEX_INITIALIZER_NP)
963     return EINVAL;
964
965   res = ReleaseMutex ((*mutex)->mutex);
966   if (res == 0)
967     return map_error (GetLastError());
968
969   return 0;
970 }
971
972 \f
973 struct npth_cond_s
974 {
975   /* All conditions are protected by the global lock, so this is
976      simple.  */
977
978   /* The waiter queue.  */
979   npth_impl_t waiter;
980 };
981
982
983 int
984 npth_cond_init (npth_cond_t *cond_r,
985                 const npth_condattr_t *cond_attr)
986 {
987   npth_cond_t cond;
988
989   if (cond_attr != NULL)
990     return EINVAL;
991
992   /* We can not check *cond_r here, as it may contain random data.  */
993   cond = malloc (sizeof (*cond));
994   if (!cond)
995     return errno;
996
997   cond->waiter = NULL;
998
999   *cond_r = cond;
1000   return 0;
1001 }
1002
1003
1004 int
1005 npth_cond_destroy (npth_cond_t *cond)
1006 {
1007   if (*cond == 0)
1008     return EINVAL;
1009
1010   if ((*cond)->waiter)
1011     return EBUSY;
1012
1013   free (*cond);
1014   *cond = NULL;
1015
1016   return 0;
1017 }
1018
1019
1020 /* Must be called with global lock held.  */
1021 static int
1022 cond_init_check (npth_cond_t *cond)
1023 {
1024   int err;
1025
1026   if (*cond == 0 || *cond == NPTH_COND_INITIALIZER)
1027     return EINVAL;
1028
1029   if (*cond != NPTH_COND_INITIALIZER)
1030     /* Already initialized.  */
1031     return 0;
1032
1033   /* Make sure we don't try again in case of error.  */
1034   *cond = 0;
1035
1036   err = npth_cond_init (cond, NULL);
1037
1038   return err;
1039 }
1040
1041
1042 int
1043 npth_cond_signal (npth_cond_t *cond)
1044 {
1045   int err;
1046   npth_impl_t thread;
1047   DWORD res;
1048
1049   /* While we are protected, let's check for a static initializer.  */
1050   err = cond_init_check (cond);
1051   if (err)
1052     return err;
1053
1054   if ((*cond)->waiter == INVALID_THREAD_ID)
1055     return 0;
1056
1057   /* Dequeue the first thread and wake it up.  */
1058   thread = (*cond)->waiter;
1059   dequeue_thread (thread);
1060
1061   res = SetEvent (thread->event);
1062   if (res == 0)
1063     /* FIXME: An error here implies a mistake in the npth code.  Log it.  */
1064     ;
1065
1066   /* Force the woken up thread into the mutex lock function (for the
1067      mutex associated with the condition, which is why we have to
1068      release the global lock here).  This helps to ensure fairness,
1069      because otherwise our own thread might release and reacquire the
1070      lock first (followed by removing the condition that lead to the
1071      wakeup) and starve the woken up thread.  */
1072   ENTER ();
1073   Sleep (0);
1074   LEAVE ();
1075
1076   return 0;
1077 }
1078
1079
1080 int
1081 npth_cond_broadcast (npth_cond_t *cond)
1082 {
1083   int err;
1084   npth_impl_t thread;
1085   DWORD res;
1086   int any;
1087
1088   /* While we are protected, let's check for a static initializer.  */
1089   err = cond_init_check (cond);
1090   if (err)
1091     return err;
1092
1093   if ((*cond)->waiter == INVALID_THREAD_ID)
1094     return 0;
1095
1096   while ((*cond)->waiter)
1097     {
1098       /* Dequeue the first thread and wake it up.  */
1099       thread = (*cond)->waiter;
1100       dequeue_thread (thread);
1101
1102       res = SetEvent (thread->event);
1103       if (res == 0)
1104         /* FIXME: An error here implies a mistake in the npth code.  Log it.  */
1105         ;
1106     }
1107
1108   /* Force the woken up threads into the mutex lock function (for the
1109      mutex associated with the condition, which is why we have to
1110      release the global lock here).  This helps to ensure fairness,
1111      because otherwise our own thread might release and reacquire the
1112      lock first (followed by removing the condition that lead to the
1113      wakeup) and starve the woken up threads.  */
1114   ENTER ();
1115   Sleep (0);
1116   LEAVE ();
1117
1118   return 0;
1119 }
1120
1121
1122 /* As a special exception in W32 NPTH, mutex can be NULL, in which
1123    case the global lock doubles as the mutex protecting the condition.
1124    This is used internally in the RW implementation as an
1125    optimization.  Note that this is safe as long as the caller does
1126    not yield to other threads (directly or indirectly) between
1127    checking the condition and waiting on it.  */
1128 int
1129 npth_cond_wait (npth_cond_t *cond, npth_mutex_t *mutex)
1130 {
1131   int err;
1132   int err2;
1133   BOOL bres;
1134   npth_impl_t thread;
1135   npth_impl_t *prev_ptr;
1136
1137   /* While we are protected, let's check for a static initializer.  */
1138   err = cond_init_check (cond);
1139   if (err)
1140     return err;
1141
1142   err = find_thread (npth_self(), &thread);
1143   if (err)
1144     return err;
1145
1146   /* Ensure there is an event.  */
1147   if (thread->event == INVALID_HANDLE_VALUE)
1148     {
1149       thread->event = CreateEvent (NULL, TRUE, FALSE, NULL);
1150       if (thread->event == INVALID_HANDLE_VALUE)
1151         return map_error (GetLastError());
1152     }
1153
1154   /* Find end of queue and enqueue the thread.  */
1155   prev_ptr = &(*cond)->waiter;
1156   while (*prev_ptr)
1157     prev_ptr = &(*prev_ptr)->next;
1158   enqueue_thread (thread, prev_ptr);
1159
1160   /* Make sure the event is not signaled before releasing the mutex.  */
1161   bres = ResetEvent (thread->event);
1162   if (bres == 0)
1163     /* Log an error.  */
1164     ;
1165
1166   if (mutex)
1167     {
1168       err = npth_mutex_unlock (mutex);
1169       if (err)
1170         {
1171           dequeue_thread (thread);
1172           return err;
1173         }
1174     }
1175
1176   ENTER();
1177   err = wait_for_single_object (thread->event, INFINITE);
1178   LEAVE();
1179
1180   /* Make sure the thread is dequeued (in case of error).  */
1181   dequeue_thread (thread);
1182
1183   if (mutex)
1184     {
1185       err2 = npth_mutex_lock (mutex);
1186       if (err2)
1187         /* FIXME: Log this at least.  */
1188         ;
1189     }
1190
1191   if (err)
1192     return err;
1193
1194   return 0;
1195 }
1196
1197
1198 int
1199 npth_cond_timedwait (npth_cond_t *cond, npth_mutex_t *mutex,
1200                      const struct timespec *abstime)
1201 {
1202   int err;
1203   int err2;
1204   BOOL bres;
1205   npth_impl_t thread;
1206   npth_impl_t *prev_ptr;
1207   DWORD msecs;
1208
1209   err = calculate_timeout (abstime, &msecs);
1210   if (err)
1211     {
1212       if (err != ETIMEDOUT)
1213         return err;
1214
1215       /* We have to give up the lock anyway to give others a chance to
1216          signal or broadcast.  */
1217       err = npth_mutex_unlock (mutex);
1218       if (err)
1219         return err;
1220       ENTER();
1221       Sleep (0);
1222       LEAVE();
1223       err = npth_mutex_lock (mutex);
1224       if (err)
1225         return (err);
1226       return ETIMEDOUT;
1227     }
1228
1229   /* While we are protected, let's check for a static initializer.  */
1230   err = cond_init_check (cond);
1231   if (err)
1232     return err;
1233
1234   err = find_thread (npth_self(), &thread);
1235   if (err)
1236     return err;
1237
1238   /* Ensure there is an event.  */
1239   if (thread->event == INVALID_HANDLE_VALUE)
1240     {
1241       thread->event = CreateEvent (NULL, TRUE, FALSE, NULL);
1242       if (thread->event == INVALID_HANDLE_VALUE)
1243         return map_error (GetLastError());
1244     }
1245
1246   /* Make sure the event is not signaled.  */
1247   bres = ResetEvent (thread->event);
1248   if (bres == 0)
1249     /* Log an error.  */
1250     ;
1251
1252   /* Find end of queue and enqueue the thread.  */
1253   prev_ptr = &(*cond)->waiter;
1254   while (*prev_ptr)
1255     prev_ptr = &(*prev_ptr)->next;
1256   enqueue_thread (thread, prev_ptr);
1257
1258   err = npth_mutex_unlock (mutex);
1259   if (err)
1260     {
1261       dequeue_thread (thread);
1262       return err;
1263     }
1264
1265   ENTER();
1266   err = wait_for_single_object (thread->event, msecs);
1267   LEAVE();
1268
1269   err2 = npth_mutex_lock (mutex);
1270   if (err2)
1271     /* FIXME: Log this at least.  */
1272     ;
1273
1274   if (err)
1275     return err;
1276
1277   return 0;
1278 }
1279
1280 \f
1281 struct npth_rwlockattr_s
1282 {
1283   int kind;
1284 };
1285
1286
1287 int
1288 npth_rwlockattr_init (npth_rwlockattr_t *attr_r)
1289 {
1290   npth_rwlockattr_t attr;
1291
1292   attr = malloc (sizeof *attr);
1293   if (!attr)
1294     return errno;
1295
1296   attr->kind = NPTH_RWLOCK_DEFAULT_NP;
1297   *attr_r = attr;
1298   return 0;
1299 }
1300
1301
1302 int
1303 npth_rwlockattr_destroy (npth_rwlockattr_t *attr)
1304 {
1305   free (*attr);
1306   *attr = NULL;
1307   return 0;
1308 }
1309
1310
1311 int
1312 npth_rwlockattr_gettype_np (const npth_rwlockattr_t *attr,
1313                             int *kind)
1314 {
1315   *kind = (*attr)->kind;
1316   return 0;
1317 }
1318
1319
1320 int
1321 npth_rwlockattr_settype_np (npth_rwlockattr_t *attr, int kind)
1322 {
1323   if (kind != NPTH_RWLOCK_PREFER_READER_NP
1324       && kind != NPTH_RWLOCK_PREFER_WRITER_NP
1325       && kind != NPTH_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
1326     return EINVAL;
1327
1328   (*attr)->kind = kind;
1329   return 0;
1330 }
1331
1332
1333 struct npth_rwlock_s
1334 {
1335   /* Objects are protected by the global lock, so no lock here
1336      necessary.  This is even true for the condition (by specifying
1337      NULL as the mutex in npth_cond_wait and npth_cond_timedwait).  */
1338
1339   /* True if we prefer writers over readers.  */
1340   int prefer_writer;
1341
1342   /* Readers who want the lock wait on this condition, which is
1343      broadcast when the last writer goes away.  */
1344   npth_cond_t reader_wait;
1345
1346   /* The number of readers waiting on the condition.  */
1347   int nr_readers_queued;
1348
1349   /* The number of current readers.  */
1350   int nr_readers;
1351
1352   /* Writers who want the lock wait on this condition, which is
1353      signaled when the current writer or last reader goes away.  */
1354   npth_cond_t writer_wait;
1355
1356   /* The number of queued writers.  */
1357   int nr_writers_queued;
1358
1359   /* The number of current writers.  This is either 1 (then nr_readers
1360      is 0) or it is 0.  At unlock time this value tells us if the
1361      current lock holder is a writer or a reader.  */
1362   int nr_writers;
1363 };
1364
1365
1366 int
1367 npth_rwlock_init (npth_rwlock_t *rwlock_r,
1368                   const npth_rwlockattr_t *user_attr)
1369 {
1370   int err;
1371   npth_rwlock_t rwlock;
1372   npth_rwlockattr_t attr;
1373   int attr_allocated;
1374
1375   if (user_attr != NULL)
1376     {
1377       attr = *user_attr;
1378       attr_allocated = 0;
1379     }
1380   else
1381     {
1382       err = npth_rwlockattr_init (&attr);
1383       if (err)
1384         return err;
1385     }
1386
1387   /* We can not check *rwlock_r here, as it may contain random data.  */
1388   rwlock = malloc (sizeof (*rwlock));
1389   if (!rwlock)
1390     {
1391       err = errno;
1392       goto err_out;
1393     }
1394
1395   rwlock->prefer_writer = (attr->kind == NPTH_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
1396
1397   err = npth_cond_init (&rwlock->reader_wait, NULL);
1398   if (err)
1399     {
1400       free (rwlock);
1401       goto err_out;
1402     }
1403
1404   err = npth_cond_init (&rwlock->writer_wait, NULL);
1405   if (err)
1406     {
1407       npth_cond_destroy (&rwlock->reader_wait);
1408       free (rwlock);
1409       goto err_out;
1410     }
1411
1412   rwlock->nr_readers = 0;
1413   rwlock->nr_readers_queued = 0;
1414   rwlock->nr_writers = 0;
1415   rwlock->nr_writers_queued = 0;
1416
1417   *rwlock_r = rwlock;
1418
1419  err_out:
1420   if (attr_allocated)
1421     npth_rwlockattr_destroy (&attr);
1422   return err;
1423 }
1424
1425
1426 /* Must be called with global lock held.  */
1427 static int
1428 rwlock_init_check (npth_rwlock_t *rwlock)
1429 {
1430   int err;
1431   npth_rwlockattr_t attr;
1432   int kind;
1433
1434   if (*rwlock == 0)
1435     return EINVAL;
1436
1437   if ((*rwlock) == NPTH_RWLOCK_INITIALIZER)
1438     kind = NPTH_RWLOCK_PREFER_READER_NP;
1439   if ((*rwlock) == NPTH_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP)
1440     kind = NPTH_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP;
1441   else
1442     /* Already initialized.  */
1443     return 0;
1444
1445   /* Make sure we don't try again in case of error.  */
1446   *rwlock = 0;
1447
1448   err = npth_rwlockattr_init (&attr);
1449   if (err)
1450     return err;
1451
1452   err = npth_rwlockattr_settype_np (&attr, kind);
1453   if (err)
1454     {
1455       npth_rwlockattr_destroy (&attr);
1456       return err;
1457     }
1458
1459   err = npth_rwlock_init (rwlock, &attr);
1460   npth_rwlockattr_destroy (&attr);
1461
1462   return err;
1463 }
1464
1465
1466 int
1467 npth_rwlock_destroy (npth_rwlock_t *rwlock)
1468 {
1469   int err;
1470
1471   if (*rwlock == 0 || *rwlock == NPTH_RWLOCK_INITIALIZER)
1472     return EINVAL;
1473
1474   if ((*rwlock)->nr_writers || (*rwlock)->nr_readers || (*rwlock)->nr_writers_queued
1475       || (*rwlock)->nr_readers_queued)
1476     return EBUSY;
1477
1478   err = npth_cond_destroy (&(*rwlock)->reader_wait);
1479   if (err)
1480     /* FIXME: Log this.  */
1481     ;
1482
1483   err = npth_cond_destroy (&(*rwlock)->writer_wait);
1484   if (err)
1485     /* FIXME: Log this.  */
1486     ;
1487
1488   free (rwlock);
1489
1490   *rwlock = NULL;
1491   return 0;
1492 }
1493
1494
1495 int
1496 npth_rwlock_tryrdlock (npth_rwlock_t *rwlock)
1497 {
1498   if ((*rwlock)->nr_writers)
1499     return EBUSY;
1500
1501   if ((*rwlock)->nr_writers_queued && (*rwlock)->prefer_writer)
1502     return EBUSY;
1503
1504   (*rwlock)->nr_readers++;
1505   return 0;
1506 }
1507
1508
1509 int
1510 npth_rwlock_rdlock (npth_rwlock_t *rwlock)
1511 {
1512   int err;
1513
1514   while (1)
1515     {
1516       /* Quick check.  */
1517       err = npth_rwlock_tryrdlock (rwlock);
1518       if (err != EBUSY)
1519         return err;
1520
1521       (*rwlock)->nr_readers_queued++;
1522       err = npth_cond_wait (&(*rwlock)->reader_wait, NULL);
1523       (*rwlock)->nr_readers_queued--;
1524       if (err)
1525         return err;
1526     }
1527 }
1528
1529 int
1530 npth_rwlock_timedrdlock (npth_rwlock_t *rwlock,
1531                          const struct timespec *abstime)
1532 {
1533   int err;
1534
1535   while (1)
1536     {
1537       /* Quick check.  */
1538       err = npth_rwlock_tryrdlock (rwlock);
1539       if (err != EBUSY)
1540         return err;
1541
1542       (*rwlock)->nr_readers_queued++;
1543       err = npth_cond_timedwait (&(*rwlock)->reader_wait, NULL, abstime);
1544       (*rwlock)->nr_readers_queued--;
1545       if (err)
1546         return err;
1547     }
1548 }
1549
1550 int
1551 npth_rwlock_trywrlock (npth_rwlock_t *rwlock)
1552 {
1553   if ((*rwlock)->nr_writers)
1554     return EBUSY;
1555
1556   if ((*rwlock)->nr_readers)
1557     return EBUSY;
1558
1559   (*rwlock)->nr_writers = 1;
1560   return 0;
1561 }
1562
1563
1564 int
1565 npth_rwlock_wrlock (npth_rwlock_t *rwlock)
1566 {
1567   int err;
1568
1569   while (1)
1570     {
1571       /* Quick check.  */
1572       err = npth_rwlock_trywrlock (rwlock);
1573       if (err != EBUSY)
1574         return err;
1575
1576       (*rwlock)->nr_writers_queued++;
1577       err = npth_cond_wait (&(*rwlock)->writer_wait, NULL);
1578       (*rwlock)->nr_writers_queued--;
1579       if (err)
1580         return err;
1581     }
1582 }
1583
1584
1585 int
1586 npth_rwlock_timedwrlock (npth_rwlock_t *rwlock,
1587                          const struct timespec *abstime)
1588 {
1589   int err;
1590
1591   while (1)
1592     {
1593       /* Quick check.  */
1594       err = npth_rwlock_trywrlock (rwlock);
1595       if (err != EBUSY)
1596         return err;
1597
1598       (*rwlock)->nr_writers_queued++;
1599       err = npth_cond_timedwait (&(*rwlock)->writer_wait, NULL, abstime);
1600       (*rwlock)->nr_writers_queued--;
1601       if (err)
1602         return err;
1603     }
1604 }
1605
1606
1607 int
1608 npth_rwlock_unlock (npth_rwlock_t *rwlock)
1609 {
1610   int err;
1611
1612   if ((*rwlock)->nr_writers)
1613     /* We are the writer.  */
1614     (*rwlock)->nr_writers = 0;
1615   else
1616     /* We are the reader.  */
1617     (*rwlock)->nr_readers--;
1618
1619   if ((*rwlock)->nr_readers == 0)
1620     {
1621       if ((*rwlock)->nr_writers_queued)
1622         {
1623           err = npth_cond_signal (&(*rwlock)->writer_wait);
1624           if (err)
1625             return err;
1626         }
1627       else if ((*rwlock)->nr_readers_queued)
1628         {
1629           err = npth_cond_broadcast (&(*rwlock)->reader_wait);
1630           return err;
1631         }
1632     }
1633   return 0;
1634 }
1635
1636 \f
1637 /* Standard POSIX Replacement API */
1638
1639 int
1640 npth_usleep(unsigned int usec)
1641 {
1642   ENTER();
1643   Sleep((usec + 999) / 1000);
1644   LEAVE();
1645   return 0;
1646 }
1647
1648
1649 unsigned int
1650 npth_sleep(unsigned int sec)
1651 {
1652   ENTER();
1653   Sleep (sec * 1000);
1654   LEAVE();
1655   return 0;
1656 }
1657
1658
1659 int
1660 npth_system(const char *cmd)
1661 {
1662   int res;
1663
1664   ENTER();
1665   res = system(cmd);
1666   LEAVE();
1667   return res;
1668 }
1669
1670
1671 pid_t
1672 npth_waitpid(pid_t pid, int *status, int options)
1673 {
1674   return EOPNOTSUPP;
1675 }
1676
1677
1678 int
1679 npth_connect(int s, const struct sockaddr *addr, socklen_t addrlen)
1680 {
1681   int res;
1682
1683   ENTER();
1684   res = connect(s, addr, addrlen);
1685   LEAVE();
1686   return res;
1687 }
1688
1689
1690 int
1691 npth_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1692 {
1693   int res;
1694
1695   ENTER();
1696   res = accept(s, addr, addrlen);
1697   LEAVE();
1698   return res;
1699 }
1700
1701
1702 int
1703 npth_select(int nfd, fd_set *rfds, fd_set *wfds, fd_set *efds,
1704             struct timeval *timeout)
1705 {
1706   int res;
1707
1708   ENTER();
1709   res = select(nfd, rfds, wfds, efds, timeout);
1710   LEAVE();
1711   return res;
1712 }
1713
1714
1715 ssize_t
1716 npth_read(int fd, void *buf, size_t nbytes)
1717 {
1718   ssize_t res;
1719
1720   ENTER();
1721   res = read(fd, buf, nbytes);
1722   LEAVE();
1723   return res;
1724 }
1725
1726
1727 ssize_t
1728 npth_write(int fd, const void *buf, size_t nbytes)
1729 {
1730   ssize_t res;
1731
1732   ENTER();
1733   res = write(fd, buf, nbytes);
1734   LEAVE();
1735   return res;
1736 }
1737
1738
1739 int
1740 npth_recvmsg (int fd, struct msghdr *msg, int flags)
1741 {
1742   return EOPNOTSUPP;
1743 }
1744
1745
1746 int
1747 npth_sendmsg (int fd, const struct msghdr *msg, int flags)
1748 {
1749   return EOPNOTSUPP;
1750 }
1751
1752
1753 void
1754 npth_unprotect (void)
1755 {
1756   /* If we are not initialized we may not access the semaphore and
1757    * thus we shortcut it. Note that in this case the unprotect/protect
1758    * is not needed.  For failsafe reasons if an nPth thread has ever
1759    * been created but nPth has accidentally not initialized we do not
1760    * shortcut so that a stack backtrace (due to the access of the
1761    * uninitialized semaphore) is more expressive.  */
1762   if (initialized_or_any_threads)
1763     ENTER();
1764 }
1765
1766
1767 void
1768 npth_protect (void)
1769 {
1770   /* See npth_unprotect for commentary.  */
1771   if (initialized_or_any_threads)
1772     LEAVE();
1773 }
1774
1775
1776 int
1777 npth_is_protected (void)
1778 {
1779   return got_sceptre;
1780 }
1781
1782
1783 \f
1784 /* Maximum number of extra handles.  We can only support 31 as that is
1785    the number of bits we can return.  This is smaller than the maximum
1786    number of allowed wait objects for WFMO (which is 64).  */
1787 #define MAX_EVENTS 31
1788
1789 /* Although the WSAEventSelect machinery seems to have no limit on the
1790    number of selectable fds, we impose the same limit as used by
1791    traditional select.  This allows us to work with a static data
1792    structure instead of an dynamically allocated array.  */
1793 #define MAX_FDOBJS FD_SETSIZE
1794
1795 /* Using WFMO even for sockets makes Windows objects more composable,
1796    which helps faking signals and other constructs, so we support
1797    that.  You can still use npth_select for the plain select
1798    function.  */
1799 int
1800 npth_eselect(int nfd, fd_set *rfds, fd_set *wfds, fd_set *efds,
1801              const struct timespec *timeout,
1802              HANDLE *events, unsigned int *events_set)
1803 {
1804   int err = 0;
1805   DWORD msecs;
1806   int i;
1807   u_int idx;
1808   /* One more for the handle associated with socket events.  */
1809   HANDLE obj[MAX_EVENTS + 1];
1810   int nr_obj = 0;
1811   /* Number of extra events.  */
1812   int nr_events = 0;
1813   HANDLE sock_event = INVALID_HANDLE_VALUE;
1814   /* This will be (nr_obj - 1) == nr_events.  */
1815   int sock_event_idx = -1;
1816   int res;
1817   DWORD ret;
1818   SOCKET fd;
1819   long flags;
1820   int cnt;
1821   struct {
1822     SOCKET fd;
1823     long flags;
1824   } fdobj[MAX_FDOBJS];
1825   int nr_fdobj = 0;
1826
1827   (void)nfd;  /* No need for it under Windows.  */
1828
1829   if (events)
1830     {
1831       if (!events_set)
1832         {
1833           errno = EINVAL;
1834           return -1;
1835         }
1836
1837       /* We always ensure that the events_set is valid, even after an
1838          error.  */
1839       *events_set = 0;
1840     }
1841
1842   if (timeout && (timeout->tv_sec < 0 || timeout->tv_nsec < 0))
1843     {
1844       errno = EINVAL;
1845       return -1;
1846     }
1847
1848   if (timeout == NULL)
1849     msecs = INFINITE;
1850   else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0)
1851     msecs = 0;
1852   else
1853     {
1854       msecs = (timeout->tv_sec * 1000) + (timeout->tv_nsec + 999999) / 1000000;
1855       if (msecs < 1)
1856         msecs = 1;
1857     }
1858
1859   if (events)
1860     {
1861       /* Copy the extra handles.  */
1862       for (i = 0; i < MAX_EVENTS; i++)
1863         {
1864           if (events[i] == INVALID_HANDLE_VALUE)
1865             break;
1866
1867           obj[nr_obj] = events[i];
1868           nr_obj++;
1869           nr_events++;
1870         }
1871
1872       /* We can only return the status of up to MAX_EVENTS handles in
1873          EVENTS_SET.  */
1874       if (events[i] != INVALID_HANDLE_VALUE)
1875         {
1876           errno = EINVAL;
1877           return -1;
1878         }
1879     }
1880
1881   /* From here on, we clean up at err_out, and you can set ERR to
1882      return an error.  */
1883
1884   sock_event = WSACreateEvent ();
1885   if (sock_event == INVALID_HANDLE_VALUE)
1886     {
1887       err = EINVAL;
1888       return -1;
1889     }
1890
1891   sock_event_idx = nr_obj;
1892   obj[nr_obj] = sock_event;
1893   nr_obj++;
1894
1895   /* Combine FDs from all lists.  */
1896 #define SET_FDOBJ(x,v) do {                      \
1897     for (idx=0; idx < (x)->fd_count; idx++)      \
1898       {                                          \
1899         for (i=0; i < nr_fdobj; i++)             \
1900           if (fdobj[i].fd == (x)->fd_array[idx]) \
1901             break;                               \
1902         if (i < nr_fdobj)                        \
1903           ;                                      \
1904         else if (nr_fdobj < MAX_FDOBJS)          \
1905           {                                      \
1906             i = nr_fdobj++;                      \
1907             fdobj[i].fd    = (x)->fd_array[idx]; \
1908             fdobj[i].flags = 0;                  \
1909           }                                      \
1910         else                                     \
1911           {                                      \
1912             err = EINVAL;                        \
1913             goto err_out;                        \
1914           }                                      \
1915         fdobj[i].flags |= (v);                   \
1916       }                                          \
1917   } while (0)
1918
1919   if (rfds)
1920     SET_FDOBJ (rfds, FD_READ | FD_ACCEPT);
1921   if (wfds)
1922     SET_FDOBJ (wfds, FD_WRITE);
1923   if (efds)
1924     SET_FDOBJ (efds, FD_OOB | FD_CLOSE);
1925
1926 #undef SET_FDOBJ
1927
1928   /* Set the select flags.  */
1929   for (i = 0; i < nr_fdobj; i++)
1930     {
1931       res = WSAEventSelect (fdobj[i].fd, sock_event, fdobj[i].flags);
1932       if (res == SOCKET_ERROR)
1933         {
1934           err = map_error (WSAGetLastError());
1935           goto err_out;
1936         }
1937     }
1938
1939   /* Let's wait.  */
1940   ENTER();
1941   ret = WaitForMultipleObjects (nr_obj, obj, FALSE, msecs);
1942   LEAVE();
1943   if (ret == WAIT_TIMEOUT)
1944     {
1945       err = ETIMEDOUT;
1946       goto err_out;
1947     }
1948   else if (ret == WAIT_FAILED)
1949     {
1950       err = map_error (GetLastError());
1951       goto err_out;
1952     }
1953
1954   /* All other return values: We look at the objects.  We must not
1955      fail from here, because then we could lose events.  */
1956
1957   /* Keep track of result count.  */
1958   cnt = 0;
1959
1960   for (i = 0; i < nr_events; i++)
1961     {
1962       ret = WaitForSingleObject (obj[i], 0);
1963       if (ret != WAIT_OBJECT_0)
1964         /* We ignore errors here.  */
1965         continue;
1966
1967       *events_set = (*events_set) | (1 << i);
1968       /* We consume the event here.  This may be undesirable, but
1969          unless we make it configurable we need a common policy,
1970          and this saves the user one step.  */
1971       ResetEvent (obj[i]);
1972       /* Increase result count.  */
1973       cnt++;
1974     }
1975
1976   /* Now update the file descriptors sets.  */
1977   if (rfds)
1978     FD_ZERO (rfds);
1979   if (wfds)
1980     FD_ZERO (wfds);
1981   if (efds)
1982     FD_ZERO (efds);
1983   for (i = 0; i < nr_fdobj; i++)
1984     {
1985       WSANETWORKEVENTS ne;
1986
1987       fd = fdobj[i].fd;
1988       flags = fdobj[i].flags;
1989
1990       res = WSAEnumNetworkEvents (fd, NULL, &ne);
1991       if (res == SOCKET_ERROR)
1992         continue; /* FIXME: We ignore this error here.  */
1993
1994       /* NB that the test on FLAGS guarantees that ?fds is not NULL. */
1995       if ((flags & FD_READ) && (ne.lNetworkEvents & (FD_READ | FD_ACCEPT)))
1996         {
1997           FD_SET (fd, rfds);
1998           cnt++;
1999         }
2000       if ((flags & FD_WRITE) && (ne.lNetworkEvents & FD_WRITE))
2001         {
2002           FD_SET (fd, wfds);
2003           cnt++;
2004         }
2005       if ((flags & FD_CLOSE) && (ne.lNetworkEvents & (FD_OOB | FD_CLOSE)))
2006         {
2007           FD_SET (fd, efds);
2008           cnt++;
2009         }
2010
2011       WSAEventSelect (fd, NULL, 0); /* We ignore errors.  */
2012     }
2013
2014   /* We ignore errors.  */
2015   WSACloseEvent (sock_event);
2016
2017   return cnt;
2018
2019   /* Cleanup.  */
2020  err_out:
2021   if (sock_event != INVALID_HANDLE_VALUE)
2022     {
2023       for (i = 0; i < nr_fdobj; i++)
2024         {
2025           WSAEventSelect (fdobj[i].fd, NULL, 0); /* We ignore errors.  */
2026         }
2027       WSACloseEvent (sock_event); /* We ignore errors.  */
2028     }
2029
2030   if (err == ETIMEDOUT)
2031     return 0;
2032
2033   errno = err;
2034   return -1;
2035 }