xref: /freebsd/tools/test/stress2/misc/machipc.sh (revision a90b9d0159070121c221b966469c3e36d912bf82)
1#!/bin/sh
2
3#
4# Copyright (c) 2015 EMC Corp.
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# Threaded Mach IPC test scenario
30# https://people.freebsd.org/~pho/stress/log/kip014.txt
31
32ps -p1 | grep -q launchd || exit 0
33
34odir=`pwd`
35cd /tmp
36sed '1,/^EOF/d' < $odir/$0 > machipc.c
37cc -o machipc -Wall -Wextra -O2 -g machipc.c -lmach -lpthread || exit 1
38rm machipc.c
39cd $odir
40
41(cd ../testcases/swap; ./swap -t 20m -i 20 -h -v) > /dev/null 2>&1 &
42sleep 5
43/tmp/machipc
44pkill swap
45wait
46rm -f /tmp/machipc
47exit 0
48EOF
49#include <sys/types.h>
50
51#include <mach/mach.h>
52
53#include <err.h>
54#include <pthread.h>
55#include <stdlib.h>
56#include <stdio.h>
57#include <string.h>
58#include <unistd.h>
59
60typedef struct {
61	unsigned int msgt_name : 8,
62		     msgt_size : 8,
63		     msgt_number : 12,
64		     msgt_inline : 1,
65		     msgt_longform : 1,
66		     msgt_deallocate : 1,
67		     msgt_unused : 1;
68} mach_msg_type_t;
69
70struct integer_message {
71	mach_msg_header_t head;
72	mach_msg_type_t type;
73
74	int inline_integer;
75};
76
77struct message_recv
78{
79	mach_msg_header_t head;
80	mach_msg_type_t type;
81	int inline_integer;
82	mach_msg_trailer_t trailer;
83};
84
85mach_port_t bootstrap_port;
86
87#define MACH_MSG_TYPE_INTEGER_32 2
88#define N 100000000
89
90static void
91error(int exitcode, int macherr, const char *funcname)
92{
93	printf("%s failed with %x\n", funcname, macherr);
94	exit(exitcode);
95}
96
97void *
98client(void *arg)
99{
100	mach_port_t port = *(mach_port_t *) arg;
101	struct message_recv message = {};
102	int err, i;
103
104	message.head.msgh_local_port = port;
105	message.head.msgh_size = sizeof(message);
106
107	for (i = 0; i < N; i++) {
108		/* Receive a message */
109		err = mach_msg(&message.head,	/* The header */
110		    MACH_RCV_MSG,		/* Flags */
111		    0,				/* Send size */
112		    sizeof(message),		/* Max receive size */
113		    port,			/* Receive port */
114		    MACH_MSG_TIMEOUT_NONE,	/* No timeout */
115		    MACH_PORT_NULL);		/* No notification */
116		if (err)
117			error(1, err, "server mach_msg MACH_RCV_MSG");
118		if (message.inline_integer != i)
119			errx(1, "FAIL message.inline_integer = %d, i = %d",
120			    message.inline_integer, i);
121	}
122
123	return(0);
124}
125
126int
127main(void)
128{
129	pthread_t ptd;
130	mach_port_t port;
131	struct integer_message message;
132	int err, i;
133
134	/* Allocate a port */
135	err = mach_port_allocate(mach_task_self(),
136	    MACH_PORT_RIGHT_RECEIVE, &port);
137	if (err)
138		error(1, err, "mach_port_allocate");
139
140	err = mach_port_insert_right(mach_task_self(),
141	    port, port, MACH_MSG_TYPE_MAKE_SEND);
142
143	if (err)
144		error(10, err, "mach_port_insert_right");
145
146	if ((err = pthread_create(&ptd, NULL, client, &port)) != 0) {
147		errc(1, err, "pthread_create failed");
148	}
149
150	/* Fill the header fields : */
151	message.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND);
152	message.head.msgh_size = sizeof( struct integer_message );
153	message.head.msgh_local_port = MACH_PORT_NULL;
154	message.head.msgh_remote_port = port;
155	message.head.msgh_id = 0;			/* Message id */
156	message.head.msgh_size = sizeof(message);	/* Message size */
157
158	/* Set the message type */
159	message.type.msgt_name = MACH_MSG_TYPE_INTEGER_32;
160	message.type.msgt_size = sizeof(message);
161	message.type.msgt_number = 1;
162	message.type.msgt_inline = TRUE;
163	message.type.msgt_longform = FALSE;
164	message.type.msgt_deallocate = FALSE;
165
166	for (i = 0; i < N; i++) {
167
168		message.inline_integer = i;
169
170		/* Send the message */
171		err = mach_msg(&message.head,	/* The header */
172		    MACH_SEND_MSG,		/* Flags */
173		    sizeof(message),		/* Send size */
174		    0,				/* Max receive Size */
175		    port,			/* Send port */
176		    MACH_MSG_TIMEOUT_NONE,	/* No timeout */
177		    MACH_PORT_NULL);		/* No notification */
178		if (err)
179			error(3, err, "client mach_msg");
180	}
181	pthread_join(ptd, NULL);
182
183	return (0);
184}
185