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