// File: flordan[P]ipc_benchmark/posix_mq/producer.cpp
// Function: main
int main(int argc, char *argv[])
{
    std::cout << "Producer running" << std::endl;

    int pid = getpid();
    std::cout << "Producer PID " << pid << std::endl;

    mqd_t mq_producer, mq_consumer;

    std::ostringstream producer_queue_name_builder;
    producer_queue_name_builder << "/producer" << pid;
    const char *producer_queue_name = producer_queue_name_builder.str().c_str();

    struct mq_attr attr;
    attr.mq_flags = 0;
    attr.mq_maxmsg = MAX_MESSAGES;
    attr.mq_msgsize = MAX_MSG_SIZE;
    attr.mq_curmsgs = 0;
    if ((mq_producer = mq_open(producer_queue_name, O_RDONLY | O_CREAT, QUEUE_PERMISSIONS, &attr)) == -1)
    {
        std::cerr << "Cannot open " << producer_queue_name << std::endl;
        return 1;
    }
    else
    {
        std::cout << "Created queue " << producer_queue_name << std::endl;
    }

    char *consumer_pid = argv[1];
    std::ostringstream consumer_queue_name_builder;
    consumer_queue_name_builder << "/consumer" << consumer_pid;
    const char *consumer_queue_name = consumer_queue_name_builder.str().c_str();

    std::cout << "Synchronizing with consumer " << consumer_queue_name << std::endl;
    while ((mq_consumer = mq_open(consumer_queue_name, O_WRONLY)) == -1)
    {
        std::cerr << "Queue " << consumer_queue_name << " not yet open." << std::endl;
        usleep(500000);
    }
    if (mq_send(mq_consumer, producer_queue_name, std::strlen(producer_queue_name) + 1, 0) == -1)
    {
        std::cerr << "Not able to send message to consumer" << std::endl;
        return 0;
    }
    char in_buffer[MSG_BUFFER_SIZE];
    if (mq_receive(mq_producer, in_buffer, MSG_BUFFER_SIZE, NULL) == -1)
    {
        std::cerr << "Cannot read from queue " << producer_queue_name << std::endl;
        return 1;
    }

    if (mq_close (mq_producer) == -1) {
        std::cerr << "Not able to close producer queue" << std::endl;
        return 1;
    }
    if (mq_unlink (producer_queue_name) == -1) {
        std::cerr << "Not able to delete producer queue "<< producer_queue_name << std::endl;
        return 1;
    }
    std::cout << "Synchronized" << std::endl;

    std::cout << "Latency test" << std::endl;
    
    struct timeval st;
    for (int i = 0; i < LATENCY_PROBES; i++)
    {
        gettimeofday(&st, NULL);
        std::ostringstream os ;
        os << st.tv_sec << "." << st.tv_usec+1000000;
        std::string mystr = os.str();
        const char* time = mystr.c_str();
        mq_send(mq_consumer,time, std::strlen(time)+1,0);
        usleep(250000);
    }

    if (mq_close (mq_consumer) == -1) {
        std::cerr << "Not able to close consumer queue" << std::endl;
        return 1;
    }

    std::cout << "Finished" << std::endl;
}

// Assembly:
subq $0x7a8, %rsp            # imm = 0x7A8
movl $0x0, 0x7a4(%rsp)
movl %edi, 0x7a0(%rsp)
movq %rsi, 0x798(%rsp)
movq 0x2ce8(%rip), %rdi      # 0x3fd0
movq %rdi, 0xf8(%rsp)
leaq 0xd0d(%rip), %rsi       # 0x2004
callq 0x10b0
movq %rax, %rdi
movq 0x2cba(%rip), %rsi      # 0x3fc0
movq %rsi, 0x100(%rsp)
callq 0x10d0
callq 0x1110
movq 0xf8(%rsp), %rdi
movl %eax, 0x794(%rsp)
leaq 0xce7(%rip), %rsi       # 0x2015
callq 0x10b0
movq %rax, %rdi
movl 0x794(%rsp), %esi
callq 0x1150
movq 0x100(%rsp), %rsi
movq %rax, %rdi
callq 0x10d0
leaq 0x610(%rsp), %rdi
movq %rdi, 0x108(%rsp)
callq 0x10f0
movq 0x108(%rsp), %rdi
leaq 0xcad(%rip), %rsi       # 0x2023
callq 0x10b0
movq %rax, 0x110(%rsp)
jmp 0x1385
movq 0x110(%rsp), %rdi
movl 0x794(%rsp), %esi
callq 0x1150
jmp 0x139b
leaq 0x5d8(%rsp), %rdi
leaq 0x610(%rsp), %rsi
callq 0x10c0
jmp 0x13b2
leaq 0x5d8(%rsp), %rdi
callq 0x1050
movq %rax, 0xf0(%rsp)
leaq 0x5d8(%rsp), %rdi
callq 0x1080
movq 0xf0(%rsp), %rax
movq %rax, 0x5f8(%rsp)
movq $0x0, 0x598(%rsp)
movq $0xa, 0x5a0(%rsp)
movq $0x100, 0x5a8(%rsp) # imm = 0x100
movq $0x0, 0x5b0(%rsp)
movq 0x5f8(%rsp), %rdi
movl $0x40, %esi
movl $0x1b0, %edx            # imm = 0x1B0
leaq 0x598(%rsp), %rcx
movb $0x0, %al
callq 0x1070
movl %eax, 0x790(%rsp)
cmpl $-0x1, %eax
jne 0x14cb
movq 0x2ba4(%rip), %rdi      # 0x3ff0
leaq 0xbda(%rip), %rsi       # 0x202d
callq 0x10b0
movq %rax, 0xe8(%rsp)
jmp 0x1462
movq 0xe8(%rsp), %rdi
movq 0x5f8(%rsp), %rsi
callq 0x10b0
movq %rax, 0xe0(%rsp)
jmp 0x1481
movq 0xe0(%rsp), %rdi
movq 0x2b30(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1497
movl $0x1, 0x7a4(%rsp)
movl $0x1, 0x594(%rsp)
jmp 0x1b30
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x608(%rsp)
movl %eax, 0x604(%rsp)
jmp 0x1b59
movq 0x2afe(%rip), %rdi      # 0x3fd0
leaq 0xb61(%rip), %rsi       # 0x203a
callq 0x10b0
movq %rax, 0xd8(%rsp)
jmp 0x14e8
movq 0xd8(%rsp), %rdi
movq 0x5f8(%rsp), %rsi
callq 0x10b0
movq %rax, 0xd0(%rsp)
jmp 0x1507
movq 0xd0(%rsp), %rdi
movq 0x2aaa(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x151d
jmp 0x151f
movq 0x798(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x588(%rsp)
leaq 0x410(%rsp), %rdi
callq 0x10f0
jmp 0x1542
leaq 0xb00(%rip), %rsi       # 0x2049
leaq 0x410(%rsp), %rdi
callq 0x10b0
movq %rax, 0xc8(%rsp)
jmp 0x1560
movq 0xc8(%rsp), %rdi
movq 0x588(%rsp), %rsi
callq 0x10b0
jmp 0x1577
leaq 0x3e8(%rsp), %rdi
leaq 0x410(%rsp), %rsi
callq 0x10c0
jmp 0x158e
leaq 0x3e8(%rsp), %rdi
movq %rdi, 0xb0(%rsp)
callq 0x1050
movq 0xb0(%rsp), %rdi
movq %rax, 0xb8(%rsp)
callq 0x1080
movq 0xb8(%rsp), %rax
movq %rax, 0x408(%rsp)
movq 0x2a01(%rip), %rdi      # 0x3fd0
leaq 0xa7d(%rip), %rsi       # 0x2053
callq 0x10b0
movq %rax, 0xc0(%rsp)
jmp 0x15e5
movq 0xc0(%rsp), %rdi
movq 0x408(%rsp), %rsi
callq 0x10b0
movq %rax, 0xa8(%rsp)
jmp 0x1604
movq 0xa8(%rsp), %rdi
movq 0x29ad(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x161a
jmp 0x161c
movq 0x408(%rsp), %rdi
movl $0x1, %esi
movb $0x0, %al
callq 0x1070
movl %eax, 0x78c(%rsp)
cmpl $-0x1, %eax
jne 0x16da
movq 0x29a9(%rip), %rdi      # 0x3ff0
leaq 0xa22(%rip), %rsi       # 0x2070
callq 0x10b0
movq %rax, 0xa0(%rsp)
jmp 0x165d
movq 0xa0(%rsp), %rdi
movq 0x408(%rsp), %rsi
callq 0x10b0
movq %rax, 0x98(%rsp)
jmp 0x167c
movq 0x98(%rsp), %rdi
leaq 0x9ec(%rip), %rsi       # 0x2077
callq 0x10b0
movq %rax, 0x90(%rsp)
jmp 0x169a
movq 0x90(%rsp), %rdi
movq 0x2917(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x16b0
movl $0x7a120, %edi          # imm = 0x7A120
callq 0x1100
jmp 0x16bc
jmp 0x161c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x608(%rsp)
movl %eax, 0x604(%rsp)
jmp 0x1b4c
movl 0x78c(%rsp), %eax
movl %eax, 0x7c(%rsp)
movq 0x5f8(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x1060
movl 0x7c(%rsp), %edi
movq 0x80(%rsp), %rsi
movq %rax, %rdx
incq %rdx
xorl %ecx, %ecx
callq 0x10e0
movl %eax, 0x8c(%rsp)
jmp 0x171c
movl 0x8c(%rsp), %eax
cmpl $-0x1, %eax
jne 0x1770
movq 0x28c1(%rip), %rdi      # 0x3ff0
leaq 0x950(%rip), %rsi       # 0x2086
callq 0x10b0
movq %rax, 0x70(%rsp)
jmp 0x1742
movq 0x70(%rsp), %rdi
movq 0x2872(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1755
movl $0x0, 0x7a4(%rsp)
movl $0x1, 0x594(%rsp)
jmp 0x1b23
movl 0x790(%rsp), %edi
xorl %eax, %eax
movl %eax, %ecx
leaq 0x2d0(%rsp), %rsi
movl $0x10a, %edx            # imm = 0x10A
callq 0x1040
movq %rax, 0x68(%rsp)
jmp 0x1794
movq 0x68(%rsp), %rax
cmpq $-0x1, %rax
jne 0x1800
movq 0x284a(%rip), %rdi      # 0x3ff0
leaq 0x8fe(%rip), %rsi       # 0x20ab
callq 0x10b0
movq %rax, 0x60(%rsp)
jmp 0x17b9
movq 0x60(%rsp), %rdi
movq 0x5f8(%rsp), %rsi
callq 0x10b0
movq %rax, 0x58(%rsp)
jmp 0x17d2
movq 0x58(%rsp), %rdi
movq 0x27e2(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x17e5
movl $0x1, 0x7a4(%rsp)
movl $0x1, 0x594(%rsp)
jmp 0x1b23
movl 0x790(%rsp), %edi
callq 0x1120
cmpl $-0x1, %eax
jne 0x1859
movq 0x27d8(%rip), %rdi      # 0x3ff0
leaq 0x8a4(%rip), %rsi       # 0x20c3
callq 0x10b0
movq %rax, 0x50(%rsp)
jmp 0x182b
movq 0x50(%rsp), %rdi
movq 0x2789(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x183e
movl $0x1, 0x7a4(%rsp)
movl $0x1, 0x594(%rsp)
jmp 0x1b23
movq 0x5f8(%rsp), %rdi
callq 0x1090
cmpl $-0x1, %eax
jne 0x18cc
movq 0x277e(%rip), %rdi      # 0x3ff0
leaq 0x86b(%rip), %rsi       # 0x20e4
callq 0x10b0
movq %rax, 0x48(%rsp)
jmp 0x1885
movq 0x48(%rsp), %rdi
movq 0x5f8(%rsp), %rsi
callq 0x10b0
movq %rax, 0x40(%rsp)
jmp 0x189e
movq 0x40(%rsp), %rdi
movq 0x2716(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x18b1
movl $0x1, 0x7a4(%rsp)
movl $0x1, 0x594(%rsp)
jmp 0x1b23
movq 0x26fd(%rip), %rdi      # 0x3fd0
leaq 0x82d(%rip), %rsi       # 0x2107
callq 0x10b0
movq %rax, 0x38(%rsp)
jmp 0x18e6
movq 0x38(%rsp), %rdi
movq 0x26ce(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x18f9
movq 0x26d0(%rip), %rdi      # 0x3fd0
leaq 0x80d(%rip), %rsi       # 0x2114
callq 0x10b0
movq %rax, 0x30(%rsp)
jmp 0x1913
movq 0x30(%rsp), %rdi
movq 0x26a1(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1926
movl $0x0, 0x2bc(%rsp)
cmpl $0x3e8, 0x2bc(%rsp) # imm = 0x3E8
jge 0x1a97
xorl %eax, %eax
movl %eax, %esi
leaq 0x2c0(%rsp), %rdi
callq 0x1140
leaq 0x140(%rsp), %rdi
callq 0x10f0
jmp 0x1962
movq 0x2c0(%rsp), %rsi
leaq 0x140(%rsp), %rdi
callq 0x1170
movq %rax, 0x28(%rsp)
jmp 0x197e
movq 0x28(%rsp), %rdi
leaq 0x6fa(%rip), %rsi       # 0x2084
callq 0x10b0
movq %rax, 0x20(%rsp)
jmp 0x1996
movq 0x20(%rsp), %rdi
movq 0x2c8(%rsp), %rsi
addq $0xf4240, %rsi          # imm = 0xF4240
callq 0x1170
jmp 0x19b1
leaq 0x120(%rsp), %rdi
leaq 0x140(%rsp), %rsi
callq 0x10c0
jmp 0x19c8
leaq 0x120(%rsp), %rdi
callq 0x1050
movq %rax, 0x118(%rsp)
movl 0x78c(%rsp), %eax
movl %eax, 0x14(%rsp)
movq 0x118(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x1060
movl 0x14(%rsp), %edi
movq 0x18(%rsp), %rsi
movq %rax, %rdx
incq %rdx
xorl %ecx, %ecx
callq 0x10e0
jmp 0x1a12
movl $0x3d090, %edi          # imm = 0x3D090
callq 0x1100
jmp 0x1a1e
leaq 0x120(%rsp), %rdi
callq 0x1080
leaq 0x140(%rsp), %rdi
callq 0x1030
movl 0x2bc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2bc(%rsp)
jmp 0x1931
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x608(%rsp)
movl %eax, 0x604(%rsp)
jmp 0x1a85
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x608(%rsp)
movl %eax, 0x604(%rsp)
leaq 0x120(%rsp), %rdi
callq 0x1080
leaq 0x140(%rsp), %rdi
callq 0x1030
jmp 0x1b4c
movl 0x78c(%rsp), %edi
callq 0x1120
cmpl $-0x1, %eax
jne 0x1aed
movq 0x2541(%rip), %rdi      # 0x3ff0
leaq 0x66b(%rip), %rsi       # 0x2121
callq 0x10b0
movq %rax, 0x8(%rsp)
jmp 0x1ac2
movq 0x8(%rsp), %rdi
movq 0x24f2(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1ad5
movl $0x1, 0x7a4(%rsp)
movl $0x1, 0x594(%rsp)
jmp 0x1b23
movq 0x24dc(%rip), %rdi      # 0x3fd0
leaq 0x647(%rip), %rsi       # 0x2142
callq 0x10b0
movq %rax, (%rsp)
jmp 0x1b06
movq (%rsp), %rdi
movq 0x24af(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1b18
movl $0x0, 0x594(%rsp)
leaq 0x410(%rsp), %rdi
callq 0x1030
leaq 0x610(%rsp), %rdi
callq 0x1030
movl 0x7a4(%rsp), %eax
addq $0x7a8, %rsp            # imm = 0x7A8
retq
leaq 0x410(%rsp), %rdi
callq 0x1030
leaq 0x610(%rsp), %rdi
callq 0x1030
movq 0x608(%rsp), %rdi
callq 0x1160