14c87aefeSPatrick Mooney /*- 24c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 34c87aefeSPatrick Mooney * 44c87aefeSPatrick Mooney * Copyright (c) 2011 NetApp, Inc. 54c87aefeSPatrick Mooney * All rights reserved. 64c87aefeSPatrick Mooney * 74c87aefeSPatrick Mooney * Redistribution and use in source and binary forms, with or without 84c87aefeSPatrick Mooney * modification, are permitted provided that the following conditions 94c87aefeSPatrick Mooney * are met: 104c87aefeSPatrick Mooney * 1. Redistributions of source code must retain the above copyright 114c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer. 124c87aefeSPatrick Mooney * 2. Redistributions in binary form must reproduce the above copyright 134c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer in the 144c87aefeSPatrick Mooney * documentation and/or other materials provided with the distribution. 154c87aefeSPatrick Mooney * 164c87aefeSPatrick Mooney * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 174c87aefeSPatrick Mooney * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 184c87aefeSPatrick Mooney * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 194c87aefeSPatrick Mooney * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 204c87aefeSPatrick Mooney * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 214c87aefeSPatrick Mooney * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 224c87aefeSPatrick Mooney * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 234c87aefeSPatrick Mooney * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 244c87aefeSPatrick Mooney * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 254c87aefeSPatrick Mooney * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 264c87aefeSPatrick Mooney * SUCH DAMAGE. 274c87aefeSPatrick Mooney * 284c87aefeSPatrick Mooney * $FreeBSD$ 294c87aefeSPatrick Mooney */ 304c87aefeSPatrick Mooney 314c87aefeSPatrick Mooney /* 324c87aefeSPatrick Mooney * Copyright 2018 Joyent, Inc. 334c87aefeSPatrick Mooney */ 344c87aefeSPatrick Mooney 354c87aefeSPatrick Mooney /* 364c87aefeSPatrick Mooney * Test program for the micro event library. Set up a simple TCP echo 374c87aefeSPatrick Mooney * service. 384c87aefeSPatrick Mooney * 394c87aefeSPatrick Mooney * cc mevent_test.c mevent.c -lpthread 404c87aefeSPatrick Mooney */ 414c87aefeSPatrick Mooney 424c87aefeSPatrick Mooney #include <sys/types.h> 434c87aefeSPatrick Mooney #include <sys/stdint.h> 444c87aefeSPatrick Mooney #ifdef __FreeBSD__ 454c87aefeSPatrick Mooney #include <sys/sysctl.h> 464c87aefeSPatrick Mooney #endif 474c87aefeSPatrick Mooney #include <sys/socket.h> 484c87aefeSPatrick Mooney #include <netinet/in.h> 494c87aefeSPatrick Mooney #ifdef __FreeBSD__ 504c87aefeSPatrick Mooney #include <machine/cpufunc.h> 514c87aefeSPatrick Mooney #endif 524c87aefeSPatrick Mooney 534c87aefeSPatrick Mooney #include <stdio.h> 544c87aefeSPatrick Mooney #include <stdlib.h> 554c87aefeSPatrick Mooney #include <pthread.h> 564c87aefeSPatrick Mooney #include <unistd.h> 574c87aefeSPatrick Mooney 584c87aefeSPatrick Mooney #include "mevent.h" 594c87aefeSPatrick Mooney 604c87aefeSPatrick Mooney #define TEST_PORT 4321 614c87aefeSPatrick Mooney 624c87aefeSPatrick Mooney static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; 634c87aefeSPatrick Mooney static pthread_cond_t accept_condvar = PTHREAD_COND_INITIALIZER; 644c87aefeSPatrick Mooney 654c87aefeSPatrick Mooney static struct mevent *tevp; 664c87aefeSPatrick Mooney 674c87aefeSPatrick Mooney 684c87aefeSPatrick Mooney #define MEVENT_ECHO 694c87aefeSPatrick Mooney 704c87aefeSPatrick Mooney /* Number of timer events to capture */ 714c87aefeSPatrick Mooney #define TEVSZ 4096 724c87aefeSPatrick Mooney uint64_t tevbuf[TEVSZ]; 734c87aefeSPatrick Mooney 744c87aefeSPatrick Mooney static void 754c87aefeSPatrick Mooney timer_print(void) 764c87aefeSPatrick Mooney { 774c87aefeSPatrick Mooney uint64_t min, max, diff, sum; 784c87aefeSPatrick Mooney #ifdef __FreeBSD__ 794c87aefeSPatrick Mooney uint64_t tsc_freq; 804c87aefeSPatrick Mooney size_t len; 814c87aefeSPatrick Mooney #endif 824c87aefeSPatrick Mooney int j; 834c87aefeSPatrick Mooney 844c87aefeSPatrick Mooney min = UINT64_MAX; 854c87aefeSPatrick Mooney max = 0; 864c87aefeSPatrick Mooney sum = 0; 874c87aefeSPatrick Mooney 884c87aefeSPatrick Mooney #ifdef __FreeBSD__ 894c87aefeSPatrick Mooney len = sizeof(tsc_freq); 904c87aefeSPatrick Mooney sysctlbyname("machdep.tsc_freq", &tsc_freq, &len, NULL, 0); 914c87aefeSPatrick Mooney #endif 924c87aefeSPatrick Mooney 934c87aefeSPatrick Mooney for (j = 1; j < TEVSZ; j++) { 944c87aefeSPatrick Mooney #ifdef __FreeBSD__ 954c87aefeSPatrick Mooney /* Convert a tsc diff into microseconds */ 964c87aefeSPatrick Mooney diff = (tevbuf[j] - tevbuf[j-1]) * 1000000 / tsc_freq; 974c87aefeSPatrick Mooney #else 984c87aefeSPatrick Mooney diff = (tevbuf[j] - tevbuf[j-1]) / 1000; 994c87aefeSPatrick Mooney #endif 1004c87aefeSPatrick Mooney sum += diff; 1014c87aefeSPatrick Mooney if (min > diff) 1024c87aefeSPatrick Mooney min = diff; 1034c87aefeSPatrick Mooney if (max < diff) 1044c87aefeSPatrick Mooney max = diff; 1054c87aefeSPatrick Mooney } 1064c87aefeSPatrick Mooney 1074c87aefeSPatrick Mooney printf("timers done: usecs, min %ld, max %ld, mean %ld\n", min, max, 1084c87aefeSPatrick Mooney sum/(TEVSZ - 1)); 1094c87aefeSPatrick Mooney } 1104c87aefeSPatrick Mooney 1114c87aefeSPatrick Mooney static void 1124c87aefeSPatrick Mooney timer_callback(int fd, enum ev_type type, void *param) 1134c87aefeSPatrick Mooney { 1144c87aefeSPatrick Mooney static int i; 1154c87aefeSPatrick Mooney 1164c87aefeSPatrick Mooney if (i >= TEVSZ) 1174c87aefeSPatrick Mooney abort(); 1184c87aefeSPatrick Mooney 1194c87aefeSPatrick Mooney #ifdef __FreeBSD__ 1204c87aefeSPatrick Mooney tevbuf[i++] = rdtsc(); 1214c87aefeSPatrick Mooney #else 1224c87aefeSPatrick Mooney tevbuf[i++] = gethrtime(); 1234c87aefeSPatrick Mooney #endif 1244c87aefeSPatrick Mooney 1254c87aefeSPatrick Mooney if (i == TEVSZ) { 1264c87aefeSPatrick Mooney mevent_delete(tevp); 1274c87aefeSPatrick Mooney timer_print(); 1284c87aefeSPatrick Mooney } 1294c87aefeSPatrick Mooney } 1304c87aefeSPatrick Mooney 1314c87aefeSPatrick Mooney 1324c87aefeSPatrick Mooney #ifdef MEVENT_ECHO 1334c87aefeSPatrick Mooney struct esync { 1344c87aefeSPatrick Mooney pthread_mutex_t e_mt; 135*6dc98349SAndy Fiddaman pthread_cond_t e_cond; 1364c87aefeSPatrick Mooney }; 1374c87aefeSPatrick Mooney 1384c87aefeSPatrick Mooney static void 1394c87aefeSPatrick Mooney echoer_callback(int fd, enum ev_type type, void *param) 1404c87aefeSPatrick Mooney { 1414c87aefeSPatrick Mooney struct esync *sync = param; 1424c87aefeSPatrick Mooney 1434c87aefeSPatrick Mooney pthread_mutex_lock(&sync->e_mt); 1444c87aefeSPatrick Mooney pthread_cond_signal(&sync->e_cond); 1454c87aefeSPatrick Mooney pthread_mutex_unlock(&sync->e_mt); 1464c87aefeSPatrick Mooney } 1474c87aefeSPatrick Mooney 1484c87aefeSPatrick Mooney static void * 1494c87aefeSPatrick Mooney echoer(void *param) 1504c87aefeSPatrick Mooney { 1514c87aefeSPatrick Mooney struct esync sync; 1524c87aefeSPatrick Mooney struct mevent *mev; 1534c87aefeSPatrick Mooney char buf[128]; 1544c87aefeSPatrick Mooney int fd = (int)(uintptr_t) param; 1554c87aefeSPatrick Mooney int len; 1564c87aefeSPatrick Mooney 1574c87aefeSPatrick Mooney pthread_mutex_init(&sync.e_mt, NULL); 1584c87aefeSPatrick Mooney pthread_cond_init(&sync.e_cond, NULL); 1594c87aefeSPatrick Mooney 1604c87aefeSPatrick Mooney pthread_mutex_lock(&sync.e_mt); 1614c87aefeSPatrick Mooney 1624c87aefeSPatrick Mooney mev = mevent_add(fd, EVF_READ, echoer_callback, &sync); 1634c87aefeSPatrick Mooney if (mev == NULL) { 1644c87aefeSPatrick Mooney printf("Could not allocate echoer event\n"); 1654c87aefeSPatrick Mooney exit(4); 1664c87aefeSPatrick Mooney } 1674c87aefeSPatrick Mooney 1684c87aefeSPatrick Mooney while (!pthread_cond_wait(&sync.e_cond, &sync.e_mt)) { 1694c87aefeSPatrick Mooney len = read(fd, buf, sizeof(buf)); 1704c87aefeSPatrick Mooney if (len > 0) { 1714c87aefeSPatrick Mooney write(fd, buf, len); 1724c87aefeSPatrick Mooney write(0, buf, len); 1734c87aefeSPatrick Mooney } else { 1744c87aefeSPatrick Mooney break; 1754c87aefeSPatrick Mooney } 1764c87aefeSPatrick Mooney } 1774c87aefeSPatrick Mooney 1784c87aefeSPatrick Mooney mevent_delete_close(mev); 1794c87aefeSPatrick Mooney 1804c87aefeSPatrick Mooney pthread_mutex_unlock(&sync.e_mt); 1814c87aefeSPatrick Mooney pthread_mutex_destroy(&sync.e_mt); 1824c87aefeSPatrick Mooney pthread_cond_destroy(&sync.e_cond); 1834c87aefeSPatrick Mooney 1844c87aefeSPatrick Mooney return (NULL); 1854c87aefeSPatrick Mooney } 1864c87aefeSPatrick Mooney 1874c87aefeSPatrick Mooney #else 1884c87aefeSPatrick Mooney 1894c87aefeSPatrick Mooney static void * 1904c87aefeSPatrick Mooney echoer(void *param) 1914c87aefeSPatrick Mooney { 1924c87aefeSPatrick Mooney char buf[128]; 1934c87aefeSPatrick Mooney int fd = (int)(uintptr_t) param; 1944c87aefeSPatrick Mooney int len; 1954c87aefeSPatrick Mooney 1964c87aefeSPatrick Mooney while ((len = read(fd, buf, sizeof(buf))) > 0) { 1974c87aefeSPatrick Mooney write(1, buf, len); 1984c87aefeSPatrick Mooney } 1994c87aefeSPatrick Mooney 2004c87aefeSPatrick Mooney return (NULL); 2014c87aefeSPatrick Mooney } 2024c87aefeSPatrick Mooney #endif /* MEVENT_ECHO */ 2034c87aefeSPatrick Mooney 2044c87aefeSPatrick Mooney static void 2054c87aefeSPatrick Mooney acceptor_callback(int fd, enum ev_type type, void *param) 2064c87aefeSPatrick Mooney { 2074c87aefeSPatrick Mooney pthread_mutex_lock(&accept_mutex); 2084c87aefeSPatrick Mooney pthread_cond_signal(&accept_condvar); 2094c87aefeSPatrick Mooney pthread_mutex_unlock(&accept_mutex); 2104c87aefeSPatrick Mooney } 2114c87aefeSPatrick Mooney 2124c87aefeSPatrick Mooney static void * 2134c87aefeSPatrick Mooney acceptor(void *param) 2144c87aefeSPatrick Mooney { 2154c87aefeSPatrick Mooney struct sockaddr_in sin; 2164c87aefeSPatrick Mooney pthread_t tid; 2174c87aefeSPatrick Mooney int news; 2184c87aefeSPatrick Mooney int s; 2194c87aefeSPatrick Mooney 2204c87aefeSPatrick Mooney if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 2214c87aefeSPatrick Mooney perror("cannot create socket"); 2224c87aefeSPatrick Mooney exit(4); 2234c87aefeSPatrick Mooney } 2244c87aefeSPatrick Mooney 2254c87aefeSPatrick Mooney #ifdef __FreeBSD__ 2264c87aefeSPatrick Mooney sin.sin_len = sizeof(sin); 2274c87aefeSPatrick Mooney #endif 2284c87aefeSPatrick Mooney sin.sin_family = AF_INET; 2294c87aefeSPatrick Mooney sin.sin_addr.s_addr = htonl(INADDR_ANY); 2304c87aefeSPatrick Mooney sin.sin_port = htons(TEST_PORT); 2314c87aefeSPatrick Mooney 2324c87aefeSPatrick Mooney if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 2334c87aefeSPatrick Mooney perror("cannot bind socket"); 2344c87aefeSPatrick Mooney exit(4); 2354c87aefeSPatrick Mooney } 2364c87aefeSPatrick Mooney 2374c87aefeSPatrick Mooney if (listen(s, 1) < 0) { 2384c87aefeSPatrick Mooney perror("cannot listen socket"); 2394c87aefeSPatrick Mooney exit(4); 2404c87aefeSPatrick Mooney } 2414c87aefeSPatrick Mooney 2424c87aefeSPatrick Mooney (void) mevent_add(s, EVF_READ, acceptor_callback, NULL); 2434c87aefeSPatrick Mooney 2444c87aefeSPatrick Mooney pthread_mutex_lock(&accept_mutex); 2454c87aefeSPatrick Mooney 2464c87aefeSPatrick Mooney while (!pthread_cond_wait(&accept_condvar, &accept_mutex)) { 2474c87aefeSPatrick Mooney news = accept(s, NULL, NULL); 2484c87aefeSPatrick Mooney if (news < 0) { 2494c87aefeSPatrick Mooney perror("accept error"); 2504c87aefeSPatrick Mooney } else { 2514c87aefeSPatrick Mooney static int first = 1; 2524c87aefeSPatrick Mooney 2534c87aefeSPatrick Mooney if (first) { 2544c87aefeSPatrick Mooney /* 2554c87aefeSPatrick Mooney * Start a timer 2564c87aefeSPatrick Mooney */ 2574c87aefeSPatrick Mooney first = 0; 2584c87aefeSPatrick Mooney tevp = mevent_add(1, EVF_TIMER, timer_callback, 2594c87aefeSPatrick Mooney NULL); 2604c87aefeSPatrick Mooney } 2614c87aefeSPatrick Mooney 2624c87aefeSPatrick Mooney printf("incoming connection, spawning thread\n"); 2634c87aefeSPatrick Mooney pthread_create(&tid, NULL, echoer, 2644c87aefeSPatrick Mooney (void *)(uintptr_t)news); 2654c87aefeSPatrick Mooney } 2664c87aefeSPatrick Mooney } 2674c87aefeSPatrick Mooney 2684c87aefeSPatrick Mooney return (NULL); 2694c87aefeSPatrick Mooney } 2704c87aefeSPatrick Mooney 2714c87aefeSPatrick Mooney int 2724c87aefeSPatrick Mooney main() 2734c87aefeSPatrick Mooney { 2744c87aefeSPatrick Mooney pthread_t tid; 2754c87aefeSPatrick Mooney 2764c87aefeSPatrick Mooney pthread_create(&tid, NULL, acceptor, NULL); 2774c87aefeSPatrick Mooney 2784c87aefeSPatrick Mooney mevent_dispatch(); 2794c87aefeSPatrick Mooney return (0); 2804c87aefeSPatrick Mooney } 281