]>
git.saurik.com Git - apple/xnu.git/blob - tools/tests/libMicro/apple/lmbench_select_tcp.c
aea77dae101690a2663016db191fbd6cc0464b97
2 * Copyright (c) 2006 Apple Inc. All Rights Reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
39 * benchmark_initworker
45 * benchmark_finibatch, etc.
46 * benchmark_finiworker
58 #pragma ident "@(#)socket.c 1.3 05/08/04 Apple Inc."
70 #include <netinet/in.h>
73 #include <sys/errno.h>
74 #include <sys/fcntl.h>
77 #include <rpc/pmap_clnt.h>
79 #include "../libmicro.h"
82 * lmbench routines, etc. brought over for this benchmark
84 int open_file(void* tsd
);
85 void server(void* tsd
);
86 int tcp_accept(int sock
, int rdwr
);
87 void sock_optimize(int sock
, int flags
);
89 int tcp_server(int prog
, int rdwr
);
90 int tcp_connect(char *host
, int prog
, int rdwr
);
91 int open_socket(void *tsd
);
94 typedef int (*open_f
)(void* tsd
);
96 * end of lmbench support routines
100 * Your state variables should live in the tsd_t struct below
103 char fname
[L_tmpnam
];
114 static int optn
= -1;
119 * lmbench routines, etc. brought over for this benchmark
128 getrlimit(RLIMIT_NOFILE
, &r
);
129 r
.rlim_cur
= r
.rlim_max
;
130 setrlimit(RLIMIT_NOFILE
, &r
);
137 tsd_t
* ts
= (tsd_t
*)tsd
;
138 return (int) open(ts
->fname
, O_RDONLY
);
142 open_socket(void* tsd
)
144 return tcp_connect("localhost", TCP_SELECT
, SOCKOPT_NONE
);
151 tsd_t
*ts
= (tsd_t
*)tsd
;
156 if (ts
->fid_f
== open_file
) {
157 /* Create a temporary file for clients to open */
158 sprintf(ts
->fname
, "lat_selectXXXXXX");
159 ts
->fid
= mkstemp(ts
->fname
);
161 char buf
[L_tmpnam
+128];
162 sprintf(buf
, "lat_select: Could not create temp file %s", ts
->fname
);
170 /* Create a socket for clients to connect to */
171 ts
->sock
= tcp_server(TCP_SELECT
, SOCKOPT_REUSE
);
173 perror("lat_select: Could not open tcp server socket");
177 /* Start a server process to accept client connections */
178 switch(ts
->pid
= fork()) {
180 /* child server process */
181 while (pid
== getppid()) {
182 int newsock
= tcp_accept(ts
->sock
, SOCKOPT_NONE
);
183 read(newsock
, &ts
->fid
, 1);
189 perror("lat_select::server(): fork() failed");
198 * Accept a connection and return it
201 tcp_accept(int sock
, int rdwr
)
203 struct sockaddr_in s
;
208 bzero((void*)&s
, namelen
);
211 if ((newsock
= accept(sock
, (struct sockaddr
*)&s
, &namelen
)) < 0) {
217 #ifdef LIBTCP_VERBOSE
218 fprintf(stderr
, "Server newsock port %d\n", sockport(newsock
));
220 sock_optimize(newsock
, rdwr
);
225 sock_optimize(int sock
, int flags
)
227 if (flags
& SOCKOPT_READ
) {
228 int sockbuf
= SOCKBUF
;
230 while (setsockopt(sock
, SOL_SOCKET
, SO_RCVBUF
, &sockbuf
,
234 #ifdef LIBTCP_VERBOSE
235 fprintf(stderr
, "sockopt %d: RCV: %dK\n", sock
, sockbuf
>>10);
238 if (flags
& SOCKOPT_WRITE
) {
239 int sockbuf
= SOCKBUF
;
241 while (setsockopt(sock
, SOL_SOCKET
, SO_SNDBUF
, &sockbuf
,
245 #ifdef LIBTCP_VERBOSE
246 fprintf(stderr
, "sockopt %d: SND: %dK\n", sock
, sockbuf
>>10);
249 if (flags
& SOCKOPT_REUSE
) {
251 if (setsockopt(sock
, SOL_SOCKET
,
252 SO_REUSEADDR
, &val
, sizeof(val
)) == -1) {
253 perror("SO_REUSEADDR");
262 struct sockaddr_in sin
;
264 namelen
= sizeof(sin
);
265 if (getsockname(s
, (struct sockaddr
*)&sin
, &namelen
) < 0) {
266 perror("getsockname");
269 return ((int)ntohs(sin
.sin_port
));
273 * Get a TCP socket, bind it, figure out the port,
274 * and advertise the port as program "prog".
276 * XXX - it would be nice if you could advertise ascii strings.
279 tcp_server(int prog
, int rdwr
)
282 struct sockaddr_in s
;
284 #ifdef LIBTCP_VERBOSE
285 fprintf(stderr
, "tcp_server(%u, %u)\n", prog
, rdwr
);
287 if ((sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0) {
291 sock_optimize(sock
, rdwr
);
292 bzero((void*)&s
, sizeof(s
));
293 s
.sin_family
= AF_INET
;
295 s
.sin_port
= htons(-prog
);
297 if (bind(sock
, (struct sockaddr
*)&s
, sizeof(s
)) < 0) {
301 if (listen(sock
, 100) < 0) {
306 #ifdef LIBTCP_VERBOSE
307 fprintf(stderr
, "Server port %d\n", sockport(sock
));
309 (void)pmap_unset((u_long
)prog
, (u_long
)1);
310 if (!pmap_set((u_long
)prog
, (u_long
)1, (u_long
)IPPROTO_TCP
,
311 (unsigned short)sockport(sock
))) {
321 * Connect to the TCP socket advertised as "prog" on "host" and
322 * return the connected socket.
324 * Hacked Thu Oct 27 1994 to cache pmap_getport calls. This saves
325 * about 4000 usecs in loopback lat_connect calls. I suppose we
326 * should time gethostbyname() & pmap_getprot(), huh?
329 tcp_connect(char *host
, int prog
, int rdwr
)
331 static struct hostent
*h
;
332 static struct sockaddr_in s
;
333 static u_short save_port
;
334 static u_long save_prog
;
335 static char *save_host
;
337 static int tries
= 0;
339 if ((sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0) {
343 if (rdwr
& SOCKOPT_PID
) {
344 static unsigned short port
;
345 struct sockaddr_in sin
;
348 port
= (unsigned short)(getpid() << 4);
355 bzero((void*)&sin
, sizeof(sin
));
356 sin
.sin_family
= AF_INET
;
357 sin
.sin_port
= htons(port
);
358 } while (bind(sock
, (struct sockaddr
*)&sin
, sizeof(sin
)) == -1);
360 #ifdef LIBTCP_VERBOSE
362 struct sockaddr_in sin
;
364 bzero((void*)&sin
, sizeof(sin
));
365 sin
.sin_family
= AF_INET
;
366 if (bind(sock
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0) {
371 fprintf(stderr
, "Client port %d\n", sockport(sock
));
373 sock_optimize(sock
, rdwr
);
374 if (!h
|| host
!= save_host
|| prog
!= save_prog
) {
375 save_host
= host
; /* XXX - counting on them not
376 * changing it - benchmark only.
379 if (!(h
= gethostbyname(host
))) {
383 bzero((void *) &s
, sizeof(s
));
384 s
.sin_family
= AF_INET
;
385 bcopy((void*)h
->h_addr
, (void *)&s
.sin_addr
, h
->h_length
);
387 save_port
= pmap_getport(&s
, prog
,
388 (u_long
)1, IPPROTO_TCP
);
390 perror("lib TCP: No port found");
393 #ifdef LIBTCP_VERBOSE
394 fprintf(stderr
, "Server port %d\n", save_port
);
396 s
.sin_port
= htons(save_port
);
398 s
.sin_port
= htons(-prog
);
401 if (connect(sock
, (struct sockaddr
*)&s
, sizeof(s
)) < 0) {
402 if (errno
== ECONNRESET
403 || errno
== ECONNREFUSED
404 || errno
== EAGAIN
) {
406 if (++tries
> 10) return(-1);
407 return (tcp_connect(host
, prog
, rdwr
));
418 * end of lmbench support routines
423 benchmark_initbatch(void *tsd
)
426 * initialize your state variables here second
441 * the lm_optstr must be defined here or no options for you
443 * ...and the framework will throw an error
446 (void) sprintf(lm_optstr
, "p:w:n:t:");
448 * working hypothesis:
450 * tsd_t is the struct that we can pass around our
453 * lm_tsdsize will allocate the space we need for this
454 * structure throughout the rest of the framework
456 lm_tsdsize
= sizeof (tsd_t
);
458 (void) sprintf(lm_usage
,
459 " [-p parallelism (default 1)]\n"
460 " [-w warmup (default 0)]\n"
461 " [-n number of descriptors (default 1)]\n"
462 " [-t int (default 1)]\n"
463 "notes: measures lmbench_select_file\n");
475 benchmark_finibatch(void *tsd
)
483 static char result
= '\0';
488 benchmark_finiworker(void *tsd
)
490 tsd_t
*ts
= (tsd_t
*)tsd
;
492 // pulls in the lmbench cleanup code
493 for (i
= 0; i
<= ts
->max
; ++i
) {
494 if (FD_ISSET(i
, &(ts
->set
)))
503 benchmark_optswitch(int opt
, char *optarg
)
508 optt
= sizetoint(optarg
);
511 optn
= sizetoint(optarg
);
514 optp
= sizetoint(optarg
);
517 optw
= sizetoint(optarg
);
526 benchmark_initworker(void *tsd
)
528 // pulls in code from lmbench main and initialize
531 * initialize your state variables here first
533 tsd_t
*ts
= (tsd_t
*)tsd
;
537 * default number of file descriptors
546 * grab more file descriptors
551 ts
->fid_f
= open_socket
;
554 * Initialize function from lmbench
557 fid
= (*ts
->fid_f
)(ts
);
559 perror("Could not open device");
564 for (n
= 0; n
< N
; n
++) {
566 //(void) fprintf(stderr, "benchmark_initworker: errno result is %d - \"%s\"\n",errno, strerror(errno));
571 FD_SET(fd
, &(ts
->set
));
572 //(void) fprintf(stderr, "initworker FD_SET: ts->set result is %i\n",ts->set);
575 //(void) fprintf(stderr, "benchmark_initworker: after second macro/loop\n");
581 /* end of initialize function */
592 benchmark(void *tsd
, result_t
*res
)
595 * initialize your state variables here last
597 * and realize that you are paying for your initialization here
598 * and it is really a bad idea
600 tsd_t
*ts
= (tsd_t
*)tsd
;
602 static struct timeval tv
;
604 //(void) fprintf(stderr, "benchmark\n");
612 for (i
= 0; i
< lm_optB
; i
++) {
614 //(void) fprintf(stderr, "benchmark: nosave is %i\n", nosave);
616 select(ts
->num
, 0, &nosave
, 0, &tv
);