1 /* Test SIGEV_THREAD handling for POSIX message queues.
2 Copyright (C) 2004-2024 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/>. */
30 #include <support/check.h>
37 static const char message
[] = "hello";
47 /* Put the mq in non-blocking mode. */
49 if (mq_getattr (m
, &attr
) != 0)
51 printf ("%s: mq_getattr failed: %m\n", __FUNCTION__
);
54 attr
.mq_flags
|= O_NONBLOCK
;
55 if (mq_setattr (m
, &attr
, NULL
) != 0)
57 printf ("%s: mq_setattr failed: %m\n", __FUNCTION__
);
61 /* Check the values. */
62 if (attr
.mq_maxmsg
!= MAXMSG
)
64 printf ("%s: mq_maxmsg wrong: is %jd, expected %d\n",
65 __FUNCTION__
, (intmax_t) attr
.mq_maxmsg
, MAXMSG
);
68 if (attr
.mq_msgsize
!= MAXMSG
)
70 printf ("%s: mq_msgsize wrong: is %jd, expected %d\n",
71 __FUNCTION__
, (intmax_t) attr
.mq_msgsize
, MSGSIZE
);
75 /* Read the message. */
76 char buf
[attr
.mq_msgsize
];
77 ssize_t n
= TEMP_FAILURE_RETRY (mq_receive (m
, buf
, attr
.mq_msgsize
, NULL
));
78 if (n
!= sizeof (message
))
80 printf ("%s: length of message wrong: is %zd, expected %zu\n",
81 __FUNCTION__
, n
, sizeof (message
));
84 if (memcmp (buf
, message
, sizeof (message
)) != 0)
86 printf ("%s: message wrong: is \"%s\", expected \"%s\"\n",
87 __FUNCTION__
, buf
, message
);
98 char tmpfname
[] = "/tmp/tst-mqueue3-barrier.XXXXXX";
99 int fd
= mkstemp (tmpfname
);
102 printf ("cannot open temporary file: %m\n");
106 /* Make sure it is always removed. */
109 /* Create one page of data. */
110 size_t ps
= sysconf (_SC_PAGESIZE
);
112 memset (data
, '\0', ps
);
114 /* Write the data to the file. */
115 if (write (fd
, data
, ps
) != (ssize_t
) ps
)
117 puts ("short write");
121 void *mem
= mmap (NULL
, ps
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0);
122 if (mem
== MAP_FAILED
)
124 printf ("mmap failed: %m\n");
128 pthread_barrier_t
*b
;
129 b
= (pthread_barrier_t
*) (((uintptr_t) mem
+ __alignof (pthread_barrier_t
))
130 & ~(__alignof (pthread_barrier_t
) - 1));
132 pthread_barrierattr_t a
;
133 if (pthread_barrierattr_init (&a
) != 0)
135 puts ("barrierattr_init failed");
139 if (pthread_barrierattr_setpshared (&a
, PTHREAD_PROCESS_SHARED
) != 0)
141 puts ("barrierattr_setpshared failed, could not test");
145 if (pthread_barrier_init (b
, &a
, 2) != 0)
147 puts ("barrier_init failed");
151 if (pthread_barrierattr_destroy (&a
) != 0)
153 puts ("barrierattr_destroy failed");
157 /* Name for the message queue. */
158 char mqname
[sizeof ("/tst-mqueue3-") + 3 * sizeof (pid_t
)];
159 snprintf (mqname
, sizeof (mqname
) - 1, "/tst-mqueue3-%ld",
160 (long int) getpid ());
162 /* Create the message queue. */
163 struct mq_attr attr
= { .mq_maxmsg
= MAXMSG
, .mq_msgsize
= MSGSIZE
};
164 m
= mq_open (mqname
, O_CREAT
| O_EXCL
| O_RDWR
, 0600, &attr
);
169 FAIL_UNSUPPORTED ("mq_open not supported");
171 printf ("mq_open failed with: %m\n");
175 /* Unlink the message queue right away. */
176 if (mq_unlink (mqname
) != 0)
178 puts ("mq_unlink failed");
185 puts ("fork failed");
190 /* Request notification via thread. */
192 ev
.sigev_notify
= SIGEV_THREAD
;
193 ev
.sigev_notify_function
= fct
;
194 ev
.sigev_value
.sival_ptr
= NULL
;
195 ev
.sigev_notify_attributes
= NULL
;
197 /* Tell the kernel. */
198 if (mq_notify (m
,&ev
) != 0)
200 puts ("mq_notify failed");
204 /* Tell the parent we are ready. */
205 (void) pthread_barrier_wait (b
);
207 /* Make sure the process goes away eventually. */
210 /* Do nothing forever. */
215 /* Wait for the child process to register to notification method. */
216 (void) pthread_barrier_wait (b
);
218 /* Send the message. */
219 if (mq_send (m
, message
, sizeof (message
), 1) != 0)
222 puts ("mq_send failed");
227 if (TEMP_FAILURE_RETRY (waitpid (pid
, &r
, 0)) != pid
)
230 puts ("waitpid failed");
234 return WIFEXITED (r
) && WEXITSTATUS (r
) == UNIQUE
? 0 : 1;
236 # define TEST_FUNCTION do_test ()
238 # define TEST_FUNCTION 0
241 #include "../test-skeleton.c"