// File: /workspace/github_c_makefile_star2_O2/LPD-EPFL[P]mctop/src/mctop.c
// Function: crawl
void*
crawl(void* param)
{
  tld_t* tld = (tld_t*) param;
  const int tid = tld->id;
  pthread_barrier_t* barrier_sleep = tld->barrier;
  barrier2_t* barrier2 = tld->barrier2;
  
  const double test_completion_perc_step = 100.0 / test_num_hw_ctx;
  double test_completion_perc = 0;
  double test_completion_time = 0;

  const uint _num_reps = test_num_reps; /* local copy */
  const uint _num_warmup_reps = test_num_warmup_reps; /* local copy */
  const uint _test_cl_size = test_num_cache_lines * sizeof(cache_line_t);
  const uint _num_sockets = test_num_sockets;
  mctop_test_mem_type_t _do_mem = test_do_mem;
  uint _mem_on_demand = test_mem_on_demand;
  const uint _num_hw_ctx = test_num_hw_ctx;
  const uint _verbose = test_verbose;
  const int _do_dvfs = test_dvfs;
  int max_stdev = test_max_stdev;
  uint n_retries = 0;

  mctop_prof_t* profiler = mctop_prof_create(_num_reps);
  mctop_prof_stats_t* stats = malloc_assert(sizeof(mctop_prof_stats_t));

  volatile size_t sum = 0;
  int node_local = -1;
  for (int x = 0; x < _num_hw_ctx; x++)
    {
      clock_t _clock_start = clock();
      if (tid == 0)
	{
	  mctop_set_cpu(NULL, x); 
	  if (_do_dvfs)
	    {
	      dvfs_scale_up(test_num_dvfs_reps, test_dvfs_ratio, NULL);
	    }

	  /* mem. latency measurements */
	  node_local = -1;
	  if (unlikely(_do_mem == ON_TIME))
	    {
	      volatile ticks mem_lats[_num_sockets];
	      for (int n = 0; n < _num_sockets; n++)
		{
		  volatile uint64_t* l = node_mem[n];
		  volatile uint64_t* mem = NULL;
		  if (unlikely(_mem_on_demand))
		    {
		      mem = numa_alloc_onnode(test_mem_size, n);
		      ll_random_create(mem, test_mem_size);
		      l = mem;
		    }
		  mem_lats[n] = ll_random_traverse(l, test_mem_reps);
		  if (unlikely(_mem_on_demand))
		    {
		      numa_free((void*) mem, test_mem_size);
		    }
		}
	      ticks mem_lat_min = -1;
	      for (int n = 0; n < _num_sockets; n++)
		{
		  if (mem_lats[n] < mem_lat_min)
		    {
		      mem_lat_min = mem_lats[n];
		      node_local = n;
		    }
		  mem_lat_table[x][n] = mem_lats[n];
		}
	      numa_set_preferred(mem_lat_min);
	    }
	  cache_lines_destroy(test_cache_line, _test_cl_size, _do_mem == ON_TIME);
	  test_cache_line = cache_lines_create(_test_cl_size, node_local);
	}

      pthread_barrier_wait(barrier_sleep);
      volatile cache_line_t* cache_line = test_cache_line;

      size_t history_med[2] = { 0 };
      for (int y = x + 1; y < _num_hw_ctx; y++)
	{
	  ID1_DO(
		 mctop_set_cpu(NULL, y);
		 if (_do_dvfs)
		   {
		     dvfs_scale_up(test_num_dvfs_reps, test_dvfs_ratio, NULL);
		   }
		 );

	  hw_warmup(cache_line, _num_warmup_reps, barrier2, tid, profiler);

	  for (size_t rep = 0; rep < _num_reps; rep++)
	    {
	      barrier2_cross_explicit(barrier2, tid, 5);

	      if (likely(tid == 0))
		{
		  barrier2_cross(barrier2, tid, rep);
		  sum += ATOMIC_OP(cache_line, rep, profiler);
		}
	      else
		{
		  sum += ATOMIC_OP(cache_line, rep, profiler);
		  barrier2_cross(barrier2, tid, rep);
		}
	    }

	  mctop_prof_stats_calc(profiler, stats);
	  double stdev = stats->std_dev_perc;
	  int64_t median = stats->median;
	  if (likely(tid == 0))
	    {
	      if (unlikely(median < 0))
		{
		  high_stdev_retry = 1;
		  cache_lines_destroy(test_cache_line, _test_cl_size, _do_mem == ON_TIME);
		  test_cache_line = cache_lines_create(_test_cl_size, node_local);
		  if (n_retries == 100)
		    {
		      printf("100 retries!\n");
		      sleep(1);
		      /* for (uint i = 0; i < _num_reps; i++) */
		      /* 	{ */
		      /* 	  printf("%zd \n", profiler->latencies[i]); */
		      /* 	} */
		      /* printf("\n"); */

		      /* exit(-1); */
		    }
		}
	      else
		{
		  if (stdev > max_stdev && (history_med[0] != median || history_med[1] != median))
		    {
		      high_stdev_retry = 1;
		      cache_lines_destroy(test_cache_line, _test_cl_size, _do_mem == ON_TIME);
		      test_cache_line = cache_lines_create(_test_cl_size, node_local);
		    }

		  lat_table_2d_set(lat_table, _num_hw_ctx, x, y, median);
		  history_med[0] = history_med[1];
		  history_med[1] = median;
		}

	      if (unlikely(_verbose))
		{
		  printf(" [%02d->%02d] median %-4zd with stdv %-7.2f%% | limit %2d%% %s\n",
			 x, y, median, stdev, max_stdev,  high_stdev_retry ? "(high)" : "");
		}
	    }
	  else
	    {
	      lat_table_2d_set(lat_table, _num_hw_ctx, y, x, median);
	    }

	  barrier2_cross_explicit(barrier2, tid, 6);

	  if (unlikely(high_stdev_retry))
	    {
	      barrier2_cross_explicit(barrier2, tid, 7);
	      if (++max_stdev > test_max_stdev_max)
		{
		  max_stdev = test_max_stdev_max;
		}
	      high_stdev_retry = 0;
	      y--;
	      n_retries++;
	    }
	  else
	    {
	      max_stdev = test_max_stdev;
	      history_med[0] = history_med[1] = 0;
	      n_retries = 0;
	    }
	}

      if (tid == 0)
	{
	  clock_t _clock_stop = clock();
	  double sec = (_clock_stop - _clock_start) / (double) CLOCKS_PER_SEC;
	  test_completion_time += sec;
	  test_completion_perc += test_completion_perc_step;
	  NOT_VERBOSE(printf("\r# Progress : %6.1f%% completed in %8.1f secs (step took %7.1f secs)",
			     test_completion_perc, test_completion_time, sec);
		      fflush(stdout);
		      );
	  assert(sum != 0);
	}
    }

  if (tid == 0)
    {
      printf("\n");
      cache_lines_destroy(test_cache_line, _test_cl_size, _do_mem == ON_TIME);
      for (int x = 0; x < _num_hw_ctx; x++)
	{
	  for (int y = x + 1; y < _num_hw_ctx; y++)
	    {
	      ticks xy = lat_table_2d_get(lat_table, _num_hw_ctx, x, y);
	      lat_table_2d_set(lat_table, _num_hw_ctx, y, x, xy);
	    }
	}
    }

  mctop_prof_free(profiler);
  free(stats);
  return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movl (%rdi), %r12d
movq 0x18(%rdi), %rax
movq %rax, -0xe0(%rbp)
movq 0x10(%rdi), %r15
movl 0xde68(%rip), %eax      # 0x102c0
movq %rax, -0x60(%rbp)
cvtsi2sd %eax, %xmm0
movsd 0x7ba0(%rip), %xmm1     # 0xa008
divsd %xmm0, %xmm1
movsd %xmm1, -0xd0(%rbp)
movl 0xdd76(%rip), %edi      # 0x101f0
movl 0xde0f(%rip), %r14d     # 0x10290
movl 0xdd81(%rip), %eax      # 0x10208
shll $0x6, %eax
movq %rax, -0x50(%rbp)
movl 0xdd94(%rip), %eax      # 0x10228
movq %rax, -0xb8(%rbp)
movl 0xdd7a(%rip), %r13d     # 0x1021c
movl 0xde00(%rip), %eax      # 0x102a8
movl %eax, -0x74(%rbp)
movl 0xddd7(%rip), %eax      # 0x10288
movl %eax, -0xb0(%rbp)
movl 0xddcf(%rip), %eax      # 0x1028c
movl %eax, -0x78(%rbp)
movl 0xdd3a(%rip), %eax      # 0x10200
movq %rax, -0x68(%rbp)
movq %rdi, -0x108(%rbp)
callq 0x5194
movq %rax, %rbx
pushq $0x28
popq %rdi
callq 0x2b8e
movq %rax, -0xc8(%rbp)
movq $0x0, -0xa8(%rbp)
xorl %eax, %eax
movl %r13d, -0xac(%rbp)
cmpl $0x1, %r13d
movq -0x60(%rbp), %r13
sete %al
movl %eax, -0x30(%rbp)
incq %r14
movq %r14, -0x100(%rbp)
movslq %r13d, %rax
movq %rax, -0xc0(%rbp)
xorpd %xmm1, %xmm1
xorl %ecx, %ecx
pushq $-0x1
popq %r14
xorpd %xmm0, %xmm0
movl $0x0, -0x34(%rbp)
movq %rcx, %rax
movsd %xmm1, -0x88(%rbp)
movsd %xmm0, -0x80(%rbp)
cmpq %r13, %rax
je 0x2aeb
movq %rax, -0x58(%rbp)
callq 0x20d0
movq %rax, -0xd8(%rbp)
testl %r12d, %r12d
jne 0x25c7
xorl %edi, %edi
movq -0x58(%rbp), %rsi
callq 0x841d
cmpl $0x0, -0x78(%rbp)
je 0x2586
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0x7a91(%rip), %xmm0     # 0xa010
xorl %esi, %esi
callq 0x5684
pushq $-0x1
popq %r14
cmpl $0x1, -0xac(%rbp)
je 0x2949
movl %r14d, -0x2c(%rbp)
movq 0xdd0e(%rip), %rdi      # 0x102b0
movq -0x50(%rbp), %r14
movq %r14, %rsi
movl -0x30(%rbp), %edx
callq 0x2bb8
movq %r14, %rdi
movl -0x2c(%rbp), %r14d
movl %r14d, %esi
callq 0x5140
movq %rax, 0xdce9(%rip)      # 0x102b0
movl %r14d, -0x2c(%rbp)
movq -0xe0(%rbp), %rdi
callq 0x2090
movq 0xdcd2(%rip), %r14      # 0x102b0
movq -0x58(%rbp), %rax
leaq 0x1(%rax), %rcx
imulq -0xc0(%rbp), %rax
shlq $0x3, %rax
movq %rax, -0xe8(%rbp)
movl %ecx, %edx
movq %rcx, -0xa0(%rbp)
movl %edx, %eax
imull %r13d, %eax
addl -0x58(%rbp), %eax
cltq
movq %rax, -0xf0(%rbp)
movslq %edx, %rax
movq %rax, -0xf8(%rbp)
movq $0x0, -0x70(%rbp)
movq $0x0, -0x48(%rbp)
cmpl %r13d, %edx
jae 0x2934
movl %edx, -0x40(%rbp)
cmpl $0x1, %r12d
jne 0x2664
xorl %edi, %edi
movl -0x40(%rbp), %esi
callq 0x841d
cmpl $0x0, -0x78(%rbp)
je 0x2664
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0x79b3(%rip), %xmm0     # 0xa010
xorl %esi, %esi
callq 0x5684
xorl %r13d, %r13d
cmpq %r13, -0x100(%rbp)
je 0x26b3
testl %r12d, %r12d
je 0x2693
movq %r14, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x2bc2
movq %r15, %rdi
movl %r12d, %esi
movq %r13, %rdx
callq 0x5832
jmp 0x26ae
movq %r15, %rdi
xorl %esi, %esi
movq %r13, %rdx
callq 0x5832
movq %r14, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x2bc2
incq %r13
jmp 0x2667
xorl %r13d, %r13d
cmpq %r13, -0x108(%rbp)
je 0x271e
movq %r15, %rdi
movl %r12d, %esi
pushq $0x5
popq %rdx
callq 0x5857
testl %r12d, %r12d
jne 0x26f9
movq %r15, %rdi
xorl %esi, %esi
movq %r13, %rdx
callq 0x5832
movq %r14, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x2bc2
addq %rax, -0xa8(%rbp)
incq %r13
jmp 0x26b6
movq %r14, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x2bc2
addq %rax, -0xa8(%rbp)
movq %r15, %rdi
movl %r12d, %esi
movq %r13, %rdx
callq 0x5832
jmp 0x26f4
movq %rbx, %rdi
movq -0xc8(%rbp), %r13
movq %r13, %rsi
callq 0x529a
movq 0x8(%r13), %r8
testl %r12d, %r12d
jne 0x2853
movsd 0x20(%r13), %xmm0
testq %r8, %r8
movq -0x60(%rbp), %r13
js 0x286b
cvtsi2sdl -0x68(%rbp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x27c2
movq -0x70(%rbp), %rcx
xorq %r8, %rcx
movq -0x48(%rbp), %rax
xorq %r8, %rax
orq %rcx, %rax
je 0x27c2
movl $0x1, 0xdb40(%rip)      # 0x102b8
movq 0xdb31(%rip), %rdi      # 0x102b0
movq -0x50(%rbp), %r13
movq %r13, %rsi
movl -0x30(%rbp), %edx
movq %r8, -0x98(%rbp)
movsd %xmm0, -0x90(%rbp)
callq 0x2bb8
movq %r13, %rdi
movq -0x60(%rbp), %r13
movl -0x2c(%rbp), %esi
callq 0x5140
movsd -0x90(%rbp), %xmm0
movq -0x98(%rbp), %r8
movq %rax, 0xdaee(%rip)      # 0x102b0
movq 0xdacf(%rip), %rax      # 0x10298
addq -0xe8(%rbp), %rax
movq -0xf8(%rbp), %rcx
movq %r8, (%rax,%rcx,8)
movq -0x48(%rbp), %rax
movq %rax, -0x70(%rbp)
movq %r8, -0x48(%rbp)
cmpl $0x0, -0xb0(%rbp)
jne 0x28d8
movq %r15, %rdi
movl %r12d, %esi
pushq $0x6
popq %rdx
callq 0x5857
cmpl $0x0, 0xdaaf(%rip)      # 0x102b8
je 0x2912
movq %r15, %rdi
movl %r12d, %esi
pushq $0x7
popq %rdx
callq 0x5857
movq -0x68(%rbp), %rcx
incl %ecx
movslq %ecx, %rcx
movq 0xdaa3(%rip), %rax      # 0x102d0
cmpq %rcx, %rax
cmovbl %eax, %ecx
movq %rcx, -0x68(%rbp)
movl $0x0, 0xda77(%rip)      # 0x102b8
incl -0x34(%rbp)
movq -0xa0(%rbp), %rcx
movl -0x40(%rbp), %edx
jmp 0x262e
movq 0xda3e(%rip), %rax      # 0x10298
movq -0xf0(%rbp), %rcx
movq %r8, (%rax,%rcx,8)
movq -0x60(%rbp), %r13
jmp 0x27f4
movsd %xmm0, -0x90(%rbp)
movq %r8, -0x98(%rbp)
movl $0x1, 0xda34(%rip)      # 0x102b8
movq 0xda25(%rip), %rdi      # 0x102b0
movq -0x50(%rbp), %rsi
movl -0x30(%rbp), %edx
callq 0x2bb8
movq -0x50(%rbp), %rdi
movl -0x2c(%rbp), %esi
callq 0x5140
movq %rax, 0xda06(%rip)      # 0x102b0
cmpl $0x64, -0x34(%rbp)
jne 0x28c4
leaq 0x82a1(%rip), %rdi      # 0xab58
callq 0x2080
pushq $0x1
popq %rdi
callq 0x2310
movq -0x98(%rbp), %r8
movsd -0x90(%rbp), %xmm0
jmp 0x27e7
cmpl $0x0, 0xd9d9(%rip)      # 0x102b8
leaq 0x78e6(%rip), %r9       # 0xa1cc
leaq 0x79b9(%rip), %rax      # 0xa2a6
cmoveq %rax, %r9
leaq 0x7894(%rip), %rdi      # 0xa18c
movq -0x58(%rbp), %rsi
movl -0x40(%rbp), %edx
movq %r8, %rcx
movq -0x68(%rbp), %r8
movb $0x1, %al
callq 0x2100
jmp 0x27f4
movl 0xd8e8(%rip), %eax      # 0x10200
movq %rax, -0x68(%rbp)
movl -0x40(%rbp), %edx
incl %edx
movl $0x0, -0x34(%rbp)
movq -0xa0(%rbp), %rcx
jmp 0x2602
movq %rcx, %rax
testl %r12d, %r12d
movl -0x2c(%rbp), %r14d
jne 0x2543
jmp 0x2a38
movq %rsp, -0x40(%rbp)
movq %rsp, %r10
movq -0xb8(%rbp), %r8
leaq 0xf(,%r8,8), %rax
andq $-0x10, %rax
subq %rax, %r10
movq %r10, %rsp
xorl %r14d, %r14d
movq %r10, -0x48(%rbp)
cmpq %r14, %r8
je 0x29f0
cmpl $0x0, -0x74(%rbp)
jne 0x29b9
movq 0xd946(%rip), %rax      # 0x102c8
movq (%rax,%r14,8), %r13
movq $0x0, -0x70(%rbp)
movl $0xf4240, %esi          # imm = 0xF4240
movq %r13, %rdi
callq 0x54f1
movq -0x48(%rbp), %r10
movq %rax, (%r10,%r14,8)
cmpl $0x0, -0x74(%rbp)
jne 0x29dc
incq %r14
movq -0x60(%rbp), %r13
movq -0xb8(%rbp), %r8
jmp 0x2970
movl $0x20000000, %edi       # imm = 0x20000000
movl %r14d, %esi
callq 0x21f0
movq %rax, %r13
movl $0x20000000, %esi       # imm = 0x20000000
movq %rax, %rdi
callq 0x5559
movq %r13, -0x70(%rbp)
jmp 0x298e
movl $0x20000000, %esi       # imm = 0x20000000
movq -0x70(%rbp), %rdi
callq 0x20c0
movq -0x48(%rbp), %r10
jmp 0x29a9
movq 0xd8a9(%rip), %rax      # 0x102a0
xorl %ecx, %ecx
pushq $-0x1
popq %rdi
pushq $-0x1
popq %r14
movq -0x58(%rbp), %r9
cmpq %rcx, %r8
je 0x2a2a
movq (%r10,%rcx,8), %rdx
cmpq %rdi, %rdx
jae 0x2a19
movq (%r10,%rcx,8), %rdi
movl %ecx, %r14d
movq (%r10,%rcx,8), %rdx
movq (%rax,%r9,8), %rsi
movq %rdx, (%rsi,%rcx,8)
incq %rcx
jmp 0x2a04
callq 0x22a0
movq -0x40(%rbp), %rsp
jmp 0x2597
callq 0x20d0
movsd -0x80(%rbp), %xmm0
movsd -0x88(%rbp), %xmm1
subq -0xd8(%rbp), %rax
cvtsi2sd %rax, %xmm2
divsd 0x75ba(%rip), %xmm2     # 0xa018
addsd %xmm2, %xmm1
addsd -0xd0(%rbp), %xmm0
cmpl $0x0, 0xd817(%rip)      # 0x10288
jne 0x2ab7
leaq 0x7759(%rip), %rdi      # 0xa1d3
movsd %xmm0, -0x80(%rbp)
movsd -0x80(%rbp), %xmm0
movsd %xmm1, -0x88(%rbp)
movsd -0x88(%rbp), %xmm1
movb $0x3, %al
callq 0x2100
movq 0xd526(%rip), %rax      # 0xffc8
movq (%rax), %rdi
callq 0x21e0
movsd -0x80(%rbp), %xmm0
movsd -0x88(%rbp), %xmm1
cmpq $0x0, -0xa8(%rbp)
movq -0xa0(%rbp), %rcx
jne 0x2533
leaq 0x7745(%rip), %rdi      # 0xa218
leaq 0x7747(%rip), %rsi      # 0xa221
leaq 0x774c(%rip), %rcx      # 0xa22d
movl $0x140, %edx            # imm = 0x140
callq 0x2110
testl %r12d, %r12d
movq -0xc0(%rbp), %r14
pushq $0x1
popq %r15
je 0x2b20
movq %rbx, %rdi
callq 0x5295
movq -0xc8(%rbp), %rdi
callq 0x2030
xorl %eax, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0xa
popq %rdi
callq 0x2040
movq 0xd781(%rip), %rdi      # 0x102b0
movq -0x50(%rbp), %rsi
movl -0x30(%rbp), %edx
callq 0x2bb8
shlq $0x3, %r14
xorl %eax, %eax
xorl %ecx, %ecx
xorl %edx, %edx
cmpq %r13, %rdx
je 0x2afb
movslq %r15d, %rsi
leaq (%rcx,%rsi,8), %rdi
imulq %r14, %rsi
addq %rax, %rsi
movq 0xd739(%rip), %r8       # 0x10298
addq %r8, %rdi
addq %r8, %rsi
movl %r15d, %r8d
cmpl %r8d, %r13d
jbe 0x2b7f
movq (%rdi), %r9
movq %r9, (%rsi)
addq $0x8, %rdi
addq %r14, %rsi
incl %r8d
jmp 0x2b68
incq %rdx
incl %r15d
addq %r14, %rcx
addq $0x8, %rax
jmp 0x2b45