]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond6.c
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / test / nptl / tst-cond6.c
1 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <unistd.h>
27 #include <sys/mman.h>
28 #include <sys/time.h>
29 #include <sys/wait.h>
30 #include <stdint.h>
31
32
33 int *condition;
34
35 static int
36 do_test (void)
37 {
38   size_t ps = sysconf (_SC_PAGESIZE);
39   char tmpfname[] = "/tmp/tst-cond6.XXXXXX";
40   char data[ps];
41   void *mem;
42   int fd;
43   pthread_mutexattr_t ma;
44   pthread_mutex_t *mut1;
45   pthread_mutex_t *mut2;
46   pthread_condattr_t ca;
47   pthread_cond_t *cond;
48   pid_t pid;
49   int result = 0;
50
51   fd = mkstemp (tmpfname);
52   if (fd == -1)
53     {
54       printf ("cannot open temporary file: %m\n");
55       exit (1);
56     }
57
58   /* Make sure it is always removed.  */
59   unlink (tmpfname);
60
61   /* Create one page of data.  */
62   memset (data, '\0', ps);
63
64   /* Write the data to the file.  */
65   if (write (fd, data, ps) != (ssize_t) ps)
66     {
67       puts ("short write");
68       exit (1);
69     }
70
71   mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
72   if (mem == MAP_FAILED)
73     {
74       printf ("mmap failed: %m\n");
75       exit (1);
76     }
77
78   mut1 = (pthread_mutex_t *) (((uintptr_t) mem
79                                + __alignof (pthread_mutex_t))
80                               & ~(__alignof (pthread_mutex_t) - 1));
81   mut2 = mut1 + 1;
82
83   cond = (pthread_cond_t *) (((uintptr_t) (mut2 + 1)
84                               + __alignof (pthread_cond_t))
85                              & ~(__alignof (pthread_cond_t) - 1));
86
87   condition = (int *) (((uintptr_t) (cond + 1) + __alignof (int))
88                        & ~(__alignof (int) - 1));
89
90   if (pthread_mutexattr_init (&ma) != 0)
91     {
92       puts ("mutexattr_init failed");
93       exit (1);
94     }
95
96   if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
97     {
98       puts ("mutexattr_setpshared failed");
99       exit (1);
100     }
101
102   if (pthread_mutex_init (mut1, &ma) != 0)
103     {
104       puts ("1st mutex_init failed");
105       exit (1);
106     }
107
108   if (pthread_mutex_init (mut2, &ma) != 0)
109     {
110       puts ("2nd mutex_init failed");
111       exit (1);
112     }
113
114   if (pthread_condattr_init (&ca) != 0)
115     {
116       puts ("condattr_init failed");
117       exit (1);
118     }
119
120   if (pthread_condattr_setpshared (&ca, PTHREAD_PROCESS_SHARED) != 0)
121     {
122       puts ("condattr_setpshared failed");
123       exit (1);
124     }
125
126   if (pthread_cond_init (cond, &ca) != 0)
127     {
128       puts ("cond_init failed");
129       exit (1);
130     }
131
132   if (pthread_mutex_lock (mut1) != 0)
133     {
134       puts ("parent: 1st mutex_lock failed");
135       exit (1);
136     }
137
138   puts ("going to fork now");
139   pid = fork ();
140   if (pid == -1)
141     {
142       puts ("fork failed");
143       exit (1);
144     }
145   else if (pid == 0)
146     {
147       struct timespec ts;
148       struct timeval tv;
149
150       if (pthread_mutex_lock (mut2) != 0)
151         {
152           puts ("child: mutex_lock failed");
153           exit (1);
154         }
155
156       if (pthread_mutex_unlock (mut1) != 0)
157         {
158           puts ("child: 1st mutex_unlock failed");
159           exit (1);
160         }
161
162       if (gettimeofday (&tv, NULL) != 0)
163         {
164           puts ("gettimeofday failed");
165           exit (1);
166         }
167
168       TIMEVAL_TO_TIMESPEC (&tv, &ts);
169       ts.tv_nsec += 500000000;
170       if (ts.tv_nsec >= 1000000000)
171         {
172           ts.tv_nsec -= 1000000000;
173           ++ts.tv_sec;
174         }
175
176       do
177         if (pthread_cond_timedwait (cond, mut2, &ts) != 0)
178           {
179             puts ("child: cond_wait failed");
180             exit (1);
181           }
182       while (*condition == 0);
183
184       if (pthread_mutex_unlock (mut2) != 0)
185         {
186           puts ("child: 2nd mutex_unlock failed");
187           exit (1);
188         }
189
190       puts ("child done");
191     }
192   else
193     {
194       int status;
195
196       if (pthread_mutex_lock (mut1) != 0)
197         {
198           puts ("parent: 2nd mutex_lock failed");
199           exit (1);
200         }
201
202       if (pthread_mutex_lock (mut2) != 0)
203         {
204           puts ("parent: 3rd mutex_lock failed");
205           exit (1);
206         }
207
208       if (pthread_cond_signal (cond) != 0)
209         {
210           puts ("parent: cond_signal failed");
211           exit (1);
212         }
213
214       *condition = 1;
215
216       if (pthread_mutex_unlock (mut2) != 0)
217         {
218           puts ("parent: mutex_unlock failed");
219           exit (1);
220         }
221
222       puts ("waiting for child");
223
224       waitpid (pid, &status, 0);
225       result |= status;
226
227       puts ("parent done");
228     }
229
230  return result;
231 }
232
233 #define TEST_FUNCTION do_test ()
234 #include "../test-skeleton.c"