xref: /freebsd/usr.sbin/bhyve/mevent_test.c (revision 366f60834ff8ef709f132fe8976c96a5e2caace9)
1*366f6083SPeter Grehan /*-
2*366f6083SPeter Grehan  * Copyright (c) 2011 NetApp, Inc.
3*366f6083SPeter Grehan  * All rights reserved.
4*366f6083SPeter Grehan  *
5*366f6083SPeter Grehan  * Redistribution and use in source and binary forms, with or without
6*366f6083SPeter Grehan  * modification, are permitted provided that the following conditions
7*366f6083SPeter Grehan  * are met:
8*366f6083SPeter Grehan  * 1. Redistributions of source code must retain the above copyright
9*366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer.
10*366f6083SPeter Grehan  * 2. Redistributions in binary form must reproduce the above copyright
11*366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer in the
12*366f6083SPeter Grehan  *    documentation and/or other materials provided with the distribution.
13*366f6083SPeter Grehan  *
14*366f6083SPeter Grehan  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15*366f6083SPeter Grehan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*366f6083SPeter Grehan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*366f6083SPeter Grehan  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18*366f6083SPeter Grehan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*366f6083SPeter Grehan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*366f6083SPeter Grehan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*366f6083SPeter Grehan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*366f6083SPeter Grehan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*366f6083SPeter Grehan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*366f6083SPeter Grehan  * SUCH DAMAGE.
25*366f6083SPeter Grehan  *
26*366f6083SPeter Grehan  * $FreeBSD$
27*366f6083SPeter Grehan  */
28*366f6083SPeter Grehan 
29*366f6083SPeter Grehan /*
30*366f6083SPeter Grehan  * Test program for the micro event library. Set up a simple TCP echo
31*366f6083SPeter Grehan  * service.
32*366f6083SPeter Grehan  *
33*366f6083SPeter Grehan  *  cc mevent_test.c mevent.c -lpthread
34*366f6083SPeter Grehan  */
35*366f6083SPeter Grehan 
36*366f6083SPeter Grehan #include <sys/types.h>
37*366f6083SPeter Grehan #include <sys/socket.h>
38*366f6083SPeter Grehan #include <netinet/in.h>
39*366f6083SPeter Grehan 
40*366f6083SPeter Grehan #include <stdio.h>
41*366f6083SPeter Grehan #include <stdlib.h>
42*366f6083SPeter Grehan #include <pthread.h>
43*366f6083SPeter Grehan 
44*366f6083SPeter Grehan #include "mevent.h"
45*366f6083SPeter Grehan 
46*366f6083SPeter Grehan #define TEST_PORT	4321
47*366f6083SPeter Grehan 
48*366f6083SPeter Grehan static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;
49*366f6083SPeter Grehan static pthread_cond_t accept_condvar = PTHREAD_COND_INITIALIZER;
50*366f6083SPeter Grehan 
51*366f6083SPeter Grehan #define MEVENT_ECHO
52*366f6083SPeter Grehan 
53*366f6083SPeter Grehan #ifdef MEVENT_ECHO
54*366f6083SPeter Grehan struct esync {
55*366f6083SPeter Grehan 	pthread_mutex_t	e_mt;
56*366f6083SPeter Grehan 	pthread_cond_t	e_cond;
57*366f6083SPeter Grehan };
58*366f6083SPeter Grehan 
59*366f6083SPeter Grehan static void
60*366f6083SPeter Grehan echoer_callback(int fd, enum ev_type type, void *param)
61*366f6083SPeter Grehan {
62*366f6083SPeter Grehan 	struct esync *sync = param;
63*366f6083SPeter Grehan 
64*366f6083SPeter Grehan 	pthread_mutex_lock(&sync->e_mt);
65*366f6083SPeter Grehan 	pthread_cond_signal(&sync->e_cond);
66*366f6083SPeter Grehan 	pthread_mutex_unlock(&sync->e_mt);
67*366f6083SPeter Grehan }
68*366f6083SPeter Grehan 
69*366f6083SPeter Grehan static void *
70*366f6083SPeter Grehan echoer(void *param)
71*366f6083SPeter Grehan {
72*366f6083SPeter Grehan 	struct esync sync;
73*366f6083SPeter Grehan 	struct mevent *mev;
74*366f6083SPeter Grehan 	char buf[128];
75*366f6083SPeter Grehan 	int fd = (int)(uintptr_t) param;
76*366f6083SPeter Grehan 	int len;
77*366f6083SPeter Grehan 
78*366f6083SPeter Grehan 	pthread_mutex_init(&sync.e_mt, NULL);
79*366f6083SPeter Grehan 	pthread_cond_init(&sync.e_cond, NULL);
80*366f6083SPeter Grehan 
81*366f6083SPeter Grehan 	pthread_mutex_lock(&sync.e_mt);
82*366f6083SPeter Grehan 
83*366f6083SPeter Grehan 	mev = mevent_add(fd, EVF_READ, echoer_callback, &sync);
84*366f6083SPeter Grehan 	if (mev == NULL) {
85*366f6083SPeter Grehan 		printf("Could not allocate echoer event\n");
86*366f6083SPeter Grehan 		exit(1);
87*366f6083SPeter Grehan 	}
88*366f6083SPeter Grehan 
89*366f6083SPeter Grehan 	while (!pthread_cond_wait(&sync.e_cond, &sync.e_mt)) {
90*366f6083SPeter Grehan 		len = read(fd, buf, sizeof(buf));
91*366f6083SPeter Grehan 		if (len > 0) {
92*366f6083SPeter Grehan 			write(fd, buf, len);
93*366f6083SPeter Grehan 			write(0, buf, len);
94*366f6083SPeter Grehan 		} else {
95*366f6083SPeter Grehan 			break;
96*366f6083SPeter Grehan 		}
97*366f6083SPeter Grehan 	}
98*366f6083SPeter Grehan 
99*366f6083SPeter Grehan 	mevent_delete_close(mev);
100*366f6083SPeter Grehan 
101*366f6083SPeter Grehan 	pthread_mutex_unlock(&sync.e_mt);
102*366f6083SPeter Grehan 	pthread_mutex_destroy(&sync.e_mt);
103*366f6083SPeter Grehan 	pthread_cond_destroy(&sync.e_cond);
104*366f6083SPeter Grehan }
105*366f6083SPeter Grehan 
106*366f6083SPeter Grehan #else
107*366f6083SPeter Grehan 
108*366f6083SPeter Grehan static void *
109*366f6083SPeter Grehan echoer(void *param)
110*366f6083SPeter Grehan {
111*366f6083SPeter Grehan 	char buf[128];
112*366f6083SPeter Grehan 	int fd = (int)(uintptr_t) param;
113*366f6083SPeter Grehan 	int len;
114*366f6083SPeter Grehan 
115*366f6083SPeter Grehan 	while ((len = read(fd, buf, sizeof(buf))) > 0) {
116*366f6083SPeter Grehan 		write(1, buf, len);
117*366f6083SPeter Grehan 	}
118*366f6083SPeter Grehan }
119*366f6083SPeter Grehan #endif /* MEVENT_ECHO */
120*366f6083SPeter Grehan 
121*366f6083SPeter Grehan static void
122*366f6083SPeter Grehan acceptor_callback(int fd, enum ev_type type, void *param)
123*366f6083SPeter Grehan {
124*366f6083SPeter Grehan 	pthread_mutex_lock(&accept_mutex);
125*366f6083SPeter Grehan 	pthread_cond_signal(&accept_condvar);
126*366f6083SPeter Grehan 	pthread_mutex_unlock(&accept_mutex);
127*366f6083SPeter Grehan }
128*366f6083SPeter Grehan 
129*366f6083SPeter Grehan static void *
130*366f6083SPeter Grehan acceptor(void *param)
131*366f6083SPeter Grehan {
132*366f6083SPeter Grehan 	struct sockaddr_in sin;
133*366f6083SPeter Grehan 	pthread_t tid;
134*366f6083SPeter Grehan 	int news;
135*366f6083SPeter Grehan 	int s;
136*366f6083SPeter Grehan 
137*366f6083SPeter Grehan         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
138*366f6083SPeter Grehan                 perror("socket");
139*366f6083SPeter Grehan                 exit(1);
140*366f6083SPeter Grehan         }
141*366f6083SPeter Grehan 
142*366f6083SPeter Grehan         sin.sin_len = sizeof(sin);
143*366f6083SPeter Grehan         sin.sin_family = AF_INET;
144*366f6083SPeter Grehan         sin.sin_addr.s_addr = htonl(INADDR_ANY);
145*366f6083SPeter Grehan         sin.sin_port = htons(TEST_PORT);
146*366f6083SPeter Grehan 
147*366f6083SPeter Grehan         if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
148*366f6083SPeter Grehan                 perror("bind");
149*366f6083SPeter Grehan                 exit(1);
150*366f6083SPeter Grehan         }
151*366f6083SPeter Grehan 
152*366f6083SPeter Grehan         if (listen(s, 1) < 0) {
153*366f6083SPeter Grehan                 perror("listen");
154*366f6083SPeter Grehan                 exit(1);
155*366f6083SPeter Grehan         }
156*366f6083SPeter Grehan 
157*366f6083SPeter Grehan 	(void) mevent_add(s, EVF_READ, acceptor_callback, NULL);
158*366f6083SPeter Grehan 
159*366f6083SPeter Grehan 	pthread_mutex_lock(&accept_mutex);
160*366f6083SPeter Grehan 
161*366f6083SPeter Grehan 	while (!pthread_cond_wait(&accept_condvar, &accept_mutex)) {
162*366f6083SPeter Grehan 		news = accept(s, NULL, NULL);
163*366f6083SPeter Grehan 		if (news < 0) {
164*366f6083SPeter Grehan 			perror("accept error");
165*366f6083SPeter Grehan 		} else {
166*366f6083SPeter Grehan 			printf("incoming connection, spawning thread\n");
167*366f6083SPeter Grehan 			pthread_create(&tid, NULL, echoer,
168*366f6083SPeter Grehan 				       (void *)(uintptr_t)news);
169*366f6083SPeter Grehan 		}
170*366f6083SPeter Grehan 	}
171*366f6083SPeter Grehan }
172*366f6083SPeter Grehan 
173*366f6083SPeter Grehan main()
174*366f6083SPeter Grehan {
175*366f6083SPeter Grehan 	pthread_t tid;
176*366f6083SPeter Grehan 
177*366f6083SPeter Grehan 	pthread_create(&tid, NULL, acceptor, NULL);
178*366f6083SPeter Grehan 
179*366f6083SPeter Grehan 	mevent_dispatch();
180*366f6083SPeter Grehan }
181