iconv: Suppress array out of bounds warning.
[platform/upstream/glibc.git] / nptl / tst-default-attr.c
1 /* Verify that pthread_[gs]etattr_default_np work correctly.
2
3    Copyright (C) 2013-2015 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <pthread.h>
21 #include <stdio.h>
22 #include <stdint.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <stdbool.h>
27
28 #define RETURN_IF_FAIL(f, ...) \
29   ({                                                                          \
30     int ret = f (__VA_ARGS__);                                                \
31     if (ret != 0)                                                             \
32       {                                                                       \
33         printf ("%s:%d: %s returned %d (errno = %d)\n", __FILE__, __LINE__,   \
34                 #f, ret, errno);                                              \
35         return ret;                                                           \
36       }                                                                       \
37   })
38
39 static int (*verify_result) (pthread_attr_t *);
40 static size_t stacksize = 1024 * 1024;
41 static size_t guardsize;
42 static bool do_join = true;
43 static int running = 0;
44 static int detach_failed = 0;
45 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
46 static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
47
48 static void *
49 thr (void *unused __attribute__ ((unused)))
50 {
51   pthread_attr_t attr;
52   int ret;
53
54   memset (&attr, 0xab, sizeof attr);
55   /* To verify that the pthread_setattr_default_np worked.  */
56   if ((ret = pthread_getattr_default_np (&attr)) != 0)
57     {
58       printf ("pthread_getattr_default_np failed: %s\n", strerror (ret));
59       goto out;
60     }
61
62   if ((ret = (*verify_result) (&attr)) != 0)
63     goto out;
64
65   memset (&attr, 0xab, sizeof attr);
66   /* To verify that the attributes actually got applied.  */
67   if ((ret = pthread_getattr_np (pthread_self (), &attr)) != 0)
68     {
69       printf ("pthread_getattr_default_np failed: %s\n", strerror (ret));
70       goto out;
71     }
72
73   ret = (*verify_result) (&attr);
74
75 out:
76   if (!do_join)
77     {
78       pthread_mutex_lock (&m);
79       running--;
80       pthread_cond_signal (&c);
81       pthread_mutex_unlock (&m);
82
83       detach_failed |= ret;
84     }
85
86   return (void *) (uintptr_t) ret;
87 }
88
89 static int
90 run_threads (const pthread_attr_t *attr)
91 {
92   pthread_t t;
93   void *tret = NULL;
94
95   RETURN_IF_FAIL (pthread_setattr_default_np, attr);
96
97   /* Run twice to ensure that the attributes do not get overwritten in the
98      first run somehow.  */
99   for (int i = 0; i < 2; i++)
100     {
101       RETURN_IF_FAIL (pthread_create, &t, NULL, thr, NULL);
102       if (do_join)
103         RETURN_IF_FAIL (pthread_join, t, &tret);
104       else
105         {
106           pthread_mutex_lock (&m);
107           running++;
108           pthread_mutex_unlock (&m);
109         }
110
111       if (tret != NULL)
112         {
113           puts ("Thread failed");
114           return 1;
115         }
116     }
117
118   /* Stay in sync for detached threads and get their status.  */
119   while (!do_join)
120     {
121       pthread_mutex_lock (&m);
122       if (running == 0)
123         {
124           pthread_mutex_unlock (&m);
125           break;
126         }
127       pthread_cond_wait (&c, &m);
128       pthread_mutex_unlock (&m);
129     }
130
131   return 0;
132 }
133
134 static int
135 verify_detach_result (pthread_attr_t *attr)
136 {
137   int state;
138
139   RETURN_IF_FAIL (pthread_attr_getdetachstate, attr, &state);
140
141   if (state != PTHREAD_CREATE_DETACHED)
142     {
143       puts ("failed to set detach state");
144       return 1;
145     }
146
147   return 0;
148 }
149
150 static int
151 do_detach_test (void)
152 {
153   pthread_attr_t attr;
154
155   do_join = false;
156   RETURN_IF_FAIL (pthread_attr_init, &attr);
157   RETURN_IF_FAIL (pthread_attr_setdetachstate, &attr, PTHREAD_CREATE_DETACHED);
158
159   RETURN_IF_FAIL (run_threads, &attr);
160   return detach_failed;
161 }
162
163 static int
164 verify_affinity_result (pthread_attr_t *attr)
165 {
166   cpu_set_t cpuset;
167
168   RETURN_IF_FAIL (pthread_attr_getaffinity_np, attr, sizeof (cpuset), &cpuset);
169   if (!CPU_ISSET (0, &cpuset))
170     {
171       puts ("failed to set cpu affinity");
172       return 1;
173     }
174
175   return 0;
176 }
177
178 static int
179 do_affinity_test (void)
180 {
181   pthread_attr_t attr;
182
183   RETURN_IF_FAIL (pthread_attr_init, &attr);
184
185   /* Processor affinity.  Like scheduling policy, this could fail if the user
186      does not have the necessary privileges.  So we only spew a warning if
187      pthread_create fails with EPERM.  A computer has at least one CPU.  */
188   cpu_set_t cpuset;
189   CPU_ZERO (&cpuset);
190   CPU_SET (0, &cpuset);
191   RETURN_IF_FAIL (pthread_attr_setaffinity_np, &attr, sizeof (cpuset), &cpuset);
192
193   int ret = run_threads (&attr);
194
195   if (ret == EPERM)
196     {
197       printf ("Skipping CPU Affinity test: %s\n", strerror (ret));
198       return 0;
199     }
200   else if (ret != 0)
201     return ret;
202
203   return 0;
204 }
205
206 static int
207 verify_sched_result (pthread_attr_t *attr)
208 {
209   int inherited, policy;
210   struct sched_param param;
211
212   RETURN_IF_FAIL (pthread_attr_getinheritsched, attr, &inherited);
213   if (inherited != PTHREAD_EXPLICIT_SCHED)
214     {
215       puts ("failed to set EXPLICIT_SCHED (%d != %d)");
216       return 1;
217     }
218
219   RETURN_IF_FAIL (pthread_attr_getschedpolicy, attr, &policy);
220   if (policy != SCHED_RR)
221     {
222       printf ("failed to set SCHED_RR (%d != %d)\n", policy, SCHED_RR);
223       return 1;
224     }
225
226   RETURN_IF_FAIL (pthread_attr_getschedparam, attr, &param);
227   if (param.sched_priority != 42)
228     {
229       printf ("failed to set sched_priority (%d != %d)\n",
230               param.sched_priority, 42);
231       return 1;
232     }
233
234   return 0;
235 }
236
237 static int
238 do_sched_test (void)
239 {
240   pthread_attr_t attr;
241
242   RETURN_IF_FAIL (pthread_attr_init, &attr);
243
244   /* Scheduling policy.  Note that we don't always test these since it's
245      possible that the user the tests run as don't have the appropriate
246      privileges.  */
247   RETURN_IF_FAIL (pthread_attr_setinheritsched, &attr, PTHREAD_EXPLICIT_SCHED);
248   RETURN_IF_FAIL (pthread_attr_setschedpolicy, &attr, SCHED_RR);
249
250   struct sched_param param;
251   param.sched_priority = 42;
252   RETURN_IF_FAIL (pthread_attr_setschedparam, &attr, &param);
253
254   int ret = run_threads (&attr);
255
256   if (ret == EPERM)
257     {
258       printf ("Skipping Scheduler Attributes test: %s\n", strerror (ret));
259       return 0;
260     }
261   else if (ret != 0)
262     return ret;
263
264   return 0;
265 }
266
267 static int
268 verify_guardsize_result (pthread_attr_t *attr)
269 {
270   size_t guard;
271
272   RETURN_IF_FAIL (pthread_attr_getguardsize, attr, &guard);
273
274   if (guardsize != guard)
275     {
276       printf ("failed to set guardsize (%zu, %zu)\n", guardsize, guard);
277       return 1;
278     }
279
280   return 0;
281 }
282
283 static int
284 do_guardsize_test (void)
285 {
286   long int pagesize = sysconf (_SC_PAGESIZE);
287   pthread_attr_t attr;
288
289   if (pagesize < 0)
290     {
291       printf ("sysconf failed: %s\n", strerror (errno));
292       return 1;
293     }
294
295   RETURN_IF_FAIL (pthread_getattr_default_np, &attr);
296
297   /* Increase default guardsize by a page.  */
298   RETURN_IF_FAIL (pthread_attr_getguardsize, &attr, &guardsize);
299   guardsize += pagesize;
300   RETURN_IF_FAIL (pthread_attr_setguardsize, &attr, guardsize);
301   RETURN_IF_FAIL (run_threads, &attr);
302
303   return 0;
304 }
305
306 static int
307 verify_stacksize_result (pthread_attr_t *attr)
308 {
309   size_t stack;
310
311   RETURN_IF_FAIL (pthread_attr_getstacksize, attr, &stack);
312
313   if (stacksize != stack)
314     {
315       printf ("failed to set default stacksize (%zu, %zu)\n", stacksize, stack);
316       return 1;
317     }
318
319   return 0;
320 }
321
322 static int
323 do_stacksize_test (void)
324 {
325   long int pagesize = sysconf (_SC_PAGESIZE);
326   pthread_attr_t attr;
327
328   if (pagesize < 0)
329     {
330       printf ("sysconf failed: %s\n", strerror (errno));
331       return 1;
332     }
333
334   /* Perturb the size by a page so that we're not aligned on the 64K boundary.
335      pthread_create does this perturbation on x86 to avoid causing the 64k
336      aliasing conflict.  We want to prevent pthread_create from doing that
337      since it is not consistent for all architectures.  */
338   stacksize += pagesize;
339
340   RETURN_IF_FAIL (pthread_attr_init, &attr);
341
342   /* Run twice to ensure that we don't give a false positive.  */
343   RETURN_IF_FAIL (pthread_attr_setstacksize, &attr, stacksize);
344   RETURN_IF_FAIL (run_threads, &attr);
345   stacksize *= 2;
346   RETURN_IF_FAIL (pthread_attr_setstacksize, &attr, stacksize);
347   RETURN_IF_FAIL (run_threads, &attr);
348   return 0;
349 }
350
351 /* We test each attribute separately because sched and affinity tests may need
352    additional user privileges that may not be available during the test run.
353    Each attribute test is a set of two functions, viz. a function to set the
354    default attribute (do_foo_test) and another to verify its result
355    (verify_foo_result).  Each test spawns a thread and checks (1) if the
356    attribute values were applied correctly and (2) if the change in the default
357    value reflected.  */
358 static int
359 do_test (void)
360 {
361   puts ("stacksize test");
362   verify_result = verify_stacksize_result;
363   RETURN_IF_FAIL (do_stacksize_test);
364
365   puts ("guardsize test");
366   verify_result = verify_guardsize_result;
367   RETURN_IF_FAIL (do_guardsize_test);
368
369   puts ("sched test");
370   verify_result = verify_sched_result;
371   RETURN_IF_FAIL (do_sched_test);
372
373   puts ("affinity test");
374   verify_result = verify_affinity_result;
375   RETURN_IF_FAIL (do_affinity_test);
376
377   puts ("detach test");
378   verify_result = verify_detach_result;
379   RETURN_IF_FAIL (do_detach_test);
380
381   return 0;
382 }
383
384 #define TEST_FUNCTION do_test ()
385 #include "../test-skeleton.c"