// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x14(%rbp)
movq -0x10(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x28(%rbp)
movq 0x11a37(%rip), %rax     # 0x15200
shrq $0x3, %rax
movl %eax, -0x2c(%rbp)
movq -0x28(%rbp), %rdi
callq 0xbbf0
movq %rax, %rdi
shlq $0x3, %rdi
callq 0x2da0
movq %rax, -0x38(%rbp)
movl $0x0, -0x3c(%rbp)
movslq -0x3c(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0x28(%rbp), %rdi
callq 0xbbf0
movq %rax, %rcx
movq -0xa0(%rbp), %rax
cmpq %rcx, %rax
jae 0x3856
movq 0x119e6(%rip), %rdi     # 0x15200
movl -0x3c(%rbp), %esi
callq 0x21c0
movq %rax, %rdx
movq -0x38(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movq -0x38(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movq 0x119bc(%rip), %rdx     # 0x15200
xorl %esi, %esi
callq 0x20f0
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x37f0
cmpl $0x0, -0x14(%rbp)
jne 0x3886
movl -0x18(%rbp), %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0x2da0
movq %rax, 0x11a77(%rip)     # 0x152e8
movl -0x18(%rbp), %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0x2da0
movq %rax, 0x11a6a(%rip)     # 0x152f0
movq -0x28(%rbp), %rax
movl 0x18(%rax), %eax
imull %eax, %eax
cvtsi2sd %rax, %xmm1
movsd 0xb76b(%rip), %xmm0     # 0xf008
divsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movl $0x0, -0x4c(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x38f0
cmpl $0x0, 0x119de(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x38e1
leaq 0xbc3b(%rip), %rdi      # 0xf512
xorps %xmm0, %xmm0
movb $0x1, %al
callq 0x20d0
movq 0x116e8(%rip), %rax     # 0x14fd0
movq (%rax), %rdi
callq 0x21b0
movl $0x0, -0x50(%rbp)
movslq -0x50(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x28(%rbp), %rdi
callq 0xbbf0
movq %rax, %rcx
movq -0xa8(%rbp), %rax
cmpq %rcx, %rax
jae 0x3d99
movq -0x28(%rbp), %rdi
movl -0x50(%rbp), %esi
callq 0xc8e0
cmpl $0x0, 0x11967(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x395e
cmpl $0x0, -0x14(%rbp)
jne 0x395c
movl -0x50(%rbp), %esi
leaq 0xbb60(%rip), %rdi      # 0xf4b5
movb $0x0, %al
callq 0x20d0
jmp 0x395e
movl $0x0, -0x54(%rbp)
movslq -0x54(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x28(%rbp), %rdi
callq 0xbbf0
movq %rax, %rcx
movq -0xb0(%rbp), %rax
cmpq %rcx, %rax
jae 0x3d89
cmpl $0x0, 0x11905(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x39c0
cmpl $0x0, -0x14(%rbp)
jne 0x39be
movl -0x54(%rbp), %esi
leaq 0xbb17(%rip), %rdi      # 0xf4ce
movb $0x0, %al
callq 0x20d0
jmp 0x39c0
movq -0x20(%rbp), %rdi
callq 0x2060
cmpl $0x0, -0x14(%rbp)
jne 0x3a6a
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0xb630(%rip), %xmm0     # 0xf010
xorl %eax, %eax
movl %eax, %esi
callq 0x7160
movq -0x38(%rbp), %rax
movslq -0x54(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movl -0x2c(%rbp), %eax
movl %eax, %edx
xorl %esi, %esi
movl $0x4, %ecx
callq 0x3510
movsd %xmm0, -0x60(%rbp)
movsd -0x60(%rbp), %xmm0
movq 0x118e1(%rip), %rax     # 0x152f8
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x38(%rbp), %rax
movslq -0x54(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movl -0x2c(%rbp), %eax
movl %eax, %edx
movl $0x1, %esi
movl $0x4, %ecx
callq 0x3510
movsd %xmm0, -0x68(%rbp)
movsd -0x68(%rbp), %xmm0
movq 0x118a7(%rip), %rax     # 0x15300
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x20(%rbp), %rdi
callq 0x2060
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0xb590(%rip), %xmm0     # 0xf010
xorl %eax, %eax
movl %eax, %esi
callq 0x7160
movl -0x18(%rbp), %esi
leaq 0x11839(%rip), %rdi     # 0x152cc
callq 0x3e60
movq -0x38(%rbp), %rax
movslq -0x54(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movl -0x2c(%rbp), %eax
movl %eax, %edx
xorl %esi, %esi
movl $0x4, %ecx
callq 0x3510
movsd %xmm0, -0x70(%rbp)
movsd -0x70(%rbp), %xmm0
movq 0x11822(%rip), %rax     # 0x152e8
movslq -0x14(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x38(%rbp), %rax
movslq -0x54(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movl -0x2c(%rbp), %eax
movl %eax, %edx
movl $0x1, %esi
movl $0x4, %ecx
callq 0x3510
movsd %xmm0, -0x78(%rbp)
movsd -0x78(%rbp), %xmm0
movq 0x117f0(%rip), %rax     # 0x152f0
movslq -0x14(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x20(%rbp), %rdi
callq 0x2060
cmpl $0x0, -0x14(%rbp)
jne 0x3d79
movl $0x0, 0x117a6(%rip)     # 0x152cc
xorps %xmm0, %xmm0
movsd %xmm0, -0x80(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x88(%rbp)
cmpl $0x0, 0x11758(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x3b62
leaq 0xb986(%rip), %rdi      # 0xf4e1
movb $0x0, %al
callq 0x20d0
movl $0x0, -0x8c(%rbp)
movl -0x8c(%rbp), %eax
cmpl -0x18(%rbp), %eax
jae 0x3be1
cmpl $0x0, 0x1171a(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x3bb3
movq 0x1174f(%rip), %rax     # 0x152e8
movslq -0x8c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
leaq 0xb943(%rip), %rdi      # 0xf4ef
movb $0x1, %al
callq 0x20d0
movq 0x1172e(%rip), %rax     # 0x152e8
movslq -0x8c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd -0x80(%rbp), %xmm0
movsd %xmm0, -0x80(%rbp)
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x3b6c
cmpl $0x0, 0x116b0(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x3c0f
movsd -0x80(%rbp), %xmm0
leaq 0xb8ee(%rip), %rdi      # 0xf4f6
movb $0x1, %al
callq 0x20d0
movsd -0x80(%rbp), %xmm0
movq 0x116ed(%rip), %rax     # 0x15308
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
cmpl $0x0, 0x11665(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x3c55
leaq 0xb8b5(%rip), %rdi      # 0xf503
movb $0x0, %al
callq 0x20d0
movl $0x0, -0x90(%rbp)
movl -0x90(%rbp), %eax
cmpl -0x18(%rbp), %eax
jae 0x3cda
cmpl $0x0, 0x11627(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x3ca6
movq 0x11664(%rip), %rax     # 0x152f0
movslq -0x90(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
leaq 0xb850(%rip), %rdi      # 0xf4ef
movb $0x1, %al
callq 0x20d0
movq 0x11643(%rip), %rax     # 0x152f0
movslq -0x90(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd -0x88(%rbp), %xmm0
movsd %xmm0, -0x88(%rbp)
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x3c5f
cmpl $0x0, 0x115b7(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x3d0b
movsd -0x88(%rbp), %xmm0
leaq 0xb7f2(%rip), %rdi      # 0xf4f6
movb $0x1, %al
callq 0x20d0
movsd -0x88(%rbp), %xmm0
movq 0x115f6(%rip), %rax     # 0x15310
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
cmpl $0x0, 0x11566(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x3d77
movl -0x4c(%rbp), %eax
incl %eax
movl %eax, -0x4c(%rbp)
cvtsi2sd %rax, %xmm0
mulsd -0x48(%rbp), %xmm0
leaq 0xb7b0(%rip), %rdi      # 0xf511
movb $0x1, %al
callq 0x20d0
movq 0x11261(%rip), %rax     # 0x14fd0
movq (%rax), %rdi
callq 0x21b0
jmp 0x3d79
jmp 0x3d7b
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x3965
jmp 0x3d8b
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x38f7
movl $0x0, -0x94(%rbp)
movslq -0x94(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0x28(%rbp), %rdi
callq 0xbbf0
movq %rax, %rcx
movq -0xb8(%rbp), %rax
cmpq %rcx, %rax
jae 0x3df5
movq -0x38(%rbp), %rax
movslq -0x94(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movq 0x11421(%rip), %rsi     # 0x15200
callq 0x2090
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0x3da3
movq -0x38(%rbp), %rdi
callq 0x2030
cmpl $0x0, -0x14(%rbp)
jne 0x3e47
cmpl $0x0, 0x1148d(%rip)     # 0x15298
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x3e2f
leaq 0xb643(%rip), %rdi      # 0xf46b
movb $0x0, %al
callq 0x20d0
movq 0x114b2(%rip), %rdi     # 0x152e8
callq 0x2030
movq 0x114ae(%rip), %rdi     # 0x152f0
callq 0x2030
xorl %eax, %eax
addq $0xc0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)