// File: williewillus[P]panda_scratchpad/src/wrapper/workload.cpp
// Function: wrapper::WriteDataMmap(int, unsigned int, unsigned int)
int WriteDataMmap(int fd, unsigned int offset, unsigned int size) {
  const unsigned int map_size = size + (offset & ((1 << 12) - 1));
  char *filep = (char *) mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED,
      fd, offset & ~((1 << 12) - 1));
  if (filep == MAP_FAILED) {
    return -1;
  }

  // Offset into a data block to start working at.
  const unsigned int rounded_offset_diff =
    ((offset + (kTestDataSize - 1)) & (~(kTestDataSize - 1))) - offset;

  // The start of the write range is not aligned with our data blocks.
  // Therefore, we should write out part of a data block for this segment,
  // with the first character in the data block aligning with the data block
  // boundary.
  if (rounded_offset_diff != 0) {
    const char *file_start_offset = filep + (offset & ((1 << 12) - 1));
    const unsigned int test_data_offset = offset & (kTestDataSize - 1);
    memcpy((char *) file_start_offset, kTestDataBlock + test_data_offset,
        kTestDataSize - test_data_offset);
  }

  // Write out the rest of the data for this request. All writes from here out
  // will have their first byte aligned with kTestDataSize.
  unsigned int num_written = 0;
  while (num_written != size - rounded_offset_diff) {
    const unsigned int to_write =
      (num_written + kTestDataSize > size - rounded_offset_diff)
      ? size - rounded_offset_diff - num_written
      : kTestDataSize;
    memcpy(filep + rounded_offset_diff + num_written, kTestDataBlock,
        to_write);
    num_written += to_write;
  }

  if (msync(filep, map_size, MS_SYNC) < 0) {
    munmap(filep, map_size);
    return -1;
  }

  munmap(filep, map_size);
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movl %edi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl -0x10(%rbp), %eax
movl -0xc(%rbp), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
addl %ecx, %eax
movl %eax, -0x14(%rbp)
movl -0x10(%rbp), %eax
movl %eax, %esi
movl -0x8(%rbp), %r8d
movl -0xc(%rbp), %eax
andl $0xfffff000, %eax       # imm = 0xFFFFF000
movl %eax, %eax
movl %eax, %r9d
xorl %eax, %eax
movl %eax, %edi
movl $0x3, %edx
movl $0x1, %ecx
callq 0x1aa20
movq %rax, -0x20(%rbp)
movq $-0x1, %rax
cmpq %rax, -0x20(%rbp)
jne 0x1d4c8
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1d5d8
movl -0xc(%rbp), %eax
addl $0xfff, %eax            # imm = 0xFFF
andl $0xfffff000, %eax       # imm = 0xFFFFF000
subl -0xc(%rbp), %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0x1d524
movq -0x20(%rbp), %rax
movl -0xc(%rbp), %ecx
andl $0xfff, %ecx            # imm = 0xFFF
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movl -0xc(%rbp), %eax
andl $0xfff, %eax            # imm = 0xFFF
movl %eax, -0x34(%rbp)
movq -0x30(%rbp), %rdi
movl -0x34(%rbp), %eax
leaq 0xbbf0(%rip), %rsi      # 0x29100
addq %rax, %rsi
movl $0x1000, %eax           # imm = 0x1000
subl -0x34(%rbp), %eax
movl %eax, %eax
movl %eax, %edx
callq 0x19b30
movl $0x0, -0x38(%rbp)
movl -0x38(%rbp), %eax
movl -0x10(%rbp), %ecx
subl -0x24(%rbp), %ecx
cmpl %ecx, %eax
je 0x1d594
movl -0x38(%rbp), %eax
addl $0x1000, %eax           # imm = 0x1000
movl -0x10(%rbp), %ecx
subl -0x24(%rbp), %ecx
cmpl %ecx, %eax
jbe 0x1d558
movl -0x10(%rbp), %eax
subl -0x24(%rbp), %eax
subl -0x38(%rbp), %eax
movl %eax, -0x40(%rbp)
jmp 0x1d562
movl $0x1000, %eax           # imm = 0x1000
movl %eax, -0x40(%rbp)
jmp 0x1d562
movl -0x40(%rbp), %eax
movl %eax, -0x3c(%rbp)
movq -0x20(%rbp), %rdi
movl -0x24(%rbp), %eax
addq %rax, %rdi
movl -0x38(%rbp), %eax
addq %rax, %rdi
movl -0x3c(%rbp), %eax
movl %eax, %edx
leaq 0xbb7c(%rip), %rsi      # 0x29100
callq 0x19b30
movl -0x3c(%rbp), %eax
addl -0x38(%rbp), %eax
movl %eax, -0x38(%rbp)
jmp 0x1d52b
movq -0x20(%rbp), %rdi
movl -0x14(%rbp), %eax
movl %eax, %esi
movl $0x4, %edx
callq 0x19120
cmpl $0x0, %eax
jge 0x1d5c3
movq -0x20(%rbp), %rdi
movl -0x14(%rbp), %eax
movl %eax, %esi
callq 0x196e0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1d5d8
movq -0x20(%rbp), %rdi
movl -0x14(%rbp), %eax
movl %eax, %esi
callq 0x196e0
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)