xref: /openbsd-src/regress/sys/kern/unixsockets/unconacc.c (revision eb897bf188ac5e11052fcbd6bf96a67fa26da039)
1*eb897bf1Smvs /* $OpenBSD: unconacc.c,v 1.1 2021/12/10 00:50:18 mvs Exp $ */
2*eb897bf1Smvs 
3*eb897bf1Smvs /*
4*eb897bf1Smvs  * Copyright (c) 2021 Vitaliy Makkoveev <mvs@openbsd.org>
5*eb897bf1Smvs  *
6*eb897bf1Smvs  * Permission to use, copy, modify, and distribute this software for any
7*eb897bf1Smvs  * purpose with or without fee is hereby granted, provided that the above
8*eb897bf1Smvs  * copyright notice and this permission notice appear in all copies.
9*eb897bf1Smvs  *
10*eb897bf1Smvs  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*eb897bf1Smvs  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*eb897bf1Smvs  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*eb897bf1Smvs  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*eb897bf1Smvs  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*eb897bf1Smvs  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*eb897bf1Smvs  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*eb897bf1Smvs  */
18*eb897bf1Smvs 
19*eb897bf1Smvs /*
20*eb897bf1Smvs  * Provide multithreaded connect(2) and accept(2) stress test on
21*eb897bf1Smvs  * unix(4) socket.
22*eb897bf1Smvs  */
23*eb897bf1Smvs 
24*eb897bf1Smvs #include <sys/types.h>
25*eb897bf1Smvs #include <sys/select.h>
26*eb897bf1Smvs #include <sys/socket.h>
27*eb897bf1Smvs #include <sys/stat.h>
28*eb897bf1Smvs #include <sys/sysctl.h>
29*eb897bf1Smvs #include <sys/un.h>
30*eb897bf1Smvs #include <stdarg.h>
31*eb897bf1Smvs #include <stdio.h>
32*eb897bf1Smvs #include <err.h>
33*eb897bf1Smvs #include <errno.h>
34*eb897bf1Smvs #include <pthread.h>
35*eb897bf1Smvs #include <string.h>
36*eb897bf1Smvs #include <time.h>
37*eb897bf1Smvs #include <unistd.h>
38*eb897bf1Smvs 
39*eb897bf1Smvs static pthread_mutex_t therr_mtx = PTHREAD_MUTEX_INITIALIZER;
40*eb897bf1Smvs 
41*eb897bf1Smvs static void
therr(int eval,const char * fmt,...)42*eb897bf1Smvs therr(int eval, const char *fmt, ...)
43*eb897bf1Smvs {
44*eb897bf1Smvs 	va_list ap;
45*eb897bf1Smvs 
46*eb897bf1Smvs 	pthread_mutex_lock(&therr_mtx);
47*eb897bf1Smvs 
48*eb897bf1Smvs 	va_start(ap, fmt);
49*eb897bf1Smvs 	verr(eval, fmt, ap);
50*eb897bf1Smvs 	va_end(ap);
51*eb897bf1Smvs }
52*eb897bf1Smvs 
53*eb897bf1Smvs static void
therrc(int eval,int code,const char * fmt,...)54*eb897bf1Smvs therrc(int eval, int code, const char *fmt, ...)
55*eb897bf1Smvs {
56*eb897bf1Smvs 	va_list ap;
57*eb897bf1Smvs 
58*eb897bf1Smvs 	pthread_mutex_lock(&therr_mtx);
59*eb897bf1Smvs 
60*eb897bf1Smvs 	va_start(ap, fmt);
61*eb897bf1Smvs 	verrc(eval, code, fmt, ap);
62*eb897bf1Smvs 	va_end(ap);
63*eb897bf1Smvs }
64*eb897bf1Smvs 
65*eb897bf1Smvs static void *
thr_acc(void * arg)66*eb897bf1Smvs thr_acc(void *arg)
67*eb897bf1Smvs {
68*eb897bf1Smvs 	int s = *(int *)arg;
69*eb897bf1Smvs 
70*eb897bf1Smvs 	while (1) {
71*eb897bf1Smvs 		int n;
72*eb897bf1Smvs 
73*eb897bf1Smvs 		if ((n = accept(s, NULL, NULL)) < 0) {
74*eb897bf1Smvs 			switch (errno) {
75*eb897bf1Smvs 			case EMFILE:
76*eb897bf1Smvs 			case ENFILE:
77*eb897bf1Smvs 				continue;
78*eb897bf1Smvs 			default:
79*eb897bf1Smvs 				therr(1, "accept");
80*eb897bf1Smvs 			}
81*eb897bf1Smvs 		}
82*eb897bf1Smvs 
83*eb897bf1Smvs 		close(n);
84*eb897bf1Smvs 	}
85*eb897bf1Smvs 
86*eb897bf1Smvs 	return NULL;
87*eb897bf1Smvs }
88*eb897bf1Smvs 
89*eb897bf1Smvs static void *
thr_conn(void * arg)90*eb897bf1Smvs thr_conn(void *arg)
91*eb897bf1Smvs {
92*eb897bf1Smvs 	struct sockaddr_un *sun = arg;
93*eb897bf1Smvs 	int s;
94*eb897bf1Smvs 
95*eb897bf1Smvs 	while (1) {
96*eb897bf1Smvs 		if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
97*eb897bf1Smvs 			switch (errno) {
98*eb897bf1Smvs 			case EMFILE:
99*eb897bf1Smvs 			case ENFILE:
100*eb897bf1Smvs 			case ENOBUFS:
101*eb897bf1Smvs 				continue;
102*eb897bf1Smvs 			default:
103*eb897bf1Smvs 				therr(1, "socket");
104*eb897bf1Smvs 			}
105*eb897bf1Smvs 		}
106*eb897bf1Smvs 
107*eb897bf1Smvs 		if (connect(s, (struct sockaddr *)sun, sizeof(*sun)) < 0) {
108*eb897bf1Smvs 			switch (errno) {
109*eb897bf1Smvs 			case ECONNREFUSED:
110*eb897bf1Smvs 				continue;
111*eb897bf1Smvs 			default:
112*eb897bf1Smvs 				therr(1, "connect");
113*eb897bf1Smvs 			}
114*eb897bf1Smvs 		}
115*eb897bf1Smvs 
116*eb897bf1Smvs 		close(s);
117*eb897bf1Smvs 	}
118*eb897bf1Smvs 
119*eb897bf1Smvs 	return NULL;
120*eb897bf1Smvs }
121*eb897bf1Smvs 
122*eb897bf1Smvs static struct sockaddr_un sun;
123*eb897bf1Smvs 
124*eb897bf1Smvs int
main(int argc,char * argv[])125*eb897bf1Smvs main(int argc, char *argv[])
126*eb897bf1Smvs {
127*eb897bf1Smvs 	struct timespec testtime = {
128*eb897bf1Smvs 		.tv_sec = 60,
129*eb897bf1Smvs 		.tv_nsec = 0,
130*eb897bf1Smvs 	};
131*eb897bf1Smvs 
132*eb897bf1Smvs 	int s;
133*eb897bf1Smvs 
134*eb897bf1Smvs 	int mib[2], ncpu;
135*eb897bf1Smvs 	size_t len;
136*eb897bf1Smvs 
137*eb897bf1Smvs 	int i;
138*eb897bf1Smvs 
139*eb897bf1Smvs 	umask(0077);
140*eb897bf1Smvs 
141*eb897bf1Smvs 	if (argc == 2 && !strcmp(argv[1], "--infinite"))
142*eb897bf1Smvs 		testtime.tv_sec = (10 * 365 * 86400);
143*eb897bf1Smvs 
144*eb897bf1Smvs 	mib[0] = CTL_HW;
145*eb897bf1Smvs 	mib[1] = HW_NCPUONLINE;
146*eb897bf1Smvs 	len = sizeof(ncpu);
147*eb897bf1Smvs 
148*eb897bf1Smvs 	if (sysctl(mib, 2, &ncpu, &len, NULL, 0) < 0)
149*eb897bf1Smvs 		err(1, "sysctl");
150*eb897bf1Smvs 	if (ncpu <= 0)
151*eb897bf1Smvs 		errx(1, "Wrong number of CPUs online: %d", ncpu);
152*eb897bf1Smvs 
153*eb897bf1Smvs 	memset(&sun, 0, sizeof(sun));
154*eb897bf1Smvs 	sun.sun_len = sizeof(sun);
155*eb897bf1Smvs 	sun.sun_family = AF_UNIX;
156*eb897bf1Smvs 	snprintf(sun.sun_path, sizeof(sun.sun_path) - 1, "unconacc.socket");
157*eb897bf1Smvs 
158*eb897bf1Smvs 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
159*eb897bf1Smvs 		err(1, "socket");
160*eb897bf1Smvs 
161*eb897bf1Smvs 	unlink(sun.sun_path);
162*eb897bf1Smvs 
163*eb897bf1Smvs 	if (bind(s, (struct sockaddr *)&sun, sizeof(sun)) < 0)
164*eb897bf1Smvs 		err(1, "bind");
165*eb897bf1Smvs 	if (listen(s, 10) < 0)
166*eb897bf1Smvs 		err(1, "listen");
167*eb897bf1Smvs 
168*eb897bf1Smvs 	for (i = 0; i < (ncpu * 2); ++i) {
169*eb897bf1Smvs 		pthread_t thr;
170*eb897bf1Smvs 		int error;
171*eb897bf1Smvs 
172*eb897bf1Smvs 		if ((error = pthread_create(&thr, NULL, thr_acc, &s)))
173*eb897bf1Smvs 			therrc(1, error, "pthread_create");
174*eb897bf1Smvs 	}
175*eb897bf1Smvs 
176*eb897bf1Smvs 	for (i = 0; i < (ncpu * 2); ++i) {
177*eb897bf1Smvs 		pthread_t thr;
178*eb897bf1Smvs 		int error;
179*eb897bf1Smvs 
180*eb897bf1Smvs 		if ((error = pthread_create(&thr, NULL, thr_conn, &sun)))
181*eb897bf1Smvs 			therrc(1, error, "pthread_create");
182*eb897bf1Smvs 	}
183*eb897bf1Smvs 
184*eb897bf1Smvs 	nanosleep(&testtime, NULL);
185*eb897bf1Smvs 
186*eb897bf1Smvs 	return 0;
187*eb897bf1Smvs }
188