OSDN Git Service

03e4881c9b34bd102065c9dbf1c022f413057920
[uclinux-h8/uClibc.git] / test / nptl / tst-cond12.c
1 /* Copyright (C) 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <pthread.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/mman.h>
27 #include <sys/wait.h>
28
29
30 static char fname[] = "/tmp/tst-cond12-XXXXXX";
31 static int fd;
32
33
34 static void prepare (void);
35 #define PREPARE(argc, argv) prepare ()
36
37 static int do_test (void);
38 #define TEST_FUNCTION do_test ()
39
40 #include "../test-skeleton.c"
41
42
43 static void
44 prepare (void)
45 {
46   fd = mkstemp (fname);
47   if (fd == -1)
48     {
49       printf ("mkstemp failed: %m\n");
50       exit (1);
51     }
52   add_temp_file (fname);
53   if (ftruncate (fd, 1000) < 0)
54     {
55       printf ("ftruncate failed: %m\n");
56       exit (1);
57     }
58 }
59
60
61 static int
62 do_test (void)
63 {
64   struct
65   {
66     pthread_mutex_t m;
67     pthread_cond_t c;
68     int var;
69   } *p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
70   if (p == MAP_FAILED)
71     {
72       printf ("initial mmap failed: %m\n");
73       return 1;
74     }
75
76   pthread_mutexattr_t ma;
77   if (pthread_mutexattr_init (&ma) != 0)
78     {
79       puts ("mutexattr_init failed");
80       return 1;
81     }
82   if (pthread_mutexattr_setpshared (&ma, 1) != 0)
83     {
84       puts ("mutexattr_setpshared failed");
85       return 1;
86     }
87   if (pthread_mutex_init (&p->m, &ma) != 0)
88     {
89       puts ("mutex_init failed");
90       return 1;
91     }
92   if (pthread_mutexattr_destroy (&ma) != 0)
93     {
94       puts ("mutexattr_destroy failed");
95       return 1;
96     }
97
98   pthread_condattr_t ca;
99   if (pthread_condattr_init (&ca) != 0)
100     {
101       puts ("condattr_init failed");
102       return 1;
103     }
104   if (pthread_condattr_setpshared (&ca, 1) != 0)
105     {
106       puts ("condattr_setpshared failed");
107       return 1;
108     }
109   if (pthread_cond_init (&p->c, &ca) != 0)
110     {
111       puts ("mutex_init failed");
112       return 1;
113     }
114   if (pthread_condattr_destroy (&ca) != 0)
115     {
116       puts ("condattr_destroy failed");
117       return 1;
118     }
119
120   if (pthread_mutex_lock (&p->m) != 0)
121     {
122       puts ("initial mutex_lock failed");
123       return 1;
124     }
125
126   p->var = 42;
127
128   pid_t pid = fork ();
129   if (pid == -1)
130     {
131       printf ("fork failed: %m\n");
132       return 1;
133     }
134
135   if (pid == 0)
136     {
137       void *oldp = p;
138       p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
139
140       if (p == oldp)
141         {
142           puts ("child: mapped to same address");
143           kill (getppid (), SIGKILL);
144           exit (1);
145         }
146
147       munmap (oldp, sizeof (*p));
148
149       if (pthread_mutex_lock (&p->m) != 0)
150         {
151           puts ("child: mutex_lock failed");
152           kill (getppid (), SIGKILL);
153           exit (1);
154         }
155
156       p->var = 0;
157
158 #ifndef USE_COND_SIGNAL
159       if (pthread_cond_broadcast (&p->c) != 0)
160         {
161           puts ("child: cond_broadcast failed");
162           kill (getppid (), SIGKILL);
163           exit (1);
164         }
165 #else
166       if (pthread_cond_signal (&p->c) != 0)
167         {
168           puts ("child: cond_signal failed");
169           kill (getppid (), SIGKILL);
170           exit (1);
171         }
172 #endif
173
174       if (pthread_mutex_unlock (&p->m) != 0)
175         {
176           puts ("child: mutex_unlock failed");
177           kill (getppid (), SIGKILL);
178           exit (1);
179         }
180
181       exit (0);
182     }
183
184   do
185     pthread_cond_wait (&p->c, &p->m);
186   while (p->var != 0);
187
188   if (TEMP_FAILURE_RETRY (waitpid (pid, NULL, 0)) != pid)
189     {
190       printf ("waitpid failed: %m\n");
191       kill (pid, SIGKILL);
192       return 1;
193     }
194
195   return 0;
196 }