// File: /workspace/github_c_makefile_star2_O0/agraf[P]kvmbench/numa.c
// Function: main
int main(int argc, char **argv)
{
    int childpid[NR_CHILDREN];
    int pipefd[2];
    int i;
    uint64_t all_bytes = 0;
    int numa_node = 0;
    int numa_max = numa_max_node() + 1;
    int opt_aligned = 1;
    int opt_numactl = 1;
    int opt_rotate = 1;

    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-u")) {
            opt_aligned = 0;
        } else if (!strcmp(argv[i], "-N")) {
            opt_numactl = 0;
        } else if (!strcmp(argv[i], "-0")) {
            opt_rotate = 0;
        } else {
            printf("Syntax: %s\n\n", argv[0]);
            printf("  -u    Misalign NUMA nodes for reader/writer\n");
            printf("  -N    Disable NUMA awareness\n");
            printf("  -0    Always use NUMA node 0\n");
            printf("\n");
            exit(0);
        }
    }

    /*
     * We create reader and writer processes. Both are connected via pipes.
     * Writers keep writing 100MB chunks of garbage to the pipe. Readers read
     * that garbage and add up the number of bytes read.
     *
     * To account to full number of bytes read at the end, account them in
     * a shared memory range.
     */

    results = mmap(NULL, sizeof(*results) * NR_CHILDREN, PROT_READ | PROT_WRITE, 
                    MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    printf("Benchmarking message passing on %d NUMA nodes ...\n", numa_max);
    if (opt_numactl) {
        printf("  NUMA aware:        yes\n");
        printf("  NUMA aligned:      %s\n", opt_aligned ? "yes" : "no");
        printf("  NUMA nodes used:   0-%d\n", opt_rotate ? numa_max-1 : 0);
    } else {
        printf("  NUMA aware:        no\n");
    }
    printf("\n");

    for (i = 0; i < NR_CHILDREN; i++) {
        int cpid;
        int new_pair = ((i & 1) == CHILD_READER);

        if (new_pair) {
            if (pipe(pipefd)) {
                printf("Error while creating pipe: %s\n", strerror(errno));
                exit_all(childpid);
            }

            /*
             * Move to the next NUMA node, so we pin reader and writer to
             * the same node
             */
            numa_node++;
            numa_node %= numa_max;
        }

        if (!opt_rotate) {
            numa_node = 0;
        }

        cpid = fork();
        if (!cpid) {
            /*
             * We're a child now, figure out what we should do, but
             * first pin us to the numa node.
             */

            if (opt_numactl) {
                numa_set_preferred(numa_node);
                numa_run_on_node(numa_node);
            }

            results[i].node = numa_node_of_cpu(sched_getcpu());

            if ((i & 1) == CHILD_READER) {
                /* Reader */
                close(pipefd[CHILD_WRITER]);
                child_reader(pipefd[CHILD_READER], &results[i].bytes);
            } else {
                /* Writer */
                close(pipefd[CHILD_READER]);
                child_writer(pipefd[CHILD_WRITER]);
            }
        } else {
            /* Parent, remember child pid */
            childpid[i] = cpid;

            if (!opt_aligned) {
                numa_node++;
                numa_node %= numa_max;
            }
        }
    }

    /* Wait n seconds */
    sleep(RUN_SECS);

    for (i = 0; i < NR_CHILDREN; i++) {
        all_bytes += results[i].bytes;
    }

    printf("Total MB/s read: %ld\n", all_bytes / MB / RUN_SECS);

    /* Then quit */
    exit_all(childpid);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x1b8(%rbp)
movl $0x0, -0x1bc(%rbp)
callq 0x10b0
addl $0x1, %eax
movl %eax, -0x1c0(%rbp)
movl $0x1, -0x1c4(%rbp)
movl $0x1, -0x1c8(%rbp)
movl $0x1, -0x1cc(%rbp)
movl $0x1, -0x1ac(%rbp)
movl -0x1ac(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x141b
movq -0x10(%rbp), %rax
movslq -0x1ac(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0xccb(%rip), %rsi       # 0x2004
callq 0x10c0
cmpl $0x0, %eax
jne 0x1352
movl $0x0, -0x1c4(%rbp)
jmp 0x1405
movq -0x10(%rbp), %rax
movslq -0x1ac(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0xc9f(%rip), %rsi       # 0x2007
callq 0x10c0
cmpl $0x0, %eax
jne 0x1381
movl $0x0, -0x1c8(%rbp)
jmp 0x1403
movq -0x10(%rbp), %rax
movslq -0x1ac(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0xc73(%rip), %rsi       # 0x200a
callq 0x10c0
cmpl $0x0, %eax
jne 0x13ad
movl $0x0, -0x1cc(%rbp)
jmp 0x1401
movq -0x10(%rbp), %rax
movq (%rax), %rsi
leaq 0xc52(%rip), %rdi       # 0x200d
movb $0x0, %al
callq 0x1060
leaq 0xc51(%rip), %rdi       # 0x201a
movb $0x0, %al
callq 0x1060
leaq 0xc72(%rip), %rdi       # 0x2049
movb $0x0, %al
callq 0x1060
leaq 0xc84(%rip), %rdi       # 0x2069
movb $0x0, %al
callq 0x1060
leaq 0xc25(%rip), %rdi       # 0x2018
movb $0x0, %al
callq 0x1060
xorl %edi, %edi
callq 0x1130
jmp 0x1403
jmp 0x1405
jmp 0x1407
movl -0x1ac(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1ac(%rbp)
jmp 0x1314
xorl %eax, %eax
movl %eax, %r9d
movl $0x1900, %esi           # imm = 0x1900
movl $0x3, %edx
movl $0x21, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
movq %r9, %rdi
callq 0x1050
movq %rax, 0x2c8c(%rip)      # 0x40d0
movl -0x1c0(%rbp), %esi
leaq 0xc38(%rip), %rdi       # 0x2089
movb $0x0, %al
callq 0x1060
cmpl $0x0, -0x1c8(%rbp)
je 0x14d2
leaq 0xc54(%rip), %rdi       # 0x20bc
movb $0x0, %al
callq 0x1060
movl -0x1c4(%rbp), %ecx
leaq 0xc77(%rip), %rsi       # 0x20f3
leaq 0xc6c(%rip), %rax       # 0x20ef
cmpl $0x0, %ecx
cmovneq %rax, %rsi
leaq 0xc45(%rip), %rdi       # 0x20d6
movb $0x0, %al
callq 0x1060
cmpl $0x0, -0x1cc(%rbp)
je 0x14b2
movl -0x1c0(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x1d8(%rbp)
jmp 0x14bc
xorl %eax, %eax
movl %eax, -0x1d8(%rbp)
jmp 0x14bc
movl -0x1d8(%rbp), %esi
leaq 0xc2d(%rip), %rdi       # 0x20f6
movb $0x0, %al
callq 0x1060
jmp 0x14e0
leaq 0xc38(%rip), %rdi       # 0x2111
movb $0x0, %al
callq 0x1060
leaq 0xb31(%rip), %rdi       # 0x2018
movb $0x0, %al
callq 0x1060
movl $0x0, -0x1ac(%rbp)
cmpl $0x64, -0x1ac(%rbp)
jge 0x16a2
movl -0x1ac(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
sete %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x1d4(%rbp)
cmpl $0x0, -0x1d4(%rbp)
je 0x1586
leaq -0x1a8(%rbp), %rdi
callq 0x1090
cmpl $0x0, %eax
je 0x1562
callq 0x1030
movl (%rax), %edi
callq 0x1140
movq %rax, %rsi
leaq 0xbdb(%rip), %rdi       # 0x212a
movb $0x0, %al
callq 0x1060
leaq -0x1a0(%rbp), %rdi
callq 0x1270
movl -0x1bc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1bc(%rbp)
movl -0x1c0(%rbp), %ecx
movl -0x1bc(%rbp), %eax
cltd
idivl %ecx
movl %edx, -0x1bc(%rbp)
cmpl $0x0, -0x1cc(%rbp)
jne 0x1599
movl $0x0, -0x1bc(%rbp)
callq 0x1160
movl %eax, -0x1d0(%rbp)
cmpl $0x0, -0x1d0(%rbp)
jne 0x1649
cmpl $0x0, -0x1c8(%rbp)
je 0x15d0
movl -0x1bc(%rbp), %edi
callq 0x1120
movl -0x1bc(%rbp), %edi
callq 0x10f0
callq 0x1110
movl %eax, %edi
callq 0x1100
movl %eax, %ecx
movq 0x2aeb(%rip), %rax      # 0x40d0
movslq -0x1ac(%rbp), %rdx
shlq $0x6, %rdx
addq %rdx, %rax
movl %ecx, 0x8(%rax)
movl -0x1ac(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x1631
movl -0x1a4(%rbp), %edi
callq 0x1080
movl -0x1a8(%rbp), %edi
movq 0x2ab4(%rip), %rsi      # 0x40d0
movslq -0x1ac(%rbp), %rax
shlq $0x6, %rax
addq %rax, %rsi
callq 0x1740
jmp 0x1647
movl -0x1a8(%rbp), %edi
callq 0x1080
movl -0x1a4(%rbp), %edi
callq 0x17a0
jmp 0x168c
movl -0x1d0(%rbp), %ecx
movslq -0x1ac(%rbp), %rax
movl %ecx, -0x1a0(%rbp,%rax,4)
cmpl $0x0, -0x1c4(%rbp)
jne 0x168a
movl -0x1bc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1bc(%rbp)
movl -0x1c0(%rbp), %ecx
movl -0x1bc(%rbp), %eax
cltd
idivl %ecx
movl %edx, -0x1bc(%rbp)
jmp 0x168c
jmp 0x168e
movl -0x1ac(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1ac(%rbp)
jmp 0x14f8
movl $0x5, %edi
callq 0x1150
movl $0x0, -0x1ac(%rbp)
cmpl $0x64, -0x1ac(%rbp)
jge 0x16f6
movq 0x2a0a(%rip), %rax      # 0x40d0
movslq -0x1ac(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq (%rax), %rax
addq -0x1b8(%rbp), %rax
movq %rax, -0x1b8(%rbp)
movl -0x1ac(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1ac(%rbp)
jmp 0x16b6
movq -0x1b8(%rbp), %rax
shrq $0x14, %rax
movl $0x5, %ecx
xorl %edx, %edx
divq %rcx
movq %rax, %rsi
leaq 0xa34(%rip), %rdi       # 0x2149
movb $0x0, %al
callq 0x1060
leaq -0x1a0(%rbp), %rdi
callq 0x1270
xorl %eax, %eax
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
nopw %cs:(%rax,%rax)