1 /* Copyright (C) 2002-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 <error.h>
19 #include <pthread.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 
23 
24 static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
25 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
26 
27 static pthread_barrier_t bar;
28 
29 
30 static void *
tf(void * a)31 tf (void *a)
32 {
33   int i = (long int) a;
34   int err;
35 
36   printf ("child %d: lock\n", i);
37 
38   err = pthread_mutex_lock (&mut);
39   if (err != 0)
40     error (EXIT_FAILURE, err, "locking in child failed");
41 
42   printf ("child %d: sync\n", i);
43 
44   int e = pthread_barrier_wait (&bar);
45   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
46     {
47       puts ("child: barrier_wait failed");
48       exit (1);
49     }
50 
51   printf ("child %d: wait\n", i);
52 
53   err = pthread_cond_wait (&cond, &mut);
54   if (err != 0)
55     error (EXIT_FAILURE, err, "child %d: failed to wait", i);
56 
57   printf ("child %d: woken up\n", i);
58 
59   err = pthread_mutex_unlock (&mut);
60   if (err != 0)
61     error (EXIT_FAILURE, err, "child %d: unlock[2] failed", i);
62 
63   printf ("child %d: done\n", i);
64 
65   return NULL;
66 }
67 
68 
69 #define N 10
70 
71 
72 static int
do_test(void)73 do_test (void)
74 {
75   pthread_t th[N];
76   int i;
77   int err;
78 
79   printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
80 
81   if (pthread_barrier_init (&bar, NULL, 2) != 0)
82     {
83       puts ("barrier_init failed");
84       exit (1);
85     }
86 
87   pthread_attr_t at;
88 
89   if (pthread_attr_init (&at) != 0)
90     {
91       puts ("attr_init failed");
92       return 1;
93     }
94 
95   if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
96     {
97       puts ("attr_setstacksize failed");
98       return 1;
99     }
100 
101   for (i = 0; i < N; ++i)
102     {
103       printf ("create thread %d\n", i);
104 
105       err = pthread_create (&th[i], &at, tf, (void *) (long int) i);
106       if (err != 0)
107 	error (EXIT_FAILURE, err, "cannot create thread %d", i);
108 
109       printf ("wait for child %d\n", i);
110 
111       /* Wait for the child to start up and get the mutex for the
112 	 conditional variable.  */
113       int e = pthread_barrier_wait (&bar);
114       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
115 	{
116 	  puts ("barrier_wait failed");
117 	  exit (1);
118 	}
119     }
120 
121   if (pthread_attr_destroy (&at) != 0)
122     {
123       puts ("attr_destroy failed");
124       return 1;
125     }
126 
127   puts ("get lock outselves");
128 
129   err = pthread_mutex_lock (&mut);
130   if (err != 0)
131     error (EXIT_FAILURE, err, "mut locking failed");
132 
133   puts ("broadcast");
134 
135   /* Wake up all threads.  */
136   err = pthread_cond_broadcast (&cond);
137   if (err != 0)
138     error (EXIT_FAILURE, err, "parent: broadcast failed");
139 
140   err = pthread_mutex_unlock (&mut);
141   if (err != 0)
142     error (EXIT_FAILURE, err, "mut unlocking failed");
143 
144   /* Join all threads.  */
145   for (i = 0; i < N; ++i)
146     {
147       printf ("join thread %d\n", i);
148 
149       err = pthread_join (th[i], NULL);
150       if (err != 0)
151 	error (EXIT_FAILURE, err, "join of child %d failed", i);
152     }
153 
154   puts ("done");
155 
156   return 0;
157 }
158 
159 
160 #define TEST_FUNCTION do_test ()
161 #include "../test-skeleton.c"
162