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 45 static int optn = DEFN; 46 static int optr = 0; 47 static int optw = 0; 48 static int optx = 0; 49 static int *fds; 50 static fd_set iset; 51 static fd_set oset; 52 static int maxfd = 0; 53 static int target = 0; 54 55 int 56 benchmark_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 76 int 77 benchmark_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 98 int 99 benchmark_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*/ 173 int 174 benchmark(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 200 char * 201 benchmark_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