Cleanup ACE_HAS_PTHREAD_SIGMASK_PROTOTYPE, all platforms support it so far as I can...
[ACE_TAO.git] / ACE / performance-tests / TTCP / ACE-C++ / wrapper-new-ttcp.cpp
blob863d8643d60091834789e5081efe63ee9134e220
1 /*
2 * T T C P . C
4 * Test TCP connection. Makes a connection on port 5001
5 * and transfers fabricated buffers or data copied from stdin.
7 * Usable on 4.2, 4.3, and 4.1a systems by defining one of
8 * BSD42 BSD43 (BSD41a)
9 * Machines using System V with BSD sockets should define SYSV.
11 * Modified for operation under 4.2BSD, 18 Dec 84
12 * T.C. Slattery, USNA
13 * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
14 * Modified in 1989 at Silicon Graphics, Inc.
15 * catch SIGPIPE to be able to print stats when receiver has died
16 * for tcp, don't look for sentinel during reads to allow small transfers
17 * increased default buffer size to 8K, nbuf to 2K to transfer 16MB
18 * moved default port to 5001, beyond IPPORT_USERRESERVED
19 * make sinkmode default because it is more popular,
20 * -s now means don't sink/source
21 * count number of read/write system calls to see effects of
22 * blocking from full socket buffers
23 * for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt)
24 * buffer alignment options, -A and -O
25 * print stats in a format that's a bit easier to use with grep & awk
26 * for SYSV, mimic BSD routines to use most of the existing timing code
27 * Modified by Steve Miller of the University of Maryland, College Park
28 * -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF)
29 * Modified Sept. 1989 at Silicon Graphics, Inc.
30 * restored -s sense at request of tcs@brl
31 * Modified Oct. 1991 at Silicon Graphics, Inc.
32 * use getopt(3) for option processing, add -f and -T options.
33 * SGI IRIX 3.3 and 4.0 releases don't need #define SYSV.
34 * Modified Aug.1993 at University Paderborn, Germany
35 * some SVR4 changes and time functions changed to itimer() calls
36 * Modified by Douglas C. Schmidt September 28, 1994
37 * added support for testing UNIX domain socket performance
38 * Modified by Tim Harrison May, 1995
39 * added support for ACE wrappers
40 * Distribution Status -
41 * Public Domain. Distribution Unlimited.
44 /* #define BSD43 */
45 /* #define BSD42 */
46 /* #define BSD41a */
47 // #define SYSV /* required on SGI IRIX releases before 3.3 */
49 #include "ace/Log_Msg.h"
50 #include "ace/SOCK_Connector.h"
51 #include "ace/SOCK_Acceptor.h"
53 #include <stdio.h>
54 #include <signal.h>
55 #include <ctype.h>
56 #include <errno.h>
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <netinet/in.h>
60 #include <malloc.h>
61 #include <string.h>
62 #include <stdlib.h>
63 #include <memory.h>
64 #include <netinet/tcp.h>
65 #include <arpa/inet.h>
66 #include <netdb.h>
67 #include <sys/time.h> /* struct itimerval */
68 #include <limits.h>
69 #include <sys/un.h>
70 #include <unistd.h>
72 ACE_SOCK_Connector connector_factory;
73 ACE_SOCK_Acceptor acceptor_factory;
74 ACE_INET_Addr address;
76 #if defined(SYSV)
77 #define bcopy(b1,b2,n) memcpy(b2,b1,n)
78 #define bzero(b1,n) memset(b1,0,n)
79 #include <sys/times.h>
80 #include <sys/param.h>
82 struct rusage
84 struct timeval ru_utime, ru_stime;
86 #define RUSAGE_SELF 0
88 #else
89 #include <sys/resource.h>
90 #endif
92 struct sockaddr_in sinme;
93 struct sockaddr_un sunme;
94 struct sockaddr_in sinhim;
95 struct sockaddr_un sunhim;
96 struct sockaddr_in frominet;
97 struct sockaddr_un fromunix;
99 struct Session_Control_Message
101 long nbuf_;
102 // number of buffers that will be sent this round.
103 long size_;
104 // size of the buffers that will be sent
105 } session_control_buf;
107 struct Data_Control_Message
109 long size_;
110 char data_;
111 } *message_buf;
113 int fromlen;
114 int domain = PF_INET; /* Default is to use Internet domain sockets. */
115 char *domainname; /* Rendezvous address for UNIX domain sockets. */
116 int fd; /* fd of network socket */
118 int data_buf_len = 1024 * 1024 * 2; // length of data portion
119 long total_msg_len; // length of entire message
120 char *data_buf; // pointer to data portion
121 int nbuf = 2 * 1024; /* number of buffers to send in sinkmode */
123 int bufoffset = 0; /* align buffer to this */
124 int bufalign = 16 * 1024; /* modulo this */
126 int udp = 0; /* 0 = tcp, !0 = udp */
127 int options = 0; /* socket options */
128 int one = 1; /* for 4.3 BSD style setsockopt() */
129 short port = 5001; /* TCP port number */
130 char *host; /* ptr to name of host */
131 int trans; /* 0=receive, !0=transmit mode */
132 int sinkmode = 0; /* 0=normal I/O, !0=sink/source mode */
133 int verbose = 0; /* 0=print basic info, 1=print cpu rate, proc
134 * resource usage. */
135 int nodelay = 0; /* set TCP_NODELAY socket option */
136 int b_flag = 0; /* use mread() */
137 int sockbufsize = 0; /* socket buffer size to use */
138 char fmt = 'K'; /* output format: k = kilobits, K = kilobytes,
139 * m = megabits, M = megabytes,
140 * g = gigabits, G = gigabytes */
141 int touchdata = 0; /* access data after reading */
143 struct hostent *addr;
144 extern int errno;
145 extern int optind;
146 extern char *optarg;
148 char Usage[] = "\
149 Usage: ttcp -t [-options] host [ < in ]\n\
150 ttcp -r [-options > out]\n\
151 Common options:\n\
152 -l ## length of bufs read from or written to network (default 8192)\n\
153 -u use UDP instead of TCP\n\
154 -U use UNIX domain sockets instead of Internet domain sockets\n\
155 -p ## port number to send to or listen at (default 5001)\n\
156 -s -t: source a pattern to network\n\
157 -r: sink (discard) all data from network\n\
158 -A align the start of buffers to this modulus (default 16384)\n\
159 -O start buffers at this offset from the modulus (default 0)\n\
160 -v verbose: print more statistics\n\
161 -d set SO_DEBUG socket option\n\
162 -b ## set socket buffer size (if supported)\n\
163 -f X format for rate: k,K = kilo{bit,byte}; m,M = mega; g,G = giga\n\
164 Options specific to -t:\n\
165 -n## number of source bufs written to network (default 2048)\n\
166 -D don't buffer TCP writes (sets TCP_NODELAY socket option)\n\
167 Options specific to -r:\n\
168 -B for -s, only output full blocks as specified by -l (for TAR)\n\
169 -T \"touch\": access each byte as it's read\n\
172 char stats[128];
173 unsigned long nbytes; /* bytes on net */
174 unsigned long numCalls = 0; /* # of I/O system calls */
175 double cput, realt; /* user, real time (seconds) */
177 void err (char *s);
178 void mes (char *s);
179 void pattern (register char *cp, register int cnt);
180 char *outfmt (double b);
181 void prep_timer ();
182 double read_timer (char *str, int len);
183 static void prusage (register struct rusage *r0, struct rusage *r1, struct timeval *e, struct timeval *b, char *outp);
184 static void tvadd (struct timeval *tsum, struct timeval *t0, struct timeval *t1);
185 static void tvsub (struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
186 static void psecs (long l, register char *cp);
187 void delay (int us);
188 int mread (int fd, register char *bufp, unsigned n);
189 int Nread (ACE_SOCK_Stream &s, void *buf, int count);
190 int Nwrite (ACE_SOCK_Stream &s, void *buf, int count);
192 #if !defined (__cplusplus)
193 typedef void (*SIG_TYP)();
194 #else
195 typedef void (*SIG_TYP)(int);
196 #endif
198 #ifdef SVR4
199 void
200 sigpipe (int foo)
201 #else
202 void
203 sigpipe ()
204 #endif
208 void sigpipe(int foo)
210 printf("Caught signal %d\n", foo);
213 char *title = 0;
214 int new_line = 0;
217 ACE_TMAIN(int argc, ACE_TCHAR *argv[])
219 ACE_SOCK_Stream connection_stream;
220 int c;
222 printf("HZ = %d\n", HZ);
223 if (argc < 2)
224 goto usage;
226 while ((c = getopt (argc, argv, "drstU:uvBDTb:f:l:n:p:A:O:L:xh:")) != -1)
228 switch (c)
230 case 'h':
231 host = optarg;
232 break;
233 case 'x':
234 new_line = 1;
235 break;
236 case 'L':
237 title = optarg;
238 break;
239 case 'B':
240 b_flag = 1;
241 break;
242 case 't':
243 trans = 1;
244 break;
245 case 'r':
246 trans = 0;
247 break;
248 case 'd':
249 options |= SO_DEBUG;
250 break;
251 case 'D':
252 #ifdef TCP_NODELAY
253 nodelay = 1;
254 #else
255 fprintf (stderr,
256 "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n");
257 #endif
258 break;
259 case 'n':
260 nbuf = atoi (optarg);
261 break;
262 case 'l':
263 data_buf_len = atoi (optarg);
264 break;
265 case 's':
266 sinkmode = !sinkmode;
267 break;
268 case 'p':
269 port = atoi (optarg);
270 break;
271 case 'U':
272 domain = PF_UNIX;
273 domainname = optarg;
274 break;
275 case 'u':
276 udp = 1;
277 break;
278 case 'v':
279 verbose = 1;
280 break;
281 case 'A':
282 bufalign = atoi (optarg);
283 break;
284 case 'O':
285 bufoffset = atoi (optarg);
286 break;
287 case 'b':
288 #if defined(SO_SNDBUF) || defined(SO_RCVBUF)
289 sockbufsize = atoi (optarg);
290 #else
291 fprintf (stderr,
292 "ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n");
293 #endif
294 break;
295 case 'f':
296 fmt = *optarg;
297 break;
298 case 'T':
299 touchdata = 1;
300 break;
302 default:
303 goto usage;
307 /* if transmitter, create remote address to transmit to. */
309 if (trans)
311 if (address.set (port, host) == -1)
312 perror ("address.set"), exit (1);
315 /* else, receiver create address to listen on */
316 else
318 address.set (port);
321 total_msg_len = sizeof (long) + data_buf_len;
323 // allocate the buffer
324 message_buf = (Data_Control_Message *) malloc (total_msg_len);
325 if (message_buf == 0)
326 err ("malloc");
328 // if (bufalign != 0)
329 // message_buf += (bufalign - ((int) message_buf % bufalign) + bufoffset) % bufalign;
331 // let's go ahead and set the control message for every send right now
332 message_buf->size_ = data_buf_len;
334 session_control_buf.nbuf_ = nbuf;
335 session_control_buf.size_ = data_buf_len;
338 // print out option values for trans and receiver
341 if (trans)
343 fprintf (stdout,
344 "ttcp-t: data_buf_len=%d, nbuf=%d, align=%d/%d, port=%d",
345 data_buf_len, nbuf, bufalign, bufoffset, port);
346 if (sockbufsize)
347 fprintf (stdout, ", sockbufsize=%d", sockbufsize);
348 fprintf (stdout, " %s -> %s\n",
349 domain == PF_INET ? (udp ? "udp" : "tcp") : "unix",
350 host == 0 ? domainname : host);
352 else // receiver
354 fprintf (stdout,
355 "ttcp-r: data_buf_len=%d, nbuf=%d, align=%d/%d, port=%d",
356 data_buf_len, nbuf, bufalign, bufoffset, port);
357 if (sockbufsize)
358 fprintf (stdout, ", sockbufsize=%d", sockbufsize);
359 fprintf (stdout, " %s\n", domain == PF_INET ? (udp ? "udp" : "tcp") : "unix");
362 mes ("socket");
365 // connect and accept
368 if (!udp)
370 signal (SIGPIPE, (SIG_TYP) sigpipe);
372 /* the transmitter will set options and connect to receiver */
373 if (trans)
375 // turn off weird ack things
376 if (nodelay)
378 struct protoent *p = getprotobyname ("tcp");
380 if (p && connection_stream.set_option (p->p_proto,
381 TCP_NODELAY,
382 (char *)& one,
383 sizeof (one)))
384 err ("setsockopt: nodelay");
385 mes ("nodelay");
387 if (connector_factory.connect (connection_stream, address) == -1)
388 perror ("connection failed"), exit (1);
389 fprintf (stdout,
390 "ttcp-t: data_buf_len=%d, nbuf=%d, align=%d/%d, port=%d",
391 data_buf_len, nbuf, bufalign, bufoffset, port);
393 if (sockbufsize)
395 if (connection_stream.set_option (SOL_SOCKET,
396 SO_SNDBUF,
397 (char *) &sockbufsize,
398 sizeof sockbufsize) == -1)
399 err ("acceptor_factory.set_option");
400 mes ("sndbuf");
404 /* receiver will listen for connections from the transmitter */
405 else
407 if (acceptor_factory.open (address, 1) == -1)
408 perror ("acceptor open"), exit (1);
410 if (sockbufsize)
412 if (connection_stream.set_option (SOL_SOCKET,
413 SO_RCVBUF,
414 (char *) &sockbufsize,
415 sizeof sockbufsize) == -1)
416 err ("acceptor_factory.set_option");
417 mes ("rcvbuf");
420 ACE_INET_Addr remote_address;
422 if (acceptor_factory.accept (connection_stream,
423 (ACE_Addr *) &remote_address) == -1)
424 perror ("acceptor accept"), exit (1);
426 // set the window size
428 fprintf (stderr,
429 "ttcp-r: accept from %s\n",
430 remote_address.get_host_name());
435 // start timer
438 errno = 0;
439 if (trans)
441 pattern (& (message_buf->data_), data_buf_len);
442 prep_timer ();
444 ACE_DEBUG ((LM_DEBUG, "Sending session control message"
445 " nbuf %d, size %d\n", session_control_buf.nbuf_,
446 session_control_buf.size_));
447 if (connection_stream.send_n ((char *) &session_control_buf,
448 sizeof (Session_Control_Message))
449 != sizeof (Session_Control_Message))
450 ACE_ERROR_RETURN ((LM_ERROR,
451 "%p send session control failed\n",
452 "ttcp"),
453 -1);
455 long ack;
456 int send_result;
457 while (nbuf--)
459 send_result = connection_stream.send_n ((char *) message_buf,
460 total_msg_len);
461 if (send_result != total_msg_len)
462 ACE_ERROR_RETURN ((LM_ERROR,
463 "%p only sent %d of %d bytes on call %d\n",
464 "ttcp", send_result, total_msg_len, numCalls + 1),
465 -1);
466 numCalls++;
467 nbytes += data_buf_len;
469 if (connection_stream.recv_n ((char *) &ack, sizeof ack) != sizeof ack)
470 ACE_ERROR_RETURN ((LM_ERROR, "%p recv of ack failed\n", "ttcp"), -1);
472 if (ack != data_buf_len)
473 ACE_DEBUG ((LM_DEBUG, "received ack for only %d bytes\n", ack));
475 printf("Client finished.\n");
477 else
479 prep_timer ();
481 if (connection_stream.recv_n ((char *) &session_control_buf,
482 sizeof (Session_Control_Message))
483 != sizeof (Session_Control_Message))
484 ACE_ERROR_RETURN ((LM_ERROR,
485 "%p recv session control failed\n",
486 "ttcp"),
487 -1);
489 ACE_DEBUG ((LM_DEBUG, "received session control message"
490 " nbuf %d, size %d\n", session_control_buf.nbuf_,
491 session_control_buf.size_));
493 nbuf = session_control_buf.nbuf_;
494 // ignore session_control_buf.size_ for now
496 long cnt;
498 while (nbuf--)
500 if (connection_stream.recv_n ((char *) message_buf, sizeof (long))
501 != sizeof (long))
502 ACE_ERROR_RETURN ((LM_ERROR,
503 "%p recv data control failed\n",
504 "ttcp"),
505 -1);
507 cnt = connection_stream.recv_n (& (message_buf->data_), message_buf->size_);
508 if (cnt != message_buf->size_)
509 ACE_ERROR_RETURN ((LM_ERROR, "recv data failed\n"), -1);
511 numCalls++;
512 nbytes += cnt;
514 if (connection_stream.send_n ((char *) &cnt, sizeof cnt)
515 != sizeof cnt)
516 ACE_ERROR_RETURN ((LM_ERROR,
517 "%p send ack failed\n",
518 "ttcp"),
519 -1);
521 printf("Server finished.\n");
524 /* if (errno)
525 err ("IO");
528 // stop the timer
531 (void) read_timer (stats, sizeof (stats));
532 if (udp && trans)
534 (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
535 (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
536 (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
537 (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
539 if (cput <= 0.0)
540 cput = 0.001;
541 if (realt <= 0.0)
542 realt = 0.001;
544 #if defined (LM_RESULTS)
545 if (trans && (title != 0))
547 double tmp;
548 FILE *fd;
549 char filename[BUFSIZ];
550 ACE_OS::sprintf (filename, "%s.results", title);
551 fd = fopen(filename,"a+");
552 if (new_line)
553 fprintf(fd,"\n -l %ldk \t", data_buf_len/1024);
554 tmp = ((double) nbytes) / realt;
555 fprintf(fd,"%.2f ", tmp * 8.0 / 1024.0 / 1024.0);
556 fclose(fd);
558 #endif
560 fprintf (stdout,
561 "ttcp%s: %ld bytes in %.2f real seconds = %s/sec +++\n",
562 trans ? "-t" : "-r",
563 nbytes, realt, outfmt (((double) nbytes) / realt));
564 if (verbose)
566 fprintf (stdout,
567 "ttcp%s: %ld bytes in %.2f CPU seconds = %s/cpu sec\n",
568 trans ? "-t" : "-r",
569 nbytes, cput, outfmt (((double) nbytes) / cput));
571 fprintf (stdout,
572 "ttcp%s: %d I/O calls, msec/call = %.2f, calls/sec = %.2f\n",
573 trans ? "-t" : "-r",
574 numCalls,
575 1024.0 * realt / ((double) numCalls),
576 ((double) numCalls) / realt);
577 fprintf (stdout, "ttcp%s: %s\n", trans ? "-t" : "-r", stats);
578 if (verbose)
580 fprintf (stdout,
581 "ttcp%s: buffer address %#x\n",
582 trans ? "-t" : "-r",
583 message_buf);
585 exit (0);
587 usage:
588 fprintf (stderr, Usage);
589 return 1;
592 void
593 err (char *s)
595 fprintf (stderr, "ttcp%s: ", trans ? "-t" : "-r");
596 perror (s);
597 fprintf (stderr, "errno=%d\n", errno);
598 exit (1);
601 void
602 mes (char *s)
604 fprintf (stderr, "ttcp%s: %s\n", trans ? "-t" : "-r", s);
607 void
608 pattern (register char *cp, register int cnt)
610 register char c;
611 c = 0;
612 while (cnt-- > 0)
614 while (!isprint ((c & 0x7F)))
615 c++;
616 *cp++ = (c++ & 0x7F);
620 char *
621 outfmt (double b)
623 static char obuf[50];
624 switch (fmt)
626 case 'G':
627 sprintf (obuf, "%.2f GB", b / 1024.0 / 1024.0 / 1024.0);
628 break;
629 default:
630 case 'K':
631 sprintf (obuf, "%.2f KB", b / 1024.0);
632 break;
633 case 'M':
634 sprintf (obuf, "%.2f MB", b / 1024.0 / 1024.0);
635 break;
636 case 'g':
637 sprintf (obuf, "%.2f Gbit", b * 8.0 / 1024.0 / 1024.0 / 1024.0);
638 break;
639 case 'k':
640 sprintf (obuf, "%.2f Kbit", b * 8.0 / 1024.0);
641 break;
642 case 'm':
643 sprintf (obuf, "%.2f Mbit", b * 8.0 / 1024.0 / 1024.0);
644 break;
646 return obuf;
649 static struct itimerval itime0; /* Time at which timing started */
650 static struct rusage ru0; /* Resource utilization at the start */
652 #if defined(SYSV)
653 /*ARGSUSED */
654 static void
655 getrusage (int ignored, register struct rusage *ru)
657 struct tms buf;
659 times (&buf);
661 /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */
662 ru->ru_stime.tv_sec = buf.tms_stime / HZ;
663 ru->ru_stime.tv_usec = ((buf.tms_stime % HZ) * 1000000) / HZ;
664 ru->ru_utime.tv_sec = buf.tms_utime / HZ;
665 ru->ru_utime.tv_usec = ((buf.tms_utime % HZ) * 1000000) / HZ;
668 #endif /* SYSV */
670 * P R E P _ T I M E R
672 void
673 prep_timer ()
675 itime0.it_interval.tv_sec = 0;
676 itime0.it_interval.tv_usec = 0;
677 // itime0.it_value.tv_sec = LONG_MAX / 22; /* greatest possible value , itimer() count backwards */
678 itime0.it_value.tv_sec = 3600;
679 itime0.it_value.tv_usec = 0;
682 getrusage (RUSAGE_SELF, &ru0);
683 fprintf(stdout, "\n");
684 fprintf(stdout, "beginning user time = %d sec and %d usec\n", ru0.ru_utime.tv_sec, ru0.ru_utime.tv_usec);
685 fprintf(stdout, "beginning sys time = %d sec and %d usec\n", ru0.ru_stime.tv_sec, ru0.ru_stime.tv_usec);
687 /* Init REAL Timer */
688 if (setitimer (ITIMER_REAL, &itime0, 0))
690 perror ("Setting 'itimer' REAL failed");
691 return;
693 fprintf(stdout, "Beginning transaction time = %d sec and %d usec\n", itime0.it_value.tv_sec, itime0.it_value.tv_usec);
697 * R E A D _ T I M E R
699 double
700 read_timer (char *str, int len)
702 struct itimerval itimedol;
703 struct rusage ru1;
704 struct timeval td;
705 struct timeval tend, tstart;
706 char line[132];
708 getrusage (RUSAGE_SELF, &ru1);
709 fprintf(stdout, "final user time = %d sec and %d usec\n", ru1.ru_utime.tv_sec, ru1.ru_utime.tv_usec);
710 fprintf(stdout, "final sys time = %d sec and %d usec\n", ru1.ru_stime.tv_sec, ru1.ru_stime.tv_usec);
712 if (getitimer (ITIMER_REAL, &itimedol))
714 perror ("Getting 'itimer' REAL failed");
715 return (0.0);
717 fprintf(stdout, "End transaction time = %d sec and %d usec\n", itimedol.it_value.tv_sec, itimedol.it_value.tv_usec);
718 prusage (&ru0, &ru1, &itime0.it_value, &itimedol.it_value, line);
719 (void) strncpy (str, line, len);
721 /* Get real time */
722 tvsub (&td, &itime0.it_value, &itimedol.it_value);
723 realt = td.tv_sec + ((double) td.tv_usec) / 1000000;
725 /* Get CPU time (user+sys) */
726 tvadd (&tend, &ru1.ru_utime, &ru1.ru_stime);
727 tvadd (&tstart, &ru0.ru_utime, &ru0.ru_stime);
728 tvsub (&td, &tend, &tstart);
729 cput = td.tv_sec + ((double) td.tv_usec) / 1000000;
730 if (cput < 0.00001)
731 cput = 0.00001;
732 return (cput);
735 static void
736 prusage (register struct rusage *r0, struct rusage *r1,
737 struct timeval *b, struct timeval *e, char *outp)
739 struct timeval tdiff;
740 register time_t t;
741 register char *cp;
742 register int i;
743 int ms;
745 t = (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 1000 +
746 (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 100000 +
747 (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 1000 +
748 (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 100000;
749 ms = -((e->tv_sec - b->tv_sec) * 1000 + (e->tv_usec - b->tv_usec) / 1000);/* in milliseconds */
751 #define END(x) {while(*x) x++;}
752 #if defined(SYSV)
753 cp = "%Uuser %Ssys %Ereal %P";
754 #else
755 cp = "%Uutime %Sstime %Edtime %P cpu occupancy";
756 /* cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";*/
757 #endif
758 for (; *cp; cp++)
760 if (*cp != '%')
761 *outp++ = *cp;
762 else if (cp[1])
763 switch (*++cp)
765 case 'U':
766 tvsub (&tdiff, &r1->ru_utime, &r0->ru_utime);
767 /* sprintf (outp, "%d.%01d", tdiff.tv_sec, tdiff.tv_usec);*/
768 sprintf (outp, "%f", (tdiff.tv_sec + tdiff.tv_usec/1000000.0));
769 END (outp);
770 break;
772 case 'S':
773 tvsub (&tdiff, &r1->ru_stime, &r0->ru_stime);
774 /* sprintf (outp, "%d.%01d", tdiff.tv_sec, tdiff.tv_usec);*/
775 sprintf (outp, "%f", (tdiff.tv_sec + tdiff.tv_usec/1000000.0));
776 END (outp);
777 break;
779 case 'E':
780 psecs (ms / 1000, outp);
781 END (outp);
782 break;
784 case 'P':
785 sprintf (outp, "%f%%", (t * 100.0 / ((ms ? ms : 1))));
786 END (outp);
787 break;
789 #if !defined(SYSV)
790 case 'W':
791 i = r1->ru_nswap - r0->ru_nswap;
792 sprintf (outp, "%d", i);
793 END (outp);
794 break;
796 case 'X':
797 sprintf (outp, "%d", t == 0 ? 0 : (r1->ru_ixrss - r0->ru_ixrss) / t);
798 END (outp);
799 break;
801 case 'D':
802 sprintf (outp, "%d", t == 0 ? 0 :
803 (r1->ru_idrss + r1->ru_isrss - (r0->ru_idrss + r0->ru_isrss)) / t);
804 END (outp);
805 break;
807 case 'K':
808 sprintf (outp, "%d", t == 0 ? 0 :
809 ((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
810 (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
811 END (outp);
812 break;
814 case 'M':
815 sprintf (outp, "%d", r1->ru_maxrss / 2);
816 END (outp);
817 break;
819 case 'F':
820 sprintf (outp, "%d", r1->ru_majflt - r0->ru_majflt);
821 END (outp);
822 break;
824 case 'R':
825 sprintf (outp, "%d", r1->ru_minflt - r0->ru_minflt);
826 END (outp);
827 break;
829 case 'I':
830 sprintf (outp, "%d", r1->ru_inblock - r0->ru_inblock);
831 END (outp);
832 break;
834 case 'O':
835 sprintf (outp, "%d", r1->ru_oublock - r0->ru_oublock);
836 END (outp);
837 break;
839 case 'C':
840 sprintf (outp, "%d+%d", r1->ru_nvcsw - r0->ru_nvcsw,
841 r1->ru_nivcsw - r0->ru_nivcsw);
842 END (outp);
843 break;
844 #endif /* !SYSV */
847 *outp = '\0';
850 static void
851 tvadd (struct timeval *tsum, struct timeval *t0, struct timeval *t1)
853 tsum->tv_sec = t0->tv_sec + t1->tv_sec;
854 tsum->tv_usec = t0->tv_usec + t1->tv_usec;
855 if (tsum->tv_usec > 1000000)
856 tsum->tv_sec++, tsum->tv_usec -= 1000000;
859 static void
860 tvsub (struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
862 tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
863 tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
864 if (tdiff->tv_usec < 0)
865 tdiff->tv_sec--, tdiff->tv_usec += 1000000;
868 static void
869 psecs (long l, register char *cp)
871 register int i;
873 i = l / 3600;
874 if (i)
876 sprintf (cp, "%d hours", i);
877 END (cp);
878 i = l % 3600;
879 sprintf (cp, "%d minutes ", (i / 60));
880 sprintf (cp, "%d seconds ", (i % 60));
881 END (cp);
883 else
885 i = l;
886 sprintf (cp, "%d minutes ", i / 60);
887 END (cp);
889 i %= 60;
890 *cp++ = ':';
891 sprintf (cp, "%d seconds ", i);
895 * N R E A D
898 Nread (ACE_SOCK_Stream &s, void *buf, int count)
900 numCalls++;
901 return (s.recv (buf, count));
905 * N W R I T E
908 Nwrite (ACE_SOCK_Stream &s, void *buf, int count)
910 numCalls++;
911 return s.send (buf, count);
914 void
915 delay (int us)
917 struct timeval tv;
919 tv.tv_sec = 0;
920 tv.tv_usec = us;
921 (void) select (1, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &tv);
925 * M R E A D
927 * This function performs the function of a read(II) but will
928 * call read(II) multiple times in order to get the requested
929 * number of characters. This can be necessary because
930 * network connections don't deliver data with the same
931 * grouping as it is written with. Written by Robert S. Miles, BRL.
934 mread (int fd, register char *bufp, unsigned n)
936 register unsigned count = 0;
937 register int nread;
941 nread = read (fd, bufp, n - count);
942 numCalls++;
943 if (nread < 0)
945 perror ("ttcp_mread");
946 return (-1);
948 if (nread == 0)
949 return ((int) count);
950 count += (unsigned) nread;
951 bufp += nread;
953 while (count < n);
955 return ((int) count);