1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * sched-messaging.c
4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * messaging: Benchmark for scheduler and IPC mechanisms
6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Based on hackbench by Rusty Russell <rusty@rustcorp.com.au>
8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../perf.h"
13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../util/util.h"
14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../util/parse-options.h"
15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../builtin.h"
16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "bench.h"
17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Test groups of 20 processes spraying to 20 receivers */
19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* ANDROID_CHANGE_BEGIN */
20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#ifdef __BIONIC__
21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <asm/page.h>
22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif
23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* ANDROID_CHANGE_END */
24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <pthread.h>
25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdio.h>
26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdlib.h>
27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <string.h>
28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <errno.h>
29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <unistd.h>
30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/types.h>
31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/socket.h>
32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/wait.h>
33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/time.h>
34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/poll.h>
35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <limits.h>
36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define DATASIZE 100
38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic bool use_pipes = false;
40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic unsigned int loops = 100;
41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic bool thread_mode = false;
42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic unsigned int num_groups = 10;
43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct sender_context {
45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	unsigned int num_fds;
46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ready_out;
47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int wakefd;
48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int out_fds[0];
49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct receiver_context {
52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	unsigned int num_packets;
53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int in_fds[2];
54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ready_out;
55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int wakefd;
56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void barf(const char *msg)
59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fprintf(stderr, "%s (error: %s)\n", msg, strerror(errno));
61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	exit(1);
62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void fdpair(int fds[2])
65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (use_pipes) {
67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pipe(fds) == 0)
68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return;
69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else {
70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0)
71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return;
72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	barf(use_pipes ? "pipe()" : "socketpair()");
75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Block until we're ready to go */
78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void ready(int ready_out, int wakefd)
79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char dummy;
81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct pollfd pollfd = { .fd = wakefd, .events = POLLIN };
82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Tell them we're ready. */
84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (write(ready_out, &dummy, 1) != 1)
85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		barf("CLIENT: ready write");
86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Wait for "GO" signal */
88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (poll(&pollfd, 1, -1) != 1)
89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		barf("poll");
90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Sender sprays loops messages down each file descriptor */
93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void *sender(struct sender_context *ctx)
94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char data[DATASIZE];
96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	unsigned int i, j;
97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ready(ctx->ready_out, ctx->wakefd);
99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Now pump to every receiver. */
101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < loops; i++) {
102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		for (j = 0; j < ctx->num_fds; j++) {
103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			int ret, done = 0;
104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengagain:
106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = write(ctx->out_fds[j], data + done,
107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				    sizeof(data)-done);
108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (ret < 0)
109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				barf("SENDER: write");
110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			done += ret;
111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (done < DATASIZE)
112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goto again;
113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return NULL;
117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* One receiver per fd */
121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void *receiver(struct receiver_context* ctx)
122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	unsigned int i;
124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!thread_mode)
126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		close(ctx->in_fds[1]);
127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Wait for start... */
129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ready(ctx->ready_out, ctx->wakefd);
130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Receive them all */
132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < ctx->num_packets; i++) {
133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		char data[DATASIZE];
134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int ret, done = 0;
135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengagain:
137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = read(ctx->in_fds[0], data + done, DATASIZE - done);
138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			barf("SERVER: read");
140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		done += ret;
141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (done < DATASIZE)
142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto again;
143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return NULL;
146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic pthread_t create_worker(void *ctx, void *(*func)(void *))
149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_attr_t attr;
151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_t childid;
152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int err;
153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!thread_mode) {
155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* process mode */
156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* Fork the receiver. */
157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		switch (fork()) {
158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case -1:
159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			barf("fork()");
160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case 0:
162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			(*func) (ctx);
163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			exit(0);
164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		default:
166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return (pthread_t)0;
170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pthread_attr_init(&attr) != 0)
173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		barf("pthread_attr_init:");
174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#ifndef __ia64__
176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN) != 0)
177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		barf("pthread_attr_setstacksize");
178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif
179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	err = pthread_create(&childid, &attr, func, ctx);
181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (err != 0) {
182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fprintf(stderr, "pthread_create failed: %s (%d)\n",
183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			strerror(err), err);
184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		exit(-1);
185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return childid;
187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void reap_worker(pthread_t id)
190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int proc_status;
192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	void *thread_status;
193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!thread_mode) {
195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* process mode */
196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		wait(&proc_status);
197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!WIFEXITED(proc_status))
198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			exit(1);
199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else {
200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pthread_join(id, &thread_status);
201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* One group of senders and receivers */
205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic unsigned int group(pthread_t *pth,
206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		unsigned int num_fds,
207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int ready_out,
208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int wakefd)
209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	unsigned int i;
211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct sender_context *snd_ctx = malloc(sizeof(struct sender_context)
212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			+ num_fds * sizeof(int));
213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!snd_ctx)
215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		barf("malloc()");
216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < num_fds; i++) {
218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int fds[2];
219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct receiver_context *ctx = malloc(sizeof(*ctx));
220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!ctx)
222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			barf("malloc()");
223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* Create the pipe between client and server */
226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fdpair(fds);
227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ctx->num_packets = num_fds * loops;
229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ctx->in_fds[0] = fds[0];
230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ctx->in_fds[1] = fds[1];
231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ctx->ready_out = ready_out;
232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ctx->wakefd = wakefd;
233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pth[i] = create_worker(ctx, (void *)receiver);
235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		snd_ctx->out_fds[i] = fds[1];
237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!thread_mode)
238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close(fds[0]);
239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Now we have all the fds, fork the senders */
242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < num_fds; i++) {
243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		snd_ctx->ready_out = ready_out;
244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		snd_ctx->wakefd = wakefd;
245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		snd_ctx->num_fds = num_fds;
246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pth[num_fds+i] = create_worker(snd_ctx, (void *)sender);
248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Close the fds we have left */
251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!thread_mode)
252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		for (i = 0; i < num_fds; i++)
253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			close(snd_ctx->out_fds[i]);
254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Return number of children to reap */
256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return num_fds * 2;
257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const struct option options[] = {
260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_BOOLEAN('p', "pipe", &use_pipes,
261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    "Use pipe() instead of socketpair()"),
262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_BOOLEAN('t', "thread", &thread_mode,
263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    "Be multi thread instead of multi process"),
264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"),
265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_UINTEGER('l', "loop", &loops, "Specify number of loops"),
266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_END()
267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const char * const bench_sched_message_usage[] = {
270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	"perf bench sched messaging <options>",
271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	NULL
272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint bench_sched_messaging(int argc, const char **argv,
275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    const char *prefix __used)
276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	unsigned int i, total_children;
278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct timeval start, stop, diff;
279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	unsigned int num_fds = 20;
280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int readyfds[2], wakefds[2];
281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char dummy;
282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pthread_t *pth_tab;
283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	argc = parse_options(argc, argv, options,
285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			     bench_sched_message_usage, 0);
286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pth_tab = malloc(num_fds * 2 * num_groups * sizeof(pthread_t));
288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!pth_tab)
289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		barf("main:malloc()");
290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fdpair(readyfds);
292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fdpair(wakefds);
293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	total_children = 0;
295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < num_groups; i++)
296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		total_children += group(pth_tab+total_children, num_fds,
297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					readyfds[1], wakefds[0]);
298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Wait for everyone to be ready */
300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < total_children; i++)
301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (read(readyfds[0], &dummy, 1) != 1)
302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			barf("Reading for readyfds");
303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	gettimeofday(&start, NULL);
305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Kick them off */
307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (write(wakefds[1], &dummy, 1) != 1)
308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		barf("Writing to start them");
309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Reap them all */
311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < total_children; i++)
312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		reap_worker(pth_tab[i]);
313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	gettimeofday(&stop, NULL);
315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	timersub(&stop, &start, &diff);
317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	switch (bench_format) {
319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case BENCH_FORMAT_DEFAULT:
320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf("# %d sender and receiver %s per group\n",
321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       num_fds, thread_mode ? "threads" : "processes");
322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf("# %d groups == %d %s run\n\n",
323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       num_groups, num_groups * 2 * num_fds,
324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       thread_mode ? "threads" : "processes");
325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf(" %14s: %lu.%03lu [sec]\n", "Total time",
326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       diff.tv_sec,
327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       (unsigned long) (diff.tv_usec/1000));
328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case BENCH_FORMAT_SIMPLE:
330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf("%lu.%03lu\n", diff.tv_sec,
331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       (unsigned long) (diff.tv_usec/1000));
332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	default:
334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* reaching here is something disaster */
335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fprintf(stderr, "Unknown format:%d\n", bench_format);
336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		exit(1);
337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
342