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