root/test/sysperf/socketpair.c
/*
 * socketpair.c
 */

#include "blib.h"
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/un.h>

#define PAGE_SIZE       4096
#define PAGE_MASK       (PAGE_SIZE - 1)

int
main(int ac, char **av)
{
    long long count = 0;
    long long max;
    char c;
    int j;
    int loops;
    int bytes;
    int ppri = 999;
    int fds[2];
    char *buf;
    char *ptr;
    char *msg = "datarate";

    if (ac == 1) {
        fprintf(stderr, "%s blocksize[k,m] [pipe_writer_pri] [msg]\n", av[0]);
        exit(1);
    }
    bytes = strtol(av[1], &ptr, 0);
    if (*ptr == 'k' || *ptr == 'K') {
        bytes *= 1024;
    } else if (*ptr == 'm' || *ptr == 'M') {
        bytes *= 1024 * 1024;
    } else if (*ptr) {
        fprintf(stderr, "Illegal numerical suffix: %s\n", ptr);
        exit(1);
    }
    if (bytes <= 0) {
        fprintf(stderr, "I can't handle %d sized buffers\n", bytes);
        exit(1);
    }
    if (ac >= 3)
        ppri = strtol(av[2], NULL, 0);
    if (ac >= 4)
        msg = av[3];

    buf = mmap(NULL, bytes * 2 + PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);
    if (buf == MAP_FAILED) {
        perror("mmap/buffer");
        exit(1);
    }

    bzero(buf, bytes * 2 + PAGE_SIZE);

    printf("tests one-way socketpair\n");
    if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, fds)) {
        perror("socketpair");
        exit(1);
    }
    if (fork() == 0) {
        /*
         * child process
         */
        int n;
        int i;

        close(fds[0]);
        buf += (bytes + PAGE_MASK) & ~PAGE_MASK;
        i = 0;
        for (;;) {
            n = read(fds[1], buf + i, bytes - i);
            if (n <= 0)
                break;
            if (n + i == bytes)
                i = 0;
            else
                i += n;
        }
        _exit(0);
    } else {
        /*
         * parent process.
         */
        if (ppri != 999) {
            if (setpriority(PRIO_PROCESS, getpid(), ppri) < 0) {
                perror("setpriority");
                exit(1);
            }
        }
        close(fds[1]);

        /*
         * Figure out how many loops it takes for 1 second's worth.
         */
        start_timing();
        for (j = 0; ; ++j) {
            if (write(fds[0], buf, bytes) != bytes) {
                perror("write");
                exit(1);
            }
            if ((j & 31) == 0 && stop_timing(0, NULL))
                break;
        }
        loops = j * 2 + 1;
        usleep(1000000 / 10);
        start_timing();

        for (j = loops; j; --j) {
            if (write(fds[0], buf, bytes) != bytes) {
                perror("write");
                exit(1);
            }
        }
        close(fds[0]);
        while(wait(NULL) >= 0)
            ;
        stop_timing(loops, "full duplex socketpair / %dK bufs:", bytes / 1024);
        printf("%s: blkSize %d %5.2f MBytes/sec\n",
                msg,
                bytes,
                (double)loops * bytes * 1000000.0 /
                (1024.0 * 1024.0 * get_timing()));
    }
    return(0);
}