1204076Spjd/* $FreeBSD$ */
2204076Spjd
3204076Spjd#include <sys/types.h>
4204076Spjd#include <sys/event.h>
5204076Spjd#include <sys/select.h>
6204076Spjd#include <sys/wait.h>
7204076Spjd#include <err.h>
8204076Spjd#include <fcntl.h>
9204076Spjd#include <mqueue.h>
10204076Spjd#include <signal.h>
11204076Spjd#include <stdio.h>
12204076Spjd#include <stdlib.h>
13204076Spjd#include <unistd.h>
14204076Spjd
15204076Spjd#include "freebsd_test_suite/macros.h"
16204076Spjd
17204076Spjd#define MQNAME	"/mytstqueue5"
18204076Spjd#define LOOPS	1000
19204076Spjd#define PRIO	10
20204076Spjd
21204076Spjdstatic void
22204076Spjdsighandler(int sig __unused)
23204076Spjd{
24204076Spjd	write(1, "timeout\n", 8);
25204076Spjd	_exit(1);
26204076Spjd}
27204076Spjd
28204076Spjdint
29204076Spjdmain(void)
30204076Spjd{
31204076Spjd	int status;
32204076Spjd	struct mq_attr attr;
33204076Spjd	struct sigaction sa;
34204076Spjd	sigset_t set;
35204076Spjd	siginfo_t info;
36204076Spjd	mqd_t mq;
37204076Spjd	pid_t pid;
38204076Spjd
39204076Spjd	PLAIN_REQUIRE_KERNEL_MODULE("mqueuefs", 0);
40204076Spjd
41204076Spjd	mq_unlink(MQNAME);
42204076Spjd
43229509Strociny	sigemptyset(&set);
44204076Spjd	sigaddset(&set, SIGRTMIN);
45229509Strociny	sigprocmask(SIG_BLOCK, &set, NULL);
46229509Strociny	sigemptyset(&sa.sa_mask);
47229509Strociny	sa.sa_flags = SA_SIGINFO;
48229509Strociny	sa.sa_sigaction = (void *) SIG_DFL;
49229509Strociny	sigaction(SIGRTMIN, &sa, NULL);
50229509Strociny
51229509Strociny	attr.mq_maxmsg  = 5;
52204076Spjd	attr.mq_msgsize = 128;
53204076Spjd	mq = mq_open(MQNAME, O_CREAT | O_RDWR | O_EXCL, 0666, &attr);
54204076Spjd	if (mq == (mqd_t)-1)
55219864Spjd		err(1, "mq_open()");
56204076Spjd	status = mq_getattr(mq, &attr);
57204076Spjd	if (status)
58204076Spjd		err(1, "mq_getattr()");
59204076Spjd	pid = fork();
60204076Spjd	if (pid == 0) { /* child */
61204076Spjd		int prio, j, i;
62204076Spjd		char *buf;
63204076Spjd		struct sigevent sigev;
64204076Spjd
65204076Spjd		signal(SIGALRM, sighandler);
66204076Spjd
67204076Spjd		sigev.sigev_notify = SIGEV_SIGNAL;
68204076Spjd		sigev.sigev_signo = SIGRTMIN;
69204076Spjd		sigev.sigev_value.sival_int = 2;
70204076Spjd
71204076Spjd		mq_close(mq);
72204076Spjd		mq = mq_open(MQNAME, O_RDWR | O_NONBLOCK);
73204076Spjd		if (mq == (mqd_t)-1)
74204076Spjd			err(1, "child: mq_open");
75204076Spjd		buf = malloc(attr.mq_msgsize);
76204076Spjd		for (j = 0; j < LOOPS; ++j) {
77204076Spjd			alarm(3);
78204076Spjd			status = mq_notify(mq, &sigev);
79204076Spjd			if (status)
80204076Spjd				err(1, "child: mq_notify");
81204076Spjd			status = sigwaitinfo(&set, &info);
82204076Spjd			if (status == -1)
83204076Spjd				err(1, "child: sigwaitinfo");
84204076Spjd			if (info.si_value.sival_int != 2)
85204076Spjd				err(1, "child: sival_int");
86204076Spjd			status = mq_receive(mq, buf, attr.mq_msgsize, &prio);
87204076Spjd			if (status == -1)
88204076Spjd				err(2, "child: mq_receive");
89204076Spjd			for (i = 0; i < attr.mq_msgsize; ++i)
90204076Spjd				if (buf[i] != i)
91204076Spjd					err(3, "child: message data corrupted");
92204076Spjd			if (prio != PRIO)
93204076Spjd				err(4, "child: priority is incorrect: %d",
94204076Spjd					 prio);
95204076Spjd		}
96204076Spjd		alarm(0);
97204076Spjd		free(buf);
98204076Spjd		mq_close(mq);
99204076Spjd		return (0);
100204076Spjd	} else if (pid == -1) {
101204076Spjd		err(1, "fork()");
102229509Strociny	} else {
103204076Spjd		char *buf;
104229509Strociny		int i, j;
105204076Spjd
106204076Spjd		signal(SIGALRM, sighandler);
107204076Spjd		buf = malloc(attr.mq_msgsize);
108204076Spjd		for (j = 0; j < LOOPS; ++j) {
109204076Spjd			for (i = 0; i < attr.mq_msgsize; ++i) {
110204076Spjd				buf[i] = i;
111204076Spjd			}
112204076Spjd			alarm(3);
113229509Strociny			status = mq_send(mq, buf, attr.mq_msgsize, PRIO);
114204076Spjd			if (status) {
115229509Strociny				kill(pid, SIGKILL);
116204076Spjd				err(2, "mq_send()");
117204076Spjd			}
118204076Spjd		}
119204076Spjd		alarm(3);
120204076Spjd		wait(&status);
121204076Spjd		alarm(0);
122204076Spjd	}
123204076Spjd	status = mq_close(mq);
124204076Spjd	if (status)
125204076Spjd		err(1, "mq_close");
126204076Spjd	mq_unlink(MQNAME);
127204076Spjd	return (0);
128204076Spjd}
129204076Spjd