[PATCH v1 1/4] rtemsbsd: Added original TTCP code
Gedare Bloom
gedare at rtems.org
Tue Jun 8 17:09:34 UTC 2021
Minor note, please use the the --subject-prefix="PATCH rtems-libbsd"
as mentioned in
https://docs.rtems.org/branches/master/eng/vc-users.html#creating-a-patch
This helps set the context of the patch review better for non-rtems.git patches.
On Tue, Jun 8, 2021 at 9:50 AM Stephen Clark <stephen.clark at oarcorp.com> wrote:
>
> Added the original Test TCP (TTCP) program in unmodified form.
> Also added the associated README.
> ---
> rtemsbsd/ttcp/README | 27 ++
> rtemsbsd/ttcp/ttcp.c | 841 +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 868 insertions(+)
> create mode 100644 rtemsbsd/ttcp/README
> create mode 100644 rtemsbsd/ttcp/ttcp.c
>
> diff --git a/rtemsbsd/ttcp/README b/rtemsbsd/ttcp/README
> new file mode 100644
> index 00000000..215ddacc
> --- /dev/null
> +++ b/rtemsbsd/ttcp/README
> @@ -0,0 +1,27 @@
> +TTCP is a benchmarking tool for determining TCP and UDP performance
> +between 2 systems.
> +
> +The program was created at the US Army Ballistics Research Lab (BRL)
> +and is in the public domain. Feel free to distribute this program
> +but please do leave the credit notices in the source and man page intact.
> +
> +Contents of this directory:
> +
> +ttcp.c Source that runs on IRIX 3.3.x and 4.0.x systems
> + and BSD-based systems. This version also uses getopt(3)
> + and has 2 new options: -f and -T.
> +
> +ttcp.c-brl Original source from BRL.
> +
> +ttcp.1 Manual page (describes ttcp.c options, which are a
> + superset of the other version).
> +
> +
> +How to get TCP performance numbers:
> +
> + receiver sender
> +
> +host1% ttcp -r -s host2% ttcp -t -s host1
> +
> +-n and -l options change the number and size of the buffers.
> +
Does this code come from somewhere that should be documented in the README?
> diff --git a/rtemsbsd/ttcp/ttcp.c b/rtemsbsd/ttcp/ttcp.c
> new file mode 100644
> index 00000000..305a7c7d
> --- /dev/null
> +++ b/rtemsbsd/ttcp/ttcp.c
> @@ -0,0 +1,841 @@
> +/*
> + * T T C P . C
> + *
> + * Test TCP connection. Makes a connection on port 5001
> + * and transfers fabricated buffers or data copied from stdin.
> + *
> + * Usable on 4.2, 4.3, and 4.1a systems by defining one of
> + * BSD42 BSD43 (BSD41a)
> + * Machines using System V with BSD sockets should define SYSV.
> + *
> + * Modified for operation under 4.2BSD, 18 Dec 84
> + * T.C. Slattery, USNA
> + * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
> + * Modified in 1989 at Silicon Graphics, Inc.
> + * catch SIGPIPE to be able to print stats when receiver has died
> + * for tcp, don't look for sentinel during reads to allow small transfers
> + * increased default buffer size to 8K, nbuf to 2K to transfer 16MB
> + * moved default port to 5001, beyond IPPORT_USERRESERVED
> + * make sinkmode default because it is more popular,
> + * -s now means don't sink/source
> + * count number of read/write system calls to see effects of
> + * blocking from full socket buffers
> + * for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt)
> + * buffer alignment options, -A and -O
> + * print stats in a format that's a bit easier to use with grep & awk
> + * for SYSV, mimic BSD routines to use most of the existing timing code
> + * Modified by Steve Miller of the University of Maryland, College Park
> + * -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF)
> + * Modified Sept. 1989 at Silicon Graphics, Inc.
> + * restored -s sense at request of tcs at brl
> + * Modified Oct. 1991 at Silicon Graphics, Inc.
> + * use getopt(3) for option processing, add -f and -T options.
> + * SGI IRIX 3.3 and 4.0 releases don't need #define SYSV.
> + *
> + * Distribution Status -
> + * Public Domain. Distribution Unlimited.
> + */
> +#ifndef lint
> +static char RCSid[] = "ttcp.c $Revision$";
> +#endif
> +
> +#define BSD43
> +/* #define BSD42 */
> +/* #define BSD41a */
> +/* #define SYSV */ /* required on SGI IRIX releases before 3.3 */
> +
> +#include <stdio.h>
> +#include <signal.h>
> +#include <ctype.h>
> +#include <errno.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <netinet/in.h>
> +#include <netinet/tcp.h>
> +#include <arpa/inet.h>
> +#include <netdb.h>
> +#include <sys/time.h> /* struct timeval */
> +
> +#if defined(SYSV)
> +#include <sys/times.h>
> +#include <sys/param.h>
> +struct rusage {
> + struct timeval ru_utime, ru_stime;
> +};
> +#define RUSAGE_SELF 0
> +#else
> +#include <sys/resource.h>
> +#endif
> +
> +struct sockaddr_in sinme;
> +struct sockaddr_in sinhim;
> +struct sockaddr_in frominet;
> +
> +int domain, fromlen;
> +int fd; /* fd of network socket */
> +
> +int buflen = 8 * 1024; /* length of buffer */
> +char *buf; /* ptr to dynamic buffer */
> +int nbuf = 2 * 1024; /* number of buffers to send in sinkmode */
> +
> +int bufoffset = 0; /* align buffer to this */
> +int bufalign = 16*1024; /* modulo this */
> +
> +int udp = 0; /* 0 = tcp, !0 = udp */
> +int options = 0; /* socket options */
> +int one = 1; /* for 4.3 BSD style setsockopt() */
> +short port = 5001; /* TCP port number */
> +char *host; /* ptr to name of host */
> +int trans; /* 0=receive, !0=transmit mode */
> +int sinkmode = 0; /* 0=normal I/O, !0=sink/source mode */
> +int verbose = 0; /* 0=print basic info, 1=print cpu rate, proc
> + * resource usage. */
> +int nodelay = 0; /* set TCP_NODELAY socket option */
> +int b_flag = 0; /* use mread() */
> +int sockbufsize = 0; /* socket buffer size to use */
> +char fmt = 'K'; /* output format: k = kilobits, K = kilobytes,
> + * m = megabits, M = megabytes,
> + * g = gigabits, G = gigabytes */
> +int touchdata = 0; /* access data after reading */
> +
> +struct hostent *addr;
> +extern int errno;
> +extern int optind;
> +extern char *optarg;
> +
> +char Usage[] = "\
> +Usage: ttcp -t [-options] host [ < in ]\n\
> + ttcp -r [-options > out]\n\
> +Common options:\n\
> + -l ## length of bufs read from or written to network (default 8192)\n\
> + -u use UDP instead of TCP\n\
> + -p ## port number to send to or listen at (default 5001)\n\
> + -s -t: source a pattern to network\n\
> + -r: sink (discard) all data from network\n\
> + -A align the start of buffers to this modulus (default 16384)\n\
> + -O start buffers at this offset from the modulus (default 0)\n\
> + -v verbose: print more statistics\n\
> + -d set SO_DEBUG socket option\n\
> + -b ## set socket buffer size (if supported)\n\
> + -f X format for rate: k,K = kilo{bit,byte}; m,M = mega; g,G = giga\n\
> +Options specific to -t:\n\
> + -n## number of source bufs written to network (default 2048)\n\
> + -D don't buffer TCP writes (sets TCP_NODELAY socket option)\n\
> +Options specific to -r:\n\
> + -B for -s, only output full blocks as specified by -l (for TAR)\n\
> + -T \"touch\": access each byte as it's read\n\
> +";
> +
> +char stats[128];
> +double nbytes; /* bytes on net */
> +unsigned long numCalls; /* # of I/O system calls */
> +double cput, realt; /* user, real time (seconds) */
> +
> +void err();
> +void mes();
> +int pattern();
> +void prep_timer();
> +double read_timer();
> +int Nread();
> +int Nwrite();
> +void delay();
> +int mread();
> +char *outfmt();
> +
> +void
> +sigpipe()
> +{
> +}
> +
> +main(argc,argv)
> +int argc;
> +char **argv;
> +{
> + unsigned long addr_tmp;
> + int c;
> +
> + if (argc < 2) goto usage;
> +
> + while ((c = getopt(argc, argv, "drstuvBDTb:f:l:n:p:A:O:")) != -1) {
> + switch (c) {
> +
> + case 'B':
> + b_flag = 1;
> + break;
> + case 't':
> + trans = 1;
> + break;
> + case 'r':
> + trans = 0;
> + break;
> + case 'd':
> + options |= SO_DEBUG;
> + break;
> + case 'D':
> +#ifdef TCP_NODELAY
> + nodelay = 1;
> +#else
> + fprintf(stderr,
> + "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n");
> +#endif
> + break;
> + case 'n':
> + nbuf = atoi(optarg);
> + break;
> + case 'l':
> + buflen = atoi(optarg);
> + break;
> + case 's':
> + sinkmode = !sinkmode;
> + break;
> + case 'p':
> + port = atoi(optarg);
> + break;
> + case 'u':
> + udp = 1;
> + break;
> + case 'v':
> + verbose = 1;
> + break;
> + case 'A':
> + bufalign = atoi(optarg);
> + break;
> + case 'O':
> + bufoffset = atoi(optarg);
> + break;
> + case 'b':
> +#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
> + sockbufsize = atoi(optarg);
> +#else
> + fprintf(stderr,
> +"ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n");
> +#endif
> + break;
> + case 'f':
> + fmt = *optarg;
> + break;
> + case 'T':
> + touchdata = 1;
> + break;
> +
> + default:
> + goto usage;
> + }
> + }
> + if(trans) {
> + /* xmitr */
> + if (optind == argc)
> + goto usage;
> + bzero((char *)&sinhim, sizeof(sinhim));
> + host = argv[optind];
> + if (atoi(host) > 0 ) {
> + /* Numeric */
> + sinhim.sin_family = AF_INET;
> +#if defined(cray)
> + addr_tmp = inet_addr(host);
> + sinhim.sin_addr = addr_tmp;
> +#else
> + sinhim.sin_addr.s_addr = inet_addr(host);
> +#endif
> + } else {
> + if ((addr=gethostbyname(host)) == NULL)
> + err("bad hostname");
> + sinhim.sin_family = addr->h_addrtype;
> + bcopy(addr->h_addr,(char*)&addr_tmp, addr->h_length);
> +#if defined(cray)
> + sinhim.sin_addr = addr_tmp;
> +#else
> + sinhim.sin_addr.s_addr = addr_tmp;
> +#endif /* cray */
> + }
> + sinhim.sin_port = htons(port);
> + sinme.sin_port = 0; /* free choice */
> + } else {
> + /* rcvr */
> + sinme.sin_port = htons(port);
> + }
> +
> +
> + if (udp && buflen < 5) {
> + buflen = 5; /* send more than the sentinel size */
> + }
> +
> + if ( (buf = (char *)malloc(buflen+bufalign)) == (char *)NULL)
> + err("malloc");
> + if (bufalign != 0)
> + buf +=(bufalign - ((int)buf % bufalign) + bufoffset) % bufalign;
> +
> + if (trans) {
> + fprintf(stdout,
> + "ttcp-t: buflen=%d, nbuf=%d, align=%d/%d, port=%d",
> + buflen, nbuf, bufalign, bufoffset, port);
> + if (sockbufsize)
> + fprintf(stdout, ", sockbufsize=%d", sockbufsize);
> + fprintf(stdout, " %s -> %s\n", udp?"udp":"tcp", host);
> + } else {
> + fprintf(stdout,
> + "ttcp-r: buflen=%d, nbuf=%d, align=%d/%d, port=%d",
> + buflen, nbuf, bufalign, bufoffset, port);
> + if (sockbufsize)
> + fprintf(stdout, ", sockbufsize=%d", sockbufsize);
> + fprintf(stdout, " %s\n", udp?"udp":"tcp");
> + }
> +
> + if ((fd = socket(AF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0)) < 0)
> + err("socket");
> + mes("socket");
> +
> + if (bind(fd, &sinme, sizeof(sinme)) < 0)
> + err("bind");
> +
> +#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
> + if (sockbufsize) {
> + if (trans) {
> + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
> + sizeof sockbufsize) < 0)
> + err("setsockopt: sndbuf");
> + mes("sndbuf");
> + } else {
> + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize,
> + sizeof sockbufsize) < 0)
> + err("setsockopt: rcvbuf");
> + mes("rcvbuf");
> + }
> + }
> +#endif
> +
> + if (!udp) {
> + signal(SIGPIPE, sigpipe);
> + if (trans) {
> + /* We are the client if transmitting */
> + if (options) {
> +#if defined(BSD42)
> + if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
> +#else /* BSD43 */
> + if( setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0)
> +#endif
> + err("setsockopt");
> + }
> +#ifdef TCP_NODELAY
> + if (nodelay) {
> + struct protoent *p;
> + p = getprotobyname("tcp");
> + if( p && setsockopt(fd, p->p_proto, TCP_NODELAY,
> + &one, sizeof(one)) < 0)
> + err("setsockopt: nodelay");
> + mes("nodelay");
> + }
> +#endif
> + if(connect(fd, &sinhim, sizeof(sinhim) ) < 0)
> + err("connect");
> + mes("connect");
> + } else {
> + /* otherwise, we are the server and
> + * should listen for the connections
> + */
> +#if defined(ultrix) || defined(sgi)
> + listen(fd,1); /* workaround for alleged u4.2 bug */
> +#else
> + listen(fd,0); /* allow a queue of 0 */
> +#endif
> + if(options) {
> +#if defined(BSD42)
> + if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
> +#else /* BSD43 */
> + if( setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0)
> +#endif
> + err("setsockopt");
> + }
> + fromlen = sizeof(frominet);
> + domain = AF_INET;
> + if((fd=accept(fd, &frominet, &fromlen) ) < 0)
> + err("accept");
> + { struct sockaddr_in peer;
> + int peerlen = sizeof(peer);
> + if (getpeername(fd, (struct sockaddr_in *) &peer,
> + &peerlen) < 0) {
> + err("getpeername");
> + }
> + fprintf(stderr,"ttcp-r: accept from %s\n",
> + inet_ntoa(peer.sin_addr));
> + }
> + }
> + }
> + prep_timer();
> + errno = 0;
> + if (sinkmode) {
> + register int cnt;
> + if (trans) {
> + pattern( buf, buflen );
> + if(udp) (void)Nwrite( fd, buf, 4 ); /* rcvr start */
> + while (nbuf-- && Nwrite(fd,buf,buflen) == buflen)
> + nbytes += buflen;
> + if(udp) (void)Nwrite( fd, buf, 4 ); /* rcvr end */
> + } else {
> + if (udp) {
> + while ((cnt=Nread(fd,buf,buflen)) > 0) {
> + static int going = 0;
> + if( cnt <= 4 ) {
> + if( going )
> + break; /* "EOF" */
> + going = 1;
> + prep_timer();
> + } else {
> + nbytes += cnt;
> + }
> + }
> + } else {
> + while ((cnt=Nread(fd,buf,buflen)) > 0) {
> + nbytes += cnt;
> + }
> + }
> + }
> + } else {
> + register int cnt;
> + if (trans) {
> + while((cnt=read(0,buf,buflen)) > 0 &&
> + Nwrite(fd,buf,cnt) == cnt)
> + nbytes += cnt;
> + } else {
> + while((cnt=Nread(fd,buf,buflen)) > 0 &&
> + write(1,buf,cnt) == cnt)
> + nbytes += cnt;
> + }
> + }
> + if(errno) err("IO");
> + (void)read_timer(stats,sizeof(stats));
> + if(udp&&trans) {
> + (void)Nwrite( fd, buf, 4 ); /* rcvr end */
> + (void)Nwrite( fd, buf, 4 ); /* rcvr end */
> + (void)Nwrite( fd, buf, 4 ); /* rcvr end */
> + (void)Nwrite( fd, buf, 4 ); /* rcvr end */
> + }
> + if( cput <= 0.0 ) cput = 0.001;
> + if( realt <= 0.0 ) realt = 0.001;
> + fprintf(stdout,
> + "ttcp%s: %.0f bytes in %.2f real seconds = %s/sec +++\n",
> + trans?"-t":"-r",
> + nbytes, realt, outfmt(nbytes/realt));
> + if (verbose) {
> + fprintf(stdout,
> + "ttcp%s: %.0f bytes in %.2f CPU seconds = %s/cpu sec\n",
> + trans?"-t":"-r",
> + nbytes, cput, outfmt(nbytes/cput));
> + }
> + fprintf(stdout,
> + "ttcp%s: %d I/O calls, msec/call = %.2f, calls/sec = %.2f\n",
> + trans?"-t":"-r",
> + numCalls,
> + 1024.0 * realt/((double)numCalls),
> + ((double)numCalls)/realt);
> + fprintf(stdout,"ttcp%s: %s\n", trans?"-t":"-r", stats);
> + if (verbose) {
> + fprintf(stdout,
> + "ttcp%s: buffer address %#x\n",
> + trans?"-t":"-r",
> + buf);
> + }
> + exit(0);
> +
> +usage:
> + fprintf(stderr,Usage);
> + exit(1);
> +}
> +
> +void
> +err(s)
> +char *s;
> +{
> + fprintf(stderr,"ttcp%s: ", trans?"-t":"-r");
> + perror(s);
> + fprintf(stderr,"errno=%d\n",errno);
> + exit(1);
> +}
> +
> +void
> +mes(s)
> +char *s;
> +{
> + fprintf(stderr,"ttcp%s: %s\n", trans?"-t":"-r", s);
> +}
> +
> +pattern( cp, cnt )
> +register char *cp;
> +register int cnt;
> +{
> + register char c;
> + c = 0;
> + while( cnt-- > 0 ) {
> + while( !isprint((c&0x7F)) ) c++;
> + *cp++ = (c++&0x7F);
> + }
> +}
> +
> +char *
> +outfmt(b)
> +double b;
> +{
> + static char obuf[50];
> + switch (fmt) {
> + case 'G':
> + sprintf(obuf, "%.2f GB", b / 1024.0 / 1024.0 / 1024.0);
> + break;
> + default:
> + case 'K':
> + sprintf(obuf, "%.2f KB", b / 1024.0);
> + break;
> + case 'M':
> + sprintf(obuf, "%.2f MB", b / 1024.0 / 1024.0);
> + break;
> + case 'g':
> + sprintf(obuf, "%.2f Gbit", b * 8.0 / 1024.0 / 1024.0 / 1024.0);
> + break;
> + case 'k':
> + sprintf(obuf, "%.2f Kbit", b * 8.0 / 1024.0);
> + break;
> + case 'm':
> + sprintf(obuf, "%.2f Mbit", b * 8.0 / 1024.0 / 1024.0);
> + break;
> + }
> + return obuf;
> +}
> +
> +static struct timeval time0; /* Time at which timing started */
> +static struct rusage ru0; /* Resource utilization at the start */
> +
> +static void prusage();
> +static void tvadd();
> +static void tvsub();
> +static void psecs();
> +
> +#if defined(SYSV)
> +/*ARGSUSED*/
> +static
> +getrusage(ignored, ru)
> + int ignored;
> + register struct rusage *ru;
> +{
> + struct tms buf;
> +
> + times(&buf);
> +
> + /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */
> + ru->ru_stime.tv_sec = buf.tms_stime / HZ;
> + ru->ru_stime.tv_usec = ((buf.tms_stime % HZ) * 1000000) / HZ;
> + ru->ru_utime.tv_sec = buf.tms_utime / HZ;
> + ru->ru_utime.tv_usec = ((buf.tms_utime % HZ) * 1000000) / HZ;
> +}
> +
> +/*ARGSUSED*/
> +static
> +gettimeofday(tp, zp)
> + struct timeval *tp;
> + struct timezone *zp;
> +{
> + tp->tv_sec = time(0);
> + tp->tv_usec = 0;
> +}
> +#endif /* SYSV */
> +
> +/*
> + * P R E P _ T I M E R
> + */
> +void
> +prep_timer()
> +{
> + gettimeofday(&time0, (struct timezone *)0);
> + getrusage(RUSAGE_SELF, &ru0);
> +}
> +
> +/*
> + * R E A D _ T I M E R
> + *
> + */
> +double
> +read_timer(str,len)
> +char *str;
> +{
> + struct timeval timedol;
> + struct rusage ru1;
> + struct timeval td;
> + struct timeval tend, tstart;
> + char line[132];
> +
> + getrusage(RUSAGE_SELF, &ru1);
> + gettimeofday(&timedol, (struct timezone *)0);
> + prusage(&ru0, &ru1, &timedol, &time0, line);
> + (void)strncpy( str, line, len );
> +
> + /* Get real time */
> + tvsub( &td, &timedol, &time0 );
> + realt = td.tv_sec + ((double)td.tv_usec) / 1000000;
> +
> + /* Get CPU time (user+sys) */
> + tvadd( &tend, &ru1.ru_utime, &ru1.ru_stime );
> + tvadd( &tstart, &ru0.ru_utime, &ru0.ru_stime );
> + tvsub( &td, &tend, &tstart );
> + cput = td.tv_sec + ((double)td.tv_usec) / 1000000;
> + if( cput < 0.00001 ) cput = 0.00001;
> + return( cput );
> +}
> +
> +static void
> +prusage(r0, r1, e, b, outp)
> + register struct rusage *r0, *r1;
> + struct timeval *e, *b;
> + char *outp;
> +{
> + struct timeval tdiff;
> + register time_t t;
> + register char *cp;
> + register int i;
> + int ms;
> +
> + t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+
> + (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+
> + (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+
> + (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000;
> + ms = (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000;
> +
> +#define END(x) {while(*x) x++;}
> +#if defined(SYSV)
> + cp = "%Uuser %Ssys %Ereal %P";
> +#else
> +#if defined(sgi) /* IRIX 3.3 will show 0 for %M,%F,%R,%C */
> + cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw";
> +#else
> + cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";
> +#endif
> +#endif
> + for (; *cp; cp++) {
> + if (*cp != '%')
> + *outp++ = *cp;
> + else if (cp[1]) switch(*++cp) {
> +
> + case 'U':
> + tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
> + sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000);
> + END(outp);
> + break;
> +
> + case 'S':
> + tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
> + sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000);
> + END(outp);
> + break;
> +
> + case 'E':
> + psecs(ms / 100, outp);
> + END(outp);
> + break;
> +
> + case 'P':
> + sprintf(outp,"%d%%", (int) (t*100 / ((ms ? ms : 1))));
> + END(outp);
> + break;
> +
> +#if !defined(SYSV)
> + case 'W':
> + i = r1->ru_nswap - r0->ru_nswap;
> + sprintf(outp,"%d", i);
> + END(outp);
> + break;
> +
> + case 'X':
> + sprintf(outp,"%d", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
> + END(outp);
> + break;
> +
> + case 'D':
> + sprintf(outp,"%d", t == 0 ? 0 :
> + (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t);
> + END(outp);
> + break;
> +
> + case 'K':
> + sprintf(outp,"%d", t == 0 ? 0 :
> + ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
> + (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
> + END(outp);
> + break;
> +
> + case 'M':
> + sprintf(outp,"%d", r1->ru_maxrss/2);
> + END(outp);
> + break;
> +
> + case 'F':
> + sprintf(outp,"%d", r1->ru_majflt-r0->ru_majflt);
> + END(outp);
> + break;
> +
> + case 'R':
> + sprintf(outp,"%d", r1->ru_minflt-r0->ru_minflt);
> + END(outp);
> + break;
> +
> + case 'I':
> + sprintf(outp,"%d", r1->ru_inblock-r0->ru_inblock);
> + END(outp);
> + break;
> +
> + case 'O':
> + sprintf(outp,"%d", r1->ru_oublock-r0->ru_oublock);
> + END(outp);
> + break;
> + case 'C':
> + sprintf(outp,"%d+%d", r1->ru_nvcsw-r0->ru_nvcsw,
> + r1->ru_nivcsw-r0->ru_nivcsw );
> + END(outp);
> + break;
> +#endif /* !SYSV */
> + }
> + }
> + *outp = '\0';
> +}
> +
> +static void
> +tvadd(tsum, t0, t1)
> + struct timeval *tsum, *t0, *t1;
> +{
> +
> + tsum->tv_sec = t0->tv_sec + t1->tv_sec;
> + tsum->tv_usec = t0->tv_usec + t1->tv_usec;
> + if (tsum->tv_usec > 1000000)
> + tsum->tv_sec++, tsum->tv_usec -= 1000000;
> +}
> +
> +static void
> +tvsub(tdiff, t1, t0)
> + struct timeval *tdiff, *t1, *t0;
> +{
> +
> + tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
> + tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
> + if (tdiff->tv_usec < 0)
> + tdiff->tv_sec--, tdiff->tv_usec += 1000000;
> +}
> +
> +static void
> +psecs(l,cp)
> +long l;
> +register char *cp;
> +{
> + register int i;
> +
> + i = l / 3600;
> + if (i) {
> + sprintf(cp,"%d:", i);
> + END(cp);
> + i = l % 3600;
> + sprintf(cp,"%d%d", (i/60) / 10, (i/60) % 10);
> + END(cp);
> + } else {
> + i = l;
> + sprintf(cp,"%d", i / 60);
> + END(cp);
> + }
> + i %= 60;
> + *cp++ = ':';
> + sprintf(cp,"%d%d", i / 10, i % 10);
> +}
> +
> +/*
> + * N R E A D
> + */
> +Nread( fd, buf, count )
> +int fd;
> +void *buf;
> +int count;
> +{
> + struct sockaddr_in from;
> + int len = sizeof(from);
> + register int cnt;
> + if( udp ) {
> + cnt = recvfrom( fd, buf, count, 0, &from, &len );
> + numCalls++;
> + } else {
> + if( b_flag )
> + cnt = mread( fd, buf, count ); /* fill buf */
> + else {
> + cnt = read( fd, buf, count );
> + numCalls++;
> + }
> + if (touchdata && cnt > 0) {
> + register int c = cnt, sum;
> + register char *b = buf;
> + while (c--)
> + sum += *b++;
> + }
> + }
> + return(cnt);
> +}
> +
> +/*
> + * N W R I T E
> + */
> +Nwrite( fd, buf, count )
> +int fd;
> +void *buf;
> +int count;
> +{
> + register int cnt;
> + if( udp ) {
> +again:
> + cnt = sendto( fd, buf, count, 0, &sinhim, sizeof(sinhim) );
> + numCalls++;
> + if( cnt<0 && errno == ENOBUFS ) {
> + delay(18000);
> + errno = 0;
> + goto again;
> + }
> + } else {
> + cnt = write( fd, buf, count );
> + numCalls++;
> + }
> + return(cnt);
> +}
> +
> +void
> +delay(us)
> +{
> + struct timeval tv;
> +
> + tv.tv_sec = 0;
> + tv.tv_usec = us;
> + (void)select( 1, (char *)0, (char *)0, (char *)0, &tv );
> +}
> +
> +/*
> + * M R E A D
> + *
> + * This function performs the function of a read(II) but will
> + * call read(II) multiple times in order to get the requested
> + * number of characters. This can be necessary because
> + * network connections don't deliver data with the same
> + * grouping as it is written with. Written by Robert S. Miles, BRL.
> + */
> +int
> +mread(fd, bufp, n)
> +int fd;
> +register char *bufp;
> +unsigned n;
> +{
> + register unsigned count = 0;
> + register int nread;
> +
> + do {
> + nread = read(fd, bufp, n-count);
> + numCalls++;
> + if(nread < 0) {
> + perror("ttcp_mread");
> + return(-1);
> + }
> + if(nread == 0)
> + return((int)count);
> + count += (unsigned)nread;
> + bufp += nread;
> + } while(count < n);
> +
> + return((int)count);
> +}
> --
> 2.27.0
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
More information about the devel
mailing list