// File: /workspace/github_c_makefile_star2_O3/LPD-EPFL[P]mctop/src/mctop.c
// Function: mem_bandwidth
void*
mem_bandwidth(void* param)
{
  tld_t* tld = (tld_t*) param;
  const int tid = tld->id;
  const uint n_threads = tld->n_threads;
  pthread_barrier_t* barrier = tld->barrier;
  mctop_t* topo = tld->topo;
  const uint n_u64 = test_mem_bw_size / sizeof(uint64_t);

  volatile cache_line_t** mem_bw = malloc_assert(mctop_get_num_nodes(topo) * sizeof(cache_line_t*));
  for (int n = 0; n < mctop_get_num_nodes(topo); n++)
    {
      mem_bw[n] = numa_alloc_onnode(test_mem_bw_size, n);
      bzero((void*) mem_bw[n], test_mem_bw_size);
    }

  ID0_DO(mem_bw_gbps_r = (double*) malloc_assert(n_threads * sizeof(double));
	 mem_bw_gbps_w = (double*) malloc_assert(n_threads * sizeof(double)));

  double progress_step = 100.0 / (topo->n_sockets * topo->n_sockets);
  uint progress = 0;
  ID0_DO(NOT_VERBOSE(printf("# Progress : %6.1f%%", 0.0)); fflush(stdout));

  for (int n = 0; n < mctop_get_num_nodes(topo); n++)
    {
      mctop_run_on_socket_nm(topo, n);
      VERBOSE(ID0_DO(printf(" ######## Run Socket %d\n", n);););
      for (int mem_on = 0; mem_on < mctop_get_num_nodes(topo); mem_on++)
	{
	  VERBOSE(ID0_DO(printf(" #### Mem Node %d\n", mem_on)););

	  pthread_barrier_wait(barrier);
	  if (tid == 0)
	    {
	      dvfs_scale_up(test_num_dvfs_reps, test_dvfs_ratio, NULL);
	      double bw_gbps_r = mem_bw_estimate(mem_bw[mem_on], BW_READ, n_u64, test_mem_bw_num_reps);
	      mem_bw_table1_r[n][mem_on] = bw_gbps_r;
	      double bw_gbps_w = mem_bw_estimate(mem_bw[mem_on], BW_WRITE, n_u64, test_mem_bw_num_reps);
	      mem_bw_table1_w[n][mem_on] = bw_gbps_w;
	    }
	  pthread_barrier_wait(barrier);

	  dvfs_scale_up(test_num_dvfs_reps, test_dvfs_ratio, NULL);
	  mini_barrier(&mem_bw_barrier, n_threads);

	  double bw_gbps_r = mem_bw_estimate(mem_bw[mem_on], BW_READ, n_u64, test_mem_bw_num_reps);
	  mem_bw_gbps_r[tid] = bw_gbps_r;
	  double bw_gbps_w = mem_bw_estimate(mem_bw[mem_on], BW_WRITE, n_u64, test_mem_bw_num_reps);
	  mem_bw_gbps_w[tid] = bw_gbps_w;

	  pthread_barrier_wait(barrier);

	  if (tid == 0)
	    {
	      mem_bw_barrier = 0;
	      double tot_bw_r = 0, tot_bw_w = 0;
	      VERBOSE(printf("   READ  BW ("););
	      for (int i = 0; i < n_threads; i++)
		{
		  VERBOSE(printf("+%2.2f", mem_bw_gbps_r[i]););
		  tot_bw_r += mem_bw_gbps_r[i];
		}
	      VERBOSE(printf(") = %f GB/s\n", tot_bw_r););
	      mem_bw_table_r[n][mem_on] = tot_bw_r;

	      VERBOSE(printf("   WRITE BW ("););
	      for (int i = 0; i < n_threads; i++)
		{
		  VERBOSE(printf("+%2.2f", mem_bw_gbps_w[i]););
		  tot_bw_w += mem_bw_gbps_w[i];
		}
	      VERBOSE(printf(") = %f GB/s\n", tot_bw_w););
	      mem_bw_table_w[n][mem_on] = tot_bw_w;

	      NOT_VERBOSE(printf("\r# Progress : %6.1f%%", ++progress * progress_step); fflush(stdout););
	    }
	}
    }

  for (int n = 0; n < mctop_get_num_nodes(topo); n++)
    {
      numa_free((void*) mem_bw[n], test_mem_bw_size);
    }
  free(mem_bw);


  if (tid == 0)
    {
      NOT_VERBOSE(printf("\n"););
      free((void*) mem_bw_gbps_r);
      free((void*) mem_bw_gbps_w);
    }
  return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movslq (%rdi), %r14
movl 0x4(%rdi), %ebp
movq 0x18(%rdi), %rax
movq %rax, 0x18(%rsp)
movq 0x20(%rdi), %r13
movq 0xc950(%rip), %r15      # 0x10220
movq %r13, %rdi
callq 0x8be5
leaq (,%rax,8), %rdi
callq 0x21d0
movq %rax, 0x10(%rsp)
testq %rax, %rax
je 0x3e11
movq %r13, %rdi
callq 0x8be5
testq %rax, %rax
movq 0x10(%rsp), %rbx
je 0x393c
xorl %r12d, %r12d
movq 0xc911(%rip), %rdi      # 0x10220
movl %r12d, %esi
callq 0x21f0
movq %rax, (%rbx,%r12,8)
movq 0xc8fe(%rip), %rdx      # 0x10220
movq %rax, %rdi
xorl %esi, %esi
callq 0x2120
incq %r12
movq %r13, %rdi
callq 0x8be5
cmpq %r12, %rax
ja 0x3908
testl %r14d, %r14d
je 0x394b
movl 0x18(%r13), %r12d
imull %r12d, %r12d
jmp 0x39b5
leaq (,%rbp,8), %r12
movq %r12, %rdi
callq 0x21d0
testq %rax, %rax
je 0x3e11
movq %rax, 0xc96d(%rip)      # 0x102d8
movq %r12, %rdi
callq 0x21d0
testq %rax, %rax
je 0x3e11
movq %rax, 0xc95d(%rip)      # 0x102e0
movl 0x18(%r13), %r12d
cmpl $0x0, 0xc8fa(%rip)      # 0x10288
jne 0x39a2
leaq 0x69b5(%rip), %rdi      # 0xa34c
xorpd %xmm0, %xmm0
movb $0x1, %al
callq 0x2100
imull %r12d, %r12d
movq 0xc61b(%rip), %rax      # 0xffc8
movq (%rax), %rdi
callq 0x21e0
movq %r13, %rdi
callq 0x8be5
testq %rax, %rax
je 0x3db8
shrq $0x3, %r15
movl %r12d, %eax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
movsd 0x662b(%rip), %xmm1     # 0xa008
divsd %xmm0, %xmm1
movsd %xmm1, 0x30(%rsp)
movl %r15d, %r12d
xorl %ebx, %ebx
movq $0x0, 0x20(%rsp)
movq %r13, 0x28(%rsp)
movq %r13, %rdi
movl %ebx, %esi
callq 0x8f9d
cmpl $0x0, 0xc87d(%rip)      # 0x10288
jne 0x3d9a
movq %r13, %rdi
callq 0x8be5
testq %rax, %rax
je 0x3d7f
xorl %r13d, %r13d
movq %rbx, %r15
cmpl $0x0, 0xc859(%rip)      # 0x10288
jne 0x3c9c
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x2090
testl %r14d, %r14d
jne 0x3ab2
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0x65bc(%rip), %xmm0     # 0xa010
xorl %esi, %esi
callq 0x5dbd
movq 0x10(%rsp), %rax
movq (%rax,%r13,8), %rbx
movl $0x4, %ecx
movq %rbx, %rdi
xorl %esi, %esi
movq %r12, %rdx
callq 0x3744
movq 0xc86b(%rip), %rax      # 0x102e8
movq (%rax,%r15,8), %rax
movsd %xmm0, (%rax,%r13,8)
movl $0x4, %ecx
movq %rbx, %rdi
movl $0x1, %esi
movq %r12, %rdx
callq 0x3744
movq 0xc84d(%rip), %rax      # 0x102f0
movq (%rax,%r15,8), %rax
movq 0x18(%rsp), %rbx
movsd %xmm0, (%rax,%r13,8)
movq %rbx, %rdi
callq 0x2090
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0x6549(%rip), %xmm0     # 0xa010
xorl %esi, %esi
callq 0x5dbd
lock
incl 0xc7e7(%rip)            # 0x102bc
movl 0xc7e1(%rip), %eax      # 0x102bc
cmpl %ebp, %eax
je 0x3ae3
pause
jmp 0x3ad5
movq 0x10(%rsp), %rax
movq (%rax,%r13,8), %rbx
movl $0x4, %ecx
movq %rbx, %rdi
xorl %esi, %esi
movq %r12, %rdx
callq 0x3744
movq 0xc7d3(%rip), %rax      # 0x102d8
movsd %xmm0, (%rax,%r14,8)
movl $0x4, %ecx
movq %rbx, %rdi
movl $0x1, %esi
movq %r12, %rdx
callq 0x3744
movq 0xc7b9(%rip), %rax      # 0x102e0
movsd %xmm0, (%rax,%r14,8)
movq 0x18(%rsp), %rdi
callq 0x2090
testl %r14d, %r14d
je 0x3b44
movq %r15, %rbx
jmp 0x3c81
movl $0x0, 0xc76e(%rip)      # 0x102bc
xorl %eax, %eax
cmpl $0x0, 0xc731(%rip)      # 0x10288
jne 0x3cb7
xorpd %xmm0, %xmm0
testq %rbp, %rbp
je 0x3bb8
movq 0xc76b(%rip), %rcx      # 0x102d8
movl %eax, %esi
xorl %ebx, %ebx
xorl %edx, %edx
testl %esi, %esi
jne 0x3b88
addsd (%rcx,%rbx,8), %xmm0
incq %rbx
movl %edx, %esi
cmpq %rbx, %rbp
jne 0x3b71
jmp 0x3bb8
movsd %xmm0, 0x8(%rsp)
movsd (%rcx,%rbx,8), %xmm0
leaq 0x678f(%rip), %rdi      # 0xa329
movb $0x1, %al
callq 0x2100
movsd 0x8(%rsp), %xmm0
movl 0xc6db(%rip), %eax      # 0x10288
movq 0xc724(%rip), %rcx      # 0x102d8
movl %eax, %edx
jmp 0x3b77
testl %eax, %eax
jne 0x3cd0
movq 0xc731(%rip), %rax      # 0x102f8
movq (%rax,%r15,8), %rax
movsd %xmm0, (%rax,%r13,8)
xorl %eax, %eax
xorpd %xmm0, %xmm0
testq %rbp, %rbp
je 0x3c2e
movq 0xc6fd(%rip), %rcx      # 0x102e0
movl %eax, %esi
xorl %ebx, %ebx
xorl %edx, %edx
testl %esi, %esi
jne 0x3bfe
addsd (%rcx,%rbx,8), %xmm0
incq %rbx
movl %edx, %esi
cmpq %rbx, %rbp
jne 0x3be7
jmp 0x3c2e
movsd %xmm0, 0x8(%rsp)
movsd (%rcx,%rbx,8), %xmm0
leaq 0x6719(%rip), %rdi      # 0xa329
movb $0x1, %al
callq 0x2100
movsd 0x8(%rsp), %xmm0
movl 0xc665(%rip), %eax      # 0x10288
movq 0xc6b6(%rip), %rcx      # 0x102e0
movl %eax, %edx
jmp 0x3bed
testl %eax, %eax
jne 0x3d21
movq 0xc6c3(%rip), %rax      # 0x10300
movq %r15, %rbx
movq (%rax,%r15,8), %rax
movsd %xmm0, (%rax,%r13,8)
movq 0x20(%rsp), %rax
incl %eax
movq %rax, 0x20(%rsp)
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
mulsd 0x30(%rsp), %xmm0
leaq 0x66e0(%rip), %rdi      # 0xa34b
movb $0x1, %al
callq 0x2100
movq 0xc34f(%rip), %rax      # 0xffc8
movq (%rax), %rdi
callq 0x21e0
incq %r13
movq 0x28(%rsp), %rdi
callq 0x8be5
cmpq %r13, %rax
ja 0x3a28
jmp 0x3d7f
testl %r14d, %r14d
movq 0x18(%rsp), %rbx
je 0x3d61
movq %rbx, %rdi
callq 0x2090
jmp 0x3ab2
leaq 0x665d(%rip), %rdi      # 0xa31b
xorl %eax, %eax
callq 0x2100
movl 0xc5bd(%rip), %eax      # 0x10288
jmp 0x3b5d
leaq 0x6659(%rip), %rdi      # 0xa330
movsd %xmm0, 0x8(%rsp)
movb $0x1, %al
callq 0x2100
movq 0xc60d(%rip), %rax      # 0x102f8
movq (%rax,%r15,8), %rax
cmpl $0x0, 0xc592(%rip)      # 0x10288
movsd 0x8(%rsp), %xmm0
movsd %xmm0, (%rax,%r13,8)
je 0x3bd1
leaq 0x662e(%rip), %rdi      # 0xa33d
xorl %eax, %eax
callq 0x2100
movl 0xc56c(%rip), %eax      # 0x10288
jmp 0x3bd3
leaq 0x6608(%rip), %rdi      # 0xa330
movsd %xmm0, 0x8(%rsp)
movb $0x1, %al
callq 0x2100
movq 0xc5c4(%rip), %rax      # 0x10300
movq %r15, %rbx
movq (%rax,%r15,8), %rax
cmpl $0x0, 0xc53e(%rip)      # 0x10288
movsd 0x8(%rsp), %xmm0
movsd %xmm0, (%rax,%r13,8)
jne 0x3c81
jmp 0x3c4a
leaq 0x65a0(%rip), %rdi      # 0xa308
movl %r13d, %esi
xorl %eax, %eax
callq 0x2100
movq %rbx, %rdi
callq 0x2090
jmp 0x3a47
incq %rbx
movq 0x28(%rsp), %r13
movq %r13, %rdi
callq 0x8be5
cmpq %rbx, %rax
ja 0x39fa
jmp 0x3db8
testl %r14d, %r14d
jne 0x3a11
leaq 0x6545(%rip), %rdi      # 0xa2ef
movl %ebx, %esi
xorl %eax, %eax
callq 0x2100
jmp 0x3a11
movq %r13, %rdi
callq 0x8be5
testq %rax, %rax
movq 0x10(%rsp), %r15
je 0x3dec
xorl %ebx, %ebx
movq (%r15,%rbx,8), %rdi
movq 0xc449(%rip), %rsi      # 0x10220
callq 0x20c0
incq %rbx
movq %r13, %rdi
callq 0x8be5
cmpq %rbx, %rax
ja 0x3dcc
movq %r15, %rdi
callq 0x2030
testl %r14d, %r14d
je 0x3e0a
xorl %eax, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x2746
jmp 0x3df9
leaq 0x8530(%rip), %rdi      # 0xc348
leaq 0x6ce0(%rip), %rsi      # 0xaaff
leaq 0x6cf2(%rip), %rcx      # 0xab18
movl $0x59, %edx
callq 0x2110