1*63cd6ed3Sbluhm /* $OpenBSD: unsendrecvthr.c,v 1.2 2023/07/09 09:33:30 bluhm Exp $ */
24890ac77Smvs
34890ac77Smvs /*
44890ac77Smvs * Copyright (c) 2021 Vitaliy Makkoveev <mvs@openbsd.org>
54890ac77Smvs *
64890ac77Smvs * Permission to use, copy, modify, and distribute this software for any
74890ac77Smvs * purpose with or without fee is hereby granted, provided that the above
84890ac77Smvs * copyright notice and this permission notice appear in all copies.
94890ac77Smvs *
104890ac77Smvs * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
114890ac77Smvs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
124890ac77Smvs * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
134890ac77Smvs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
144890ac77Smvs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
154890ac77Smvs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
164890ac77Smvs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
174890ac77Smvs */
184890ac77Smvs
194890ac77Smvs /*
204890ac77Smvs * Create the pair of SOCK_SEQPACKET sockets and perform #count_of_cpus
214890ac77Smvs * simultaneous writes on each of them. In half of transmissions the
224890ac77Smvs * sockets will be re-locked in kernel space. Be sure no data corruption
234890ac77Smvs * or loss.
244890ac77Smvs */
254890ac77Smvs
264890ac77Smvs #include <sys/types.h>
274890ac77Smvs #include <sys/select.h>
284890ac77Smvs #include <sys/socket.h>
294890ac77Smvs #include <sys/sysctl.h>
304890ac77Smvs #include <sys/un.h>
314890ac77Smvs #include <stdarg.h>
324890ac77Smvs #include <stdio.h>
334890ac77Smvs #include <stdlib.h>
344890ac77Smvs #include <err.h>
354890ac77Smvs #include <pthread.h>
364890ac77Smvs #include <string.h>
374890ac77Smvs #include <time.h>
384890ac77Smvs #include <unistd.h>
394890ac77Smvs
404890ac77Smvs static pthread_mutex_t therr_mtx = PTHREAD_MUTEX_INITIALIZER;
414890ac77Smvs
424890ac77Smvs static void
therr(int eval,const char * fmt,...)434890ac77Smvs therr(int eval, const char *fmt, ...)
444890ac77Smvs {
454890ac77Smvs va_list ap;
464890ac77Smvs
474890ac77Smvs pthread_mutex_lock(&therr_mtx);
484890ac77Smvs
494890ac77Smvs va_start(ap, fmt);
504890ac77Smvs verr(eval, fmt, ap);
514890ac77Smvs va_end(ap);
524890ac77Smvs }
534890ac77Smvs
544890ac77Smvs static void
therrx(int eval,const char * fmt,...)554890ac77Smvs therrx(int eval, const char *fmt, ...)
564890ac77Smvs {
574890ac77Smvs va_list ap;
584890ac77Smvs
594890ac77Smvs pthread_mutex_lock(&therr_mtx);
604890ac77Smvs
614890ac77Smvs va_start(ap, fmt);
624890ac77Smvs verrx(eval, fmt, ap);
634890ac77Smvs va_end(ap);
644890ac77Smvs }
654890ac77Smvs
664890ac77Smvs static void
therrc(int eval,int code,const char * fmt,...)674890ac77Smvs therrc(int eval, int code, const char *fmt, ...)
684890ac77Smvs {
694890ac77Smvs va_list ap;
704890ac77Smvs
714890ac77Smvs pthread_mutex_lock(&therr_mtx);
724890ac77Smvs
734890ac77Smvs va_start(ap, fmt);
744890ac77Smvs verrc(eval, code, fmt, ap);
754890ac77Smvs va_end(ap);
764890ac77Smvs }
774890ac77Smvs
784890ac77Smvs struct data {
794890ac77Smvs int id;
804890ac77Smvs unsigned int cnt;
814890ac77Smvs };
824890ac77Smvs
834890ac77Smvs struct thr_tx_arg {
844890ac77Smvs int s;
854890ac77Smvs int id;
864890ac77Smvs };
874890ac77Smvs
884890ac77Smvs struct rx_data {
894890ac77Smvs unsigned int cnt;
904890ac77Smvs };
914890ac77Smvs
924890ac77Smvs struct thr_rx_arg {
934890ac77Smvs int s;
944890ac77Smvs int rx_data_num;
954890ac77Smvs struct rx_data *rx_data;
964890ac77Smvs };
974890ac77Smvs
984890ac77Smvs static void *
thr_tx(void * arg)994890ac77Smvs thr_tx(void *arg)
1004890ac77Smvs {
1014890ac77Smvs struct data data;
1024890ac77Smvs int s = ((struct thr_tx_arg *)arg)->s;
1034890ac77Smvs
1044890ac77Smvs data.id = ((struct thr_tx_arg *)arg)->id;
1054890ac77Smvs data.cnt = 1;
1064890ac77Smvs
1074890ac77Smvs while (1) {
1084890ac77Smvs ssize_t ret;
1094890ac77Smvs
1104890ac77Smvs if ((ret = send(s, &data, sizeof(data), 0)) < 0)
1114890ac77Smvs therr(1, "send");
1124890ac77Smvs if (ret != sizeof(data))
1134890ac77Smvs therrx(1, "send: wrong data size");
1144890ac77Smvs
1154890ac77Smvs data.cnt++;
1164890ac77Smvs }
1174890ac77Smvs
1184890ac77Smvs return NULL;
1194890ac77Smvs }
1204890ac77Smvs
1214890ac77Smvs static void *
thr_rx(void * arg)1224890ac77Smvs thr_rx(void *arg)
1234890ac77Smvs {
1244890ac77Smvs int s = ((struct thr_rx_arg *)arg)->s;
1254890ac77Smvs int rx_data_num = ((struct thr_rx_arg *)arg)->rx_data_num;
1264890ac77Smvs struct rx_data *rx_data = ((struct thr_rx_arg *)arg)->rx_data;
1274890ac77Smvs
1284890ac77Smvs while (1) {
1294890ac77Smvs struct data data;
1304890ac77Smvs ssize_t ret;
1314890ac77Smvs
1324890ac77Smvs if ((ret = recv(s, &data, sizeof(data), 0)) < 0)
1334890ac77Smvs therr(1, "recv");
1344890ac77Smvs if (ret != sizeof(data))
1354890ac77Smvs therrx(1, "recv: wrong data size");
1364890ac77Smvs
1374890ac77Smvs if (data.id >= rx_data_num)
1384890ac77Smvs therrx(1, "recv: wrong id");
1394890ac77Smvs
1404890ac77Smvs if (data.cnt != (unsigned int)(rx_data[data.id].cnt + 1)) {
1414890ac77Smvs therrx(1, "recv: data loss %d -> %d",
1424890ac77Smvs rx_data[data.id].cnt, data.cnt);
1434890ac77Smvs }
1444890ac77Smvs rx_data[data.id].cnt = data.cnt;
1454890ac77Smvs }
1464890ac77Smvs
1474890ac77Smvs return NULL;
1484890ac77Smvs }
1494890ac77Smvs
1504890ac77Smvs int
main(int argc,char * argv[])1514890ac77Smvs main(int argc, char *argv[])
1524890ac77Smvs {
1534890ac77Smvs struct timespec testtime = {
1544890ac77Smvs .tv_sec = 60,
1554890ac77Smvs .tv_nsec = 0,
1564890ac77Smvs };
1574890ac77Smvs
1584890ac77Smvs int mib[2], ncpu;
1594890ac77Smvs size_t len;
1604890ac77Smvs
1614890ac77Smvs struct rx_data *rx_data[2];
1624890ac77Smvs struct thr_rx_arg rx_args[2];
1634890ac77Smvs struct thr_tx_arg *tx_args[2];
1644890ac77Smvs
1654890ac77Smvs int s[2], i, j;
1664890ac77Smvs
1674890ac77Smvs if (argc == 2 && !strcmp(argv[1], "--infinite"))
1684890ac77Smvs testtime.tv_sec = (10 * 365 * 86400);
1694890ac77Smvs
1704890ac77Smvs mib[0] = CTL_HW;
1714890ac77Smvs mib[1] = HW_NCPUONLINE;
1724890ac77Smvs len = sizeof(ncpu);
1734890ac77Smvs
1744890ac77Smvs if (sysctl(mib, 2, &ncpu, &len, NULL, 0) < 0)
1754890ac77Smvs err(1, "sysctl");
1764890ac77Smvs if (ncpu <= 0)
1774890ac77Smvs errx(1, "Wrong number of CPUs online: %d", ncpu);
1784890ac77Smvs
1794890ac77Smvs if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, s) < 0)
1804890ac77Smvs err(1, "socketpair");
1814890ac77Smvs
1824890ac77Smvs for (i = 0; i < 2; ++i) {
183*63cd6ed3Sbluhm if (!(rx_data[i] = calloc(ncpu, sizeof(struct rx_data))))
1844890ac77Smvs err(1, "calloc");
1854890ac77Smvs
1864890ac77Smvs for (j = 0; j < ncpu; ++j)
1874890ac77Smvs rx_data[i][j].cnt = 0;
1884890ac77Smvs }
1894890ac77Smvs
1904890ac77Smvs for (i = 0; i < 2; ++i) {
1914890ac77Smvs rx_args[i].s = s[i];
1924890ac77Smvs rx_args[i].rx_data_num = ncpu;
1934890ac77Smvs rx_args[i].rx_data = rx_data[i];
1944890ac77Smvs }
1954890ac77Smvs
1964890ac77Smvs for (i = 0; i < 2; ++i) {
197*63cd6ed3Sbluhm if (!(tx_args[i] = calloc(ncpu, sizeof(struct thr_tx_arg))))
1984890ac77Smvs err(1, "calloc");
1994890ac77Smvs
2004890ac77Smvs for (j = 0; j < ncpu; ++j) {
2014890ac77Smvs tx_args[i][j].s = s[i];
2024890ac77Smvs tx_args[i][j].id = j;
2034890ac77Smvs }
2044890ac77Smvs }
2054890ac77Smvs
2064890ac77Smvs for (i = 0; i < 2; ++i) {
2074890ac77Smvs pthread_t thr;
2084890ac77Smvs int error;
2094890ac77Smvs
2104890ac77Smvs error = pthread_create(&thr, NULL, thr_rx, &rx_args[i]);
2114890ac77Smvs if (error)
2124890ac77Smvs therrc(1, error, "pthread_create");
2134890ac77Smvs }
2144890ac77Smvs
2154890ac77Smvs for (i = 0; i < 2; ++i) {
2164890ac77Smvs pthread_t thr;
2174890ac77Smvs int error;
2184890ac77Smvs
2194890ac77Smvs for (j = 0; j < ncpu; ++j) {
2204890ac77Smvs error = pthread_create(&thr, NULL,
2214890ac77Smvs thr_tx, &tx_args[i][j]);
2224890ac77Smvs if (error)
2234890ac77Smvs therrc(1, error, "pthread_create");
2244890ac77Smvs }
2254890ac77Smvs }
2264890ac77Smvs
2274890ac77Smvs nanosleep(&testtime, NULL);
2284890ac77Smvs
2294890ac77Smvs return 0;
2304890ac77Smvs }
231