1 /* Test SIGEV_THREAD handling for POSIX message queues.
2 Copyright (C) 2004-2021 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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 <https://www.gnu.org/licenses/>. */
36 static const char message
[] = "hello";
46 /* Put the mq in non-blocking mode. */
48 if (mq_getattr (m
, &attr
) != 0)
50 printf ("%s: mq_getattr failed: %m\n", __FUNCTION__
);
53 attr
.mq_flags
|= O_NONBLOCK
;
54 if (mq_setattr (m
, &attr
, NULL
) != 0)
56 printf ("%s: mq_setattr failed: %m\n", __FUNCTION__
);
60 /* Check the values. */
61 if (attr
.mq_maxmsg
!= MAXMSG
)
63 printf ("%s: mq_maxmsg wrong: is %jd, expecte %d\n",
64 __FUNCTION__
, (intmax_t) attr
.mq_maxmsg
, MAXMSG
);
67 if (attr
.mq_msgsize
!= MAXMSG
)
69 printf ("%s: mq_msgsize wrong: is %jd, expecte %d\n",
70 __FUNCTION__
, (intmax_t) attr
.mq_msgsize
, MSGSIZE
);
74 /* Read the message. */
75 char buf
[attr
.mq_msgsize
];
76 ssize_t n
= TEMP_FAILURE_RETRY (mq_receive (m
, buf
, attr
.mq_msgsize
, NULL
));
77 if (n
!= sizeof (message
))
79 printf ("%s: length of message wrong: is %zd, expected %zu\n",
80 __FUNCTION__
, n
, sizeof (message
));
83 if (memcmp (buf
, message
, sizeof (message
)) != 0)
85 printf ("%s: message wrong: is \"%s\", expected \"%s\"\n",
86 __FUNCTION__
, buf
, message
);
97 char tmpfname
[] = "/tmp/tst-mqueue3-barrier.XXXXXX";
98 int fd
= mkstemp (tmpfname
);
101 printf ("cannot open temporary file: %m\n");
105 /* Make sure it is always removed. */
108 /* Create one page of data. */
109 size_t ps
= sysconf (_SC_PAGESIZE
);
111 memset (data
, '\0', ps
);
113 /* Write the data to the file. */
114 if (write (fd
, data
, ps
) != (ssize_t
) ps
)
116 puts ("short write");
120 void *mem
= mmap (NULL
, ps
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0);
121 if (mem
== MAP_FAILED
)
123 printf ("mmap failed: %m\n");
127 pthread_barrier_t
*b
;
128 b
= (pthread_barrier_t
*) (((uintptr_t) mem
+ __alignof (pthread_barrier_t
))
129 & ~(__alignof (pthread_barrier_t
) - 1));
131 pthread_barrierattr_t a
;
132 if (pthread_barrierattr_init (&a
) != 0)
134 puts ("barrierattr_init failed");
138 if (pthread_barrierattr_setpshared (&a
, PTHREAD_PROCESS_SHARED
) != 0)
140 puts ("barrierattr_setpshared failed, could not test");
144 if (pthread_barrier_init (b
, &a
, 2) != 0)
146 puts ("barrier_init failed");
150 if (pthread_barrierattr_destroy (&a
) != 0)
152 puts ("barrierattr_destroy failed");
156 /* Name for the message queue. */
157 char mqname
[sizeof ("/tst-mqueue3-") + 3 * sizeof (pid_t
)];
158 snprintf (mqname
, sizeof (mqname
) - 1, "/tst-mqueue3-%ld",
159 (long int) getpid ());
161 /* Create the message queue. */
162 struct mq_attr attr
= { .mq_maxmsg
= MAXMSG
, .mq_msgsize
= MSGSIZE
};
163 m
= mq_open (mqname
, O_CREAT
| O_EXCL
| O_RDWR
, 0600, &attr
);
168 puts ("not implemented");
172 puts ("mq_open failed");
176 /* Unlink the message queue right away. */
177 if (mq_unlink (mqname
) != 0)
179 puts ("mq_unlink failed");
186 puts ("fork failed");
191 /* Request notification via thread. */
193 ev
.sigev_notify
= SIGEV_THREAD
;
194 ev
.sigev_notify_function
= fct
;
195 ev
.sigev_value
.sival_ptr
= NULL
;
196 ev
.sigev_notify_attributes
= NULL
;
198 /* Tell the kernel. */
199 if (mq_notify (m
,&ev
) != 0)
201 puts ("mq_notify failed");
205 /* Tell the parent we are ready. */
206 (void) pthread_barrier_wait (b
);
208 /* Make sure the process goes away eventually. */
211 /* Do nothing forever. */
216 /* Wait for the child process to register to notification method. */
217 (void) pthread_barrier_wait (b
);
219 /* Send the message. */
220 if (mq_send (m
, message
, sizeof (message
), 1) != 0)
223 puts ("mq_send failed");
228 if (TEMP_FAILURE_RETRY (waitpid (pid
, &r
, 0)) != pid
)
231 puts ("waitpid failed");
235 return WIFEXITED (r
) && WEXITSTATUS (r
) == UNIQUE
? 0 : 1;
237 # define TEST_FUNCTION do_test ()
239 # define TEST_FUNCTION 0
242 #include "../test-skeleton.c"