Update.
[platform/upstream/glibc.git] / rt / tst-mqueue6.c
1 /* Test mq_notify.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
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, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <mqueue.h>
24 #include <limits.h>
25 #include <signal.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/mman.h>
31 #include <sys/time.h>
32 #include <sys/wait.h>
33 #include <time.h>
34 #include <unistd.h>
35 #include "tst-mqueue.h"
36
37 #if _POSIX_THREADS
38 # include <pthread.h>
39
40 #define mqsend(q) (mqsend) (q, __LINE__)
41 static inline int
42 (mqsend) (mqd_t q, int line)
43 {
44   char c;
45   if (mq_send (q, &c, 1, 1) != 0)
46     {
47       printf ("mq_send on line %d failed with: %m\n", line);
48       return 1;
49     }
50   return 0;
51 }
52
53 #define mqrecv(q) (mqrecv) (q, __LINE__)
54 static inline int
55 (mqrecv) (mqd_t q, int line)
56 {
57   char c;
58   ssize_t rets = TEMP_FAILURE_RETRY (mq_receive (q, &c, 1, NULL));
59   if (rets != 1)
60     {
61       if (rets == -1)
62         printf ("mq_receive on line %d failed with: %m\n", line);
63       else
64         printf ("mq_receive on line %d returned %zd != 1\n",
65                 line, rets);
66       return 1;
67     }
68   return 0;
69 }
70
71 volatile int fct_cnt, fct_err;
72 size_t fct_guardsize;
73
74 static void
75 fct (union sigval s)
76 {
77   mqd_t q = *(mqd_t *) s.sival_ptr;
78
79   pthread_attr_t nattr;
80   int ret = pthread_getattr_np (pthread_self (), &nattr);
81   if (ret)
82     {
83       errno = ret;
84       printf ("pthread_getattr_np failed: %m\n");
85       fct_err = 1;
86     }
87   else
88     {
89       ret = pthread_attr_getguardsize (&nattr, &fct_guardsize);
90       if (ret)
91         {
92           errno = ret;
93           printf ("pthread_attr_getguardsize failed: %m\n");
94           fct_err = 1;
95         }
96       if (pthread_attr_destroy (&nattr) != 0)
97         {
98           puts ("pthread_attr_destroy failed");
99           fct_err = 1;
100         }
101     }
102
103   ++fct_cnt;
104   fct_err |= mqsend (q);
105 }
106
107 #define TEST_FUNCTION do_test ()
108 static int
109 do_test (void)
110 {
111   int result = 0;
112
113   char name[sizeof "/tst-mqueue6-" + sizeof (pid_t) * 3];
114   snprintf (name, sizeof (name), "/tst-mqueue6-%u", getpid ());
115
116   struct mq_attr attr = { .mq_maxmsg = 1, .mq_msgsize = 1 };
117   mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
118
119   if (q == (mqd_t) -1)
120     {
121       printf ("mq_open failed with: %m\n");
122       return result;
123     }
124   else
125     add_temp_mq (name);
126
127   pthread_attr_t nattr;
128   if (pthread_attr_init (&nattr)
129       || pthread_attr_setguardsize (&nattr, 0))
130     {
131       puts ("pthread_attr_t setup failed");
132       result = 1;
133     }
134
135   fct_guardsize = 1;
136
137   struct sigevent ev;
138   memset (&ev, 0xaa, sizeof (ev));
139   ev.sigev_notify = SIGEV_THREAD;
140   ev.sigev_notify_function = fct;
141   ev.sigev_notify_attributes = &nattr;
142   ev.sigev_value.sival_ptr = &q;
143   if (mq_notify (q, &ev) != 0)
144     {
145       printf ("mq_notify (q, { SIGEV_THREAD }) failed with: %m\n");
146       result = 1;
147     }
148
149   size_t ps = sysconf (_SC_PAGESIZE);
150   if (pthread_attr_setguardsize (&nattr, 32 * ps))
151     {
152       puts ("pthread_attr_t setup failed");
153       result = 1;
154     }
155
156   if (mq_notify (q, &ev) == 0)
157     {
158       puts ("second mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
159       result = 1;
160     }
161   else if (errno != EBUSY)
162     {
163       printf ("second mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
164       result = 1;
165     }
166
167   if (fct_cnt != 0)
168     {
169       printf ("fct called too early (%d on %d)\n", fct_cnt, __LINE__);
170       result = 1;
171     }
172
173   result |= mqsend (q);
174
175   result |= mqrecv (q);
176   result |= mqrecv (q);
177
178   if (fct_cnt != 1)
179     {
180       printf ("fct not called (%d on %d)\n", fct_cnt, __LINE__);
181       result = 1;
182     }
183   else if (fct_guardsize != 0)
184     {
185       printf ("fct_guardsize %zd != 0\n", fct_guardsize);
186       result = 1;
187     }
188
189   if (mq_notify (q, &ev) != 0)
190     {
191       printf ("third mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
192       result = 1;
193     }
194
195   if (mq_notify (q, NULL) != 0)
196     {
197       printf ("mq_notify (q, NULL) failed with: %m\n");
198       result = 1;
199     }
200
201   memset (&ev, 0x11, sizeof (ev));
202   ev.sigev_notify = SIGEV_THREAD;
203   ev.sigev_notify_function = fct;
204   ev.sigev_notify_attributes = &nattr;
205   ev.sigev_value.sival_ptr = &q;
206   if (mq_notify (q, &ev) != 0)
207     {
208       printf ("mq_notify (q, { SIGEV_THREAD }) failed with: %m\n");
209       result = 1;
210     }
211
212   if (pthread_attr_setguardsize (&nattr, 0))
213     {
214       puts ("pthread_attr_t setup failed");
215       result = 1;
216     }
217
218   if (mq_notify (q, &ev) == 0)
219     {
220       puts ("second mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
221       result = 1;
222     }
223   else if (errno != EBUSY)
224     {
225       printf ("second mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
226       result = 1;
227     }
228
229   if (fct_cnt != 1)
230     {
231       printf ("fct called too early (%d on %d)\n", fct_cnt, __LINE__);
232       result = 1;
233     }
234
235   result |= mqsend (q);
236
237   result |= mqrecv (q);
238   result |= mqrecv (q);
239
240   if (fct_cnt != 2)
241     {
242       printf ("fct not called (%d on %d)\n", fct_cnt, __LINE__);
243       result = 1;
244     }
245   else if (fct_guardsize != 32 * ps)
246     {
247       printf ("fct_guardsize %zd != %zd\n", fct_guardsize, 32 * ps);
248       result = 1;
249     }
250
251   if (mq_notify (q, &ev) != 0)
252     {
253       printf ("third mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
254       result = 1;
255     }
256
257   if (mq_notify (q, NULL) != 0)
258     {
259       printf ("mq_notify (q, NULL) failed with: %m\n");
260       result = 1;
261     }
262
263   if (pthread_attr_destroy (&nattr) != 0)
264     {
265       puts ("pthread_attr_destroy failed");
266       result = 1;
267     }
268
269   if (mq_unlink (name) != 0)
270     {
271       printf ("mq_unlink failed: %m\n");
272       result = 1;
273     }
274
275   if (mq_close (q) != 0)
276     {
277       printf ("mq_close failed: %m\n");
278       result = 1;
279     }
280
281   memset (&ev, 0x55, sizeof (ev));
282   ev.sigev_notify = SIGEV_THREAD;
283   ev.sigev_notify_function = fct;
284   ev.sigev_notify_attributes = NULL;
285   ev.sigev_value.sival_int = 0;
286   if (mq_notify (q, &ev) == 0)
287     {
288       puts ("mq_notify on closed mqd_t unexpectedly succeeded");
289       result = 1;
290     }
291   else if (errno != EBADF)
292     {
293       printf ("mq_notify on closed mqd_t did not fail with EBADF: %m\n");
294       result = 1;
295     }
296
297   if (fct_err)
298     result = 1;
299   return result;
300 }
301 #else
302 # define TEST_FUNCTION 0
303 #endif
304
305 #include "../test-skeleton.c"