1/* 2 * Copyright (c) 2006 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 30/* 31 * Order of Execution 32 * 33 * benchmark_init 34 * 35 * benchmark_optswitch 36 * 37 * benchmark_initrun 38 * 39 * benchmark_initworker 40 * benchmark_initbatch 41 * benchmark 42 * benchmark_finibatch 43 * benchmark_initbatch 44 * benchmark 45 * benchmark_finibatch, etc. 46 * benchmark_finiworker 47 * 48 * benchmark_result 49 * 50 * benchmark_finirun 51 * 52 * benchmark_fini 53 */ 54 55 56 57#ifdef __sun 58#pragma ident "@(#)socket.c 1.3 05/08/04 Apple Inc." 59#endif 60 61 62 63#include <unistd.h> 64#include <stdlib.h> 65#include <stdio.h> 66#include <fcntl.h> 67#include <string.h> 68#include <errno.h> 69 70#include "../libmicro.h" 71 72/* 73 * lmbench routines, etc. brought over for this benchmark 74 */ 75int open_file(void* tsd); 76void server(void* tsd); 77 78 79typedef int (*open_f)(void* tsd); 80/* 81 * end of lmbench support routines 82 */ 83 84/* 85 * Your state variables should live in the tsd_t struct below 86 */ 87typedef struct { 88 char fname[L_tmpnam]; 89 open_f fid_f; 90 pid_t pid; 91 int sock; 92 int fid; 93 int num; 94 int max; 95 fd_set set; 96} tsd_t; 97 98static int optt = 1; 99static int optn = -1; 100static int optp = 1; 101static int optw = 0; 102 103/* 104 * lmbench routines, etc. brought over for this benchmark 105 */ 106 107void 108morefds(void) 109{ 110#ifdef RLIMIT_NOFILE 111 struct rlimit r; 112 113 getrlimit(RLIMIT_NOFILE, &r); 114 r.rlim_cur = r.rlim_max; 115 setrlimit(RLIMIT_NOFILE, &r); 116#endif 117} 118 119int 120open_file(void* tsd) 121{ 122 tsd_t* ts = (tsd_t*)tsd; 123 //(void) fprintf(stderr, "open_file: ts->fname = %s\n",ts->fname); 124 return (int) open(ts->fname, O_RDONLY); 125} 126 127void 128server(void* tsd) 129{ 130 int pid; 131 tsd_t* ts = (tsd_t*)tsd; 132 133 pid = getpid(); 134 ts->pid = 0; 135 //(void) fprintf(stderr, "server: state->fid_f = %i\n",ts->fid_f); 136 137 if (ts->fid_f == open_file) { 138 /* Create a temporary file for clients to open */ 139 sprintf(ts->fname, "/tmp/lat_selectXXXXXX"); 140 //(void) fprintf(stderr, "server: ts->fname = %s\n",ts->fname); 141 ts->fid = mkstemp(ts->fname); 142 //(void) fprintf(stderr, "server: ts->fname = %s: ts->fid = %d\n",ts->fname, ts->fid); 143 144 if (ts->fid <= 0) { 145 char buf[L_tmpnam+128]; 146 sprintf(buf, "lat_select: Could not create temp file %s", ts->fname); 147 perror(buf); 148 exit(1); 149 } 150 close(ts->fid); 151 return; 152 } 153// 154// this is all for the tcp version of this test only 155// 156// /* Create a socket for clients to connect to */ 157// state->sock = tcp_server(TCP_SELECT, SOCKOPT_REUSE); 158// if (state->sock <= 0) { 159// perror("lat_select: Could not open tcp server socket"); 160// exit(1); 161// } 162 163 /* Start a server process to accept client connections */ 164// switch(state->pid = fork()) { 165// case 0: 166// /* child server process */ 167// while (pid == getppid()) { 168// int newsock = tcp_accept(state->sock, SOCKOPT_NONE); 169// read(newsock, &state->fid, 1); 170// close(newsock); 171// } 172// exit(0); 173// case -1: 174// /* error */ 175// perror("lat_select::server(): fork() failed"); 176// exit(1); 177// default: 178// break; 179// } 180} 181 182 183/* 184 * end of lmbench support routines 185 */ 186 187/*ARGSUSED*/ 188int 189benchmark_initbatch(void *tsd) 190{ 191 /* 192 * initialize your state variables here second 193 */ 194 return (0); 195} 196 197int 198benchmark_finirun() 199{ 200 //(void) fprintf(stderr, "benchmark_finirun\n"); 201 return (0); 202} 203 204int 205benchmark_init() 206{ 207 //(void) fprintf(stderr, "benchmark_init\n"); 208 /* 209 * the lm_optstr must be defined here or no options for you 210 * 211 * ...and the framework will throw an error 212 * 213 */ 214 (void) sprintf(lm_optstr, "p:w:n:t:"); 215 /* 216 * working hypothesis: 217 * 218 * tsd_t is the struct that we can pass around our 219 * state info in 220 * 221 * lm_tsdsize will allocate the space we need for this 222 * structure throughout the rest of the framework 223 */ 224 lm_tsdsize = sizeof (tsd_t); 225 226 (void) sprintf(lm_usage, 227 " [-p parallelism (default 1)]\n" 228 " [-w warmup (default 0)]\n" 229 " [-n number of descriptors (default 1)]\n" 230 " [-t int (default 1)]\n" 231 "notes: measures lmbench_select_file\n"); 232 lm_defB = 1; 233 return (0); 234} 235 236int 237benchmark_fini() 238{ 239 //(void) fprintf(stderr, "benchmark_fini\n"); 240 return (0); 241} 242 243int 244benchmark_finibatch(void *tsd) 245{ 246 return (0); 247} 248 249char * 250benchmark_result() 251{ 252 static char result = '\0'; 253 //(void) fprintf(stderr, "benchmark_result\n"); 254 return (&result); 255} 256 257int 258benchmark_finiworker(void *tsd) 259{ 260 tsd_t *ts = (tsd_t *)tsd; 261 int i; 262 // pulls in the lmbench cleanup code 263 //(void) fprintf(stderr, "benchmark_finiworker\n"); 264 for (i = 0; i <= ts->max; ++i) { 265 if (FD_ISSET(i, &(ts->set))) 266 close(i); 267 } 268 FD_ZERO(&(ts->set)); 269 unlink(ts->fname); 270 return (0); 271} 272 273int 274benchmark_optswitch(int opt, char *optarg) 275{ 276 //(void) fprintf(stderr, "benchmark_optswitch\n"); 277 278 switch (opt) { 279 case 't': 280 optt = sizetoint(optarg); 281 break; 282 case 'n': 283 optn = sizetoint(optarg); 284 break; 285 case 'p': 286 optp = sizetoint(optarg); 287 break; 288 case 'w': 289 optw = sizetoint(optarg); 290 break; 291 default: 292 return (-1); 293 } 294 return (0); 295} 296 297int 298benchmark_initworker(void *tsd) 299{ 300 // pulls in code from lmbench main and initialize 301 int n = 0; 302 /* 303 * initialize your state variables here first 304 */ 305 tsd_t *ts = (tsd_t *)tsd; 306 int N, fid, fd; 307 308 /* 309 * default number of file descriptors 310 */ 311 //(void) fprintf(stderr, "benchmark_initworker\n"); 312 ts->num = 200; 313 if (optn > 0) { 314 ts->num = optn; 315 } 316 N = ts->num; 317 //(void) fprintf(stderr, "benchmark_initworker ts->num is %i\n",ts->num); 318 319 /* 320 * grab more file descriptors 321 */ 322 323 morefds(); 324 325 ts->fid_f = open_file; 326 server(ts); 327 //(void) fprintf(stderr, "benchmark_initworker: returned from server call\n"); 328 /* 329 * Initialize function from lmbench 330 * for this test 331 */ 332 fid = (*ts->fid_f)(ts); 333 //(void) fprintf(stderr, "initworker: fid is %i\n",fid); 334 if (fid <= 0) { 335 perror("Could not open device"); 336 exit(1); 337 } 338 ts->max = 0; 339 FD_ZERO(&(ts->set)); 340 //(void) fprintf(stderr, "initworker FD_ZERO: ts->set result is %i\n",ts->set); 341 //(void) fprintf(stderr, "initworker: N is %i\n",N); 342 for (n = 0; n < N; n++) { 343 //(void) fprintf(stderr, "benchmark_initworker: in the loop - N is %i: n is %i\n",N, n); 344 fd = dup(fid); 345 //(void) fprintf(stderr, "benchmark_initworker: dup result is %i\n",fd); 346 //(void) fprintf(stderr, "benchmark_initworker: errno result is %d - \"%s\"\n",errno, strerror(errno)); 347 348 if (fd == -1) break; 349 if (fd > ts->max) 350 ts->max = fd; 351 FD_SET(fd, &(ts->set)); 352 //(void) fprintf(stderr, "initworker FD_SET: ts->set result is %i\n",ts->set); 353 354 } 355 //(void) fprintf(stderr, "benchmark_initworker: after second macro/loop\n"); 356 357 ts->max++; 358 close(fid); 359 //(void) fprintf(stderr, "benchmark_initworker: N is %i: n is %i\n",N, n); 360 if (n != N) 361 exit(1); 362 /* end of initialize function */ 363 //(void) fprintf(stderr, "benchmark_initworker: about to exit\n"); 364 return (0); 365} 366 367int 368benchmark_initrun() 369{ 370 //(void) fprintf(stderr, "benchmark_initrun\n"); 371 return (0); 372} 373 374int 375benchmark(void *tsd, result_t *res) 376{ 377 /* 378 * initialize your state variables here last 379 * 380 * and realize that you are paying for your initialization here 381 * and it is really a bad idea 382 */ 383 tsd_t *ts = (tsd_t *)tsd; 384 fd_set nosave; 385 static struct timeval tv; 386 387 //(void) fprintf(stderr, "benchmark\n"); 388 389 int i; 390 //int sel_res; 391 tv.tv_sec = 0; 392 tv.tv_usec = 0; 393 394 395 for (i = 0; i < lm_optB; i++) { 396 nosave = ts->set; 397 //(void) fprintf(stderr, "benchmark: nosave is %i\n", nosave); 398 399 select(ts->num, 0, &nosave, 0, &tv); 400 //(void) fprintf(stderr, "benchmark: select result is %i\n",sel_res); 401 //(void) fprintf(stderr, "benchmark: errno result is %d - \"%s\"\n",errno, strerror(errno)); 402 403 404 } 405 res->re_count = i; 406 return (0); 407} 408 409