1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms 5 * of the Common Development and Distribution License 6 * (the "License"). You may not use this file except 7 * in compliance with the License. 8 * 9 * You can obtain a copy of the license at 10 * src/OPENSOLARIS.LICENSE 11 * or http://www.opensolaris.org/os/licensing. 12 * See the License for the specific language governing 13 * permissions and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL 16 * HEADER in each file and include the License file at 17 * usr/src/OPENSOLARIS.LICENSE. If applicable, 18 * add the following below this CDDL HEADER, with the 19 * fields enclosed by brackets "[]" replaced with your 20 * own identifying information: Portions Copyright [yyyy] 21 * [name of copyright owner] 22 * 23 * CDDL HEADER END 24 */ 25 26/* 27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31#define MAX(x, y) ((x) > (y) ? (x) : (y)) 32#define MIN(x, y) ((x) > (y) ? (y) : (x)) 33 34#include <unistd.h> 35#include <stdlib.h> 36#include <stdio.h> 37#include <string.h> 38#include <sys/time.h> 39#include <sys/socket.h> 40 41#include "libmicro.h" 42 43#define DEFN 256 44 45static int optn = DEFN; 46static int optr = 0; 47static int optw = 0; 48static int optx = 0; 49static int *fds; 50static fd_set iset; 51static fd_set oset; 52static int maxfd = 0; 53static int target = 0; 54 55int 56benchmark_init() 57{ 58 (void) sprintf(lm_optstr, "n:r:w:x"); 59 60 lm_tsdsize = 0; 61 62 (void) sprintf(lm_usage, 63 " [-n fds-per-thread (default %d)]\n" 64 " [-r readable-fds (default 0)]\n" 65 " [-w writeable-fds (default 0)]\n" 66 " [-x] (start -r option with highest fd first; " 67 "default is lowest first)\n" 68 "notes: measures select()\n", 69 DEFN); 70 71 (void) sprintf(lm_header, "%8s %5s", "maxfd", "flags"); 72 73 return (0); 74} 75 76int 77benchmark_optswitch(int opt, char *optarg) 78{ 79 switch (opt) { 80 case 'n': 81 optn = atoi(optarg); 82 break; 83 case 'r': 84 optr = atoi(optarg); 85 break; 86 case 'w': 87 optw = atoi(optarg); 88 break; 89 case 'x': 90 optx = 1; 91 break; 92 default: 93 return (-1); 94 } 95 return (0); 96} 97 98int 99benchmark_initrun() 100{ 101 int i; 102 int j; 103 int pair[2]; 104 105 if (optn % 2 != 0) { 106 (void) printf("ERROR: -n value must be even\n"); 107 optn = optr = optw = 0; 108 return (-1); 109 } 110 111 if (optn < 0 || optr < 0 || optw < 0) { 112 (void) printf("ERROR: -n, -r and -w values must be > 0\n"); 113 optn = optr = optw = 0; 114 return (-1); 115 } 116 117 if (optr > optn || optw > optn) { 118 (void) printf("ERROR: -r and -w values must be <= maxfd\n"); 119 optn = optr = optw = 0; 120 return (-1); 121 } 122 123 fds = (int *)malloc(optn * sizeof (int)); 124 if (fds == NULL) { 125 (void) printf("ERROR: malloc() failed\n"); 126 optn = optr = optw = 0; 127 return (-1); 128 } 129 130 (void) setfdlimit(optn + 10); 131 132 target = optr + optw; 133 134 FD_ZERO(&iset); 135 FD_ZERO(&oset); 136 137 for (i = 0; i < optn; i += 2) { 138 if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) == -1) { 139 (void) printf("ERROR: socketpair() failed\n"); 140 return (-1); 141 } 142 143 fds[i] = MIN(pair[0], pair[1]); 144 fds[i+1] = MAX(pair[0], pair[1]); 145 maxfd = fds[i+1] + 1; 146 147 if (maxfd > FD_SETSIZE) { 148 (void) printf("WARNING: FD_SETSIZE is too small!\n"); 149 return (-1); 150 } 151 152 FD_SET(fds[i], &iset); 153 FD_SET(fds[i+1], &iset); 154 } 155 156 for (i = 0; i < optw; i++) { 157 FD_SET(fds[i], &oset); 158 } 159 if (optx) { 160 for (i = 0, j = optn - 1; i < optr; i++, j--) { 161 (void) write(fds[j+1 - (2*(j%2))], "", 1); 162 } 163 } else { 164 for (i = 0; i < optr; i++) { 165 (void) write(fds[i+1 - (2*(i%2))], "", 1); 166 } 167 } 168 169 return (0); 170} 171 172/*ARGSUSED*/ 173int 174benchmark(void *tsd, result_t *res) 175{ 176 int i; 177 fd_set set1; 178 fd_set set2; 179 fd_set *my_iset = &set1; 180 fd_set *my_oset = NULL; 181 struct timeval tv = {0, 0}; 182 183 if (optw) { 184 my_oset = &set2; 185 } 186 187 for (i = 0; i < lm_optB; i++) { 188 (void) memcpy(&set1, &iset, sizeof (fd_set)); 189 (void) memcpy(&set2, &oset, sizeof (fd_set)); 190 191 if (select(maxfd, my_iset, my_oset, NULL, &tv) != target) { 192 res->re_errors++; 193 } 194 } 195 res->re_count = i; 196 197 return (0); 198} 199 200char * 201benchmark_result() 202{ 203 static char result[256]; 204 char flags[4]; 205 206 flags[0] = optr ? 'r' : '-'; 207 flags[1] = optw ? 'w' : '-'; 208 flags[2] = optx ? 'x' : '-'; 209 flags[3] = 0; 210 211 (void) sprintf(result, "%8d %5s", optn, flags); 212 213 return (result); 214} 215