1 /* Copyright (C) 2003-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <errno.h>
19 #include <pthread.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/time.h>
24 
25 
26 static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
27 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
28 static pthread_barrier_t b;
29 
30 static void *
tf(void * a)31 tf (void *a)
32 {
33   /* Block SIGUSR1.  */
34   sigset_t ss;
35 
36   sigemptyset (&ss);
37   sigaddset (&ss, SIGUSR1);
38   if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
39     {
40       puts ("child: sigmask failed");
41       exit (1);
42     }
43 
44   if (pthread_mutex_lock (&m) != 0)
45     {
46       puts ("child: mutex_lock failed");
47       exit (1);
48     }
49 
50   int e = pthread_barrier_wait (&b);
51   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
52     {
53       puts ("child: barrier_wait failed");
54       exit (1);
55     }
56 
57   /* Compute timeout.  */
58   struct timeval tv;
59   (void) gettimeofday (&tv, NULL);
60   struct timespec ts;
61   TIMEVAL_TO_TIMESPEC (&tv, &ts);
62   /* Timeout: 1sec.  */
63   ts.tv_sec += 1;
64 
65   /* This call should never return.  */
66   if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
67     {
68       puts ("cond_timedwait didn't time out");
69       exit (1);
70     }
71 
72   return NULL;
73 }
74 
75 
76 int
do_test(void)77 do_test (void)
78 {
79   pthread_t th;
80 
81   if (pthread_barrier_init (&b, NULL, 2) != 0)
82     {
83       puts ("barrier_init failed");
84       exit (1);
85     }
86 
87   if (pthread_create (&th, NULL, tf, NULL) != 0)
88     {
89       puts ("create failed");
90       exit (1);
91     }
92 
93   int e = pthread_barrier_wait (&b);
94   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
95     {
96       puts ("barrier_wait failed");
97       exit (1);
98     }
99 
100   if (pthread_mutex_lock (&m) != 0)
101     {
102       puts ("mutex_lock failed");
103       exit (1);
104     }
105 
106   /* Send the thread a signal which it has blocked.  */
107   if (pthread_kill (th, SIGUSR1) != 0)
108     {
109       puts ("kill failed");
110       exit (1);
111     }
112 
113   if (pthread_mutex_unlock (&m) != 0)
114     {
115       puts ("mutex_unlock failed");
116       exit (1);
117     }
118 
119   void *r;
120   if (pthread_join (th, &r) != 0)
121     {
122       puts ("join failed");
123       exit (1);
124     }
125   if (r != NULL)
126     {
127       puts ("return value wrong");
128       exit (1);
129     }
130 
131   return 0;
132 }
133 
134 
135 #define TEST_FUNCTION do_test ()
136 #include "../test-skeleton.c"
137