OSDN Git Service

whitespace fixes
[uclinux-h8/uclibc-ng.git] / test / nptl / tst-rwlock12.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 <stdint.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/mman.h>
28 #include <sys/wait.h>
29
30
31 static int
32 do_test (void)
33 {
34   size_t ps = sysconf (_SC_PAGESIZE);
35   char tmpfname[] = "/tmp/tst-rwlock12.XXXXXX";
36   char data[ps];
37   void *mem;
38   int fd;
39   pthread_mutex_t *m;
40   pthread_mutexattr_t ma;
41   pthread_rwlock_t *r;
42   pthread_rwlockattr_t ra;
43   pid_t pid;
44   int status = 0;
45
46   fd = mkstemp (tmpfname);
47   if (fd == -1)
48     {
49       printf ("cannot open temporary file: %m\n");
50       return 1;
51     }
52
53   /* Make sure it is always removed.  */
54   unlink (tmpfname);
55
56   /* Create one page of data.  */
57   memset (data, '\0', ps);
58
59   /* Write the data to the file.  */
60   if (write (fd, data, ps) != (ssize_t) ps)
61     {
62       puts ("short write");
63       return 1;
64     }
65
66   mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
67   if (mem == MAP_FAILED)
68     {
69       printf ("mmap failed: %m\n");
70       return 1;
71     }
72
73   r = (pthread_rwlock_t *) (((uintptr_t) mem + __alignof (pthread_rwlock_t))
74                             & ~(__alignof (pthread_rwlock_t) - 1));
75   /* The following assumes alignment for a mutex is at least as high
76      as that for a rwlock.  Which is true in our case.  */
77   m = (pthread_mutex_t *) (r + 1);
78
79   if (pthread_rwlockattr_init (&ra) != 0)
80     {
81       puts ("rwlockattr_init failed");
82       return 1;
83     }
84
85   if (pthread_rwlockattr_setpshared (&ra, PTHREAD_PROCESS_SHARED) != 0)
86     {
87       puts ("rwlockattr_setpshared failed");
88       return 1;
89     }
90
91   if (pthread_rwlock_init (r, &ra) != 0)
92     {
93       puts ("rwlock_init failed");
94       return 1;
95     }
96
97   if (pthread_mutexattr_init (&ma) != 0)
98     {
99       puts ("rwlockattr_init failed");
100       return 1;
101     }
102
103   if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
104     {
105       puts ("mutexattr_setpshared failed");
106       return 1;
107     }
108
109   if (pthread_mutex_init (m, &ma) != 0)
110     {
111       puts ("mutex_init failed");
112       return 1;
113     }
114
115   /* Lock the mutex.  */
116   if (pthread_mutex_lock (m) != 0)
117     {
118       puts ("mutex_lock failed");
119       return 1;
120     }
121
122   puts ("going to fork now");
123   pid = fork ();
124   if (pid == -1)
125     {
126       puts ("fork failed");
127       return 1;
128     }
129   else if (pid == 0)
130     {
131       /* Lock the mutex.  */
132       if (pthread_mutex_lock (m) != 0)
133         {
134           puts ("child: mutex_lock failed");
135           return 1;
136         }
137
138       /* Try to get the rwlock.  */
139       if (pthread_rwlock_trywrlock (r) == 0)
140         {
141           puts ("rwlock_trywrlock succeeded");
142           return 1;
143         }
144
145       /* Try again.  */
146       struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000000 };
147       int e = pthread_rwlock_timedwrlock (r, &ts);
148       if (e == 0)
149         {
150           puts ("rwlock_timedwrlock succeeded");
151           return 1;
152         }
153       if (e != ETIMEDOUT)
154         {
155           puts ("rwlock_timedwrlock didn't return ETIMEDOUT");
156           status = 1;
157         }
158
159       if (pthread_rwlock_tryrdlock (r) == 0)
160         {
161           puts ("rwlock_tryrdlock succeeded");
162           return 1;
163         }
164
165       e = pthread_rwlock_timedrdlock (r, &ts);
166       if (e == 0)
167         {
168           puts ("rwlock_timedrdlock succeeded");
169           return 1;
170         }
171       if (e != ETIMEDOUT)
172         {
173           puts ("rwlock_timedrdlock didn't return ETIMEDOUT");
174           status = 1;
175         }
176     }
177   else
178     {
179       /* Lock the rwlock for writing.  */
180       if (pthread_rwlock_wrlock (r) != 0)
181         {
182           puts ("rwlock_wrlock failed");
183           kill (pid, SIGTERM);
184           return 1;
185         }
186
187       /* Allow the child to run.  */
188       if (pthread_mutex_unlock (m) != 0)
189         {
190           puts ("mutex_unlock failed");
191           kill (pid, SIGTERM);
192           return 1;
193         }
194
195       /* Just wait for the child.  */
196       if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
197         {
198           puts ("waitpid failed");
199           kill (pid, SIGTERM);
200           return 1;
201         }
202     }
203
204   return status;
205 }
206
207 #define TEST_FUNCTION do_test ()
208 #include "../test-skeleton.c"