// File: /workspace/github_c_makefile_star2_O1/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), %r14d
movq 0x18(%rdi), %rax
movq %rax, -0x100(%rbp)
movq 0x10(%rdi), %r15
movslq 0xe757(%rip), %rbx      # 0x112c0
movl 0xe681(%rip), %edi      # 0x111f0
movl 0xe71b(%rip), %eax      # 0x11290
movq %rax, -0xe8(%rbp)
movl 0xe685(%rip), %r12d     # 0x11208
movl 0xe69f(%rip), %eax      # 0x11228
movq %rax, -0x80(%rbp)
movl 0xe689(%rip), %eax      # 0x1121c
movl %eax, -0x54(%rbp)
movl 0xe70c(%rip), %eax      # 0x112a8
movl %eax, -0x9c(%rbp)
movl 0xe6e0(%rip), %eax      # 0x11288
movl %eax, -0xcc(%rbp)
movl 0xe6d8(%rip), %eax      # 0x1128c
movl %eax, -0xa0(%rbp)
movq 0xe63f(%rip), %rax      # 0x11200
movq %rax, -0x90(%rbp)
movq %rdi, -0xe0(%rbp)
callq 0x58ac
movq %rax, %r13
movl $0x28, %edi
callq 0x21d0
movq %rax, -0xd8(%rbp)
testq %rax, %rax
je 0x339e
shll $0x6, %r12d
movq $0x0, -0xc8(%rbp)
testl %ebx, %ebx
je 0x3346
cvtsi2sd %ebx, %xmm0
movl %ebx, %eax
movq %rax, -0xb8(%rbp)
movsd 0x83eb(%rip), %xmm1     # 0xb008
divsd %xmm0, %xmm1
movsd %xmm1, -0xf8(%rbp)
xorl %eax, %eax
cmpl $0x1, -0x54(%rbp)
sete %al
movl %eax, -0x58(%rbp)
movl %r12d, %eax
movq %rax, -0x88(%rbp)
incq -0xe8(%rbp)
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
movq $0x0, -0x68(%rbp)
xorpd %xmm0, %xmm0
movq -0x80(%rbp), %rax
leaq 0xf(,%rax,8), %rax
andq $-0x10, %rax
movq %rax, -0xf0(%rbp)
xorpd %xmm1, %xmm1
movl $0x0, -0x5c(%rbp)
movq %rbx, -0xc0(%rbp)
movl %r12d, -0x44(%rbp)
movsd %xmm1, -0x70(%rbp)
movsd %xmm0, -0x78(%rbp)
callq 0x20d0
movq %rax, -0x108(%rbp)
testl %r14d, %r14d
jne 0x2d0e
xorl %edi, %edi
movq -0x68(%rbp), %rsi
callq 0x297a
cmpl $0x0, -0xa0(%rbp)
je 0x2cc9
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0x834e(%rip), %xmm0     # 0xb010
xorl %esi, %esi
callq 0x5e1d
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
cmpl $0x1, -0x54(%rbp)
je 0x322a
movq 0xe5cf(%rip), %rdi      # 0x112b0
testq %rdi, %rdi
movq -0x88(%rbp), %rsi
je 0x2cfc
movl -0x58(%rbp), %edx
callq 0x589e
movq -0x88(%rbp), %rsi
movq %rsi, %rdi
movl -0x2c(%rbp), %esi
callq 0x5858
movq %rax, 0xe5a2(%rip)      # 0x112b0
movq -0x100(%rbp), %rdi
callq 0x2090
movq -0x68(%rbp), %rax
leaq 0x1(%rax), %rcx
cmpq -0xb8(%rbp), %rcx
movq %rcx, -0xb0(%rbp)
jae 0x3167
movq 0xe573(%rip), %rbx      # 0x112b0
imulq -0xc0(%rbp), %rax
shlq $0x3, %rax
movq %rax, -0x110(%rbp)
movl %ecx, %eax
movq $0x0, -0x50(%rbp)
movq $0x0, -0x98(%rbp)
movl %eax, -0x38(%rbp)
cmpl $0x1, %r14d
jne 0x2d95
xorl %edi, %edi
movl -0x38(%rbp), %esi
callq 0x297a
cmpl $0x0, -0xa0(%rbp)
je 0x2d95
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0x8282(%rip), %xmm0     # 0xb010
xorl %esi, %esi
callq 0x5e1d
xorl %r12d, %r12d
testl %r14d, %r14d
je 0x2def
movq $0x0, -0x40(%rbp)
rdtsc
movl %edx, %ecx
movl %eax, %esi
negl %ecx
shlq $0x20, %rcx
xorl %eax, %eax
movl $0x1, %edx
lock
cmpxchgq %rdx, (%rbx)
movq %rax, -0x40(%rbp)
rdtsc
movl %eax, %eax
shlq $0x20, %rdx
addq %rax, %rdx
addq 0x8(%r13), %rsi
subq %rsi, %rcx
addq %rdx, %rcx
movq %rcx, 0x40(%r13,%r12,8)
movq -0x40(%rbp), %rax
movq %r15, %rdi
movl %r14d, %esi
movq %r12, %rdx
callq 0x5fcd
jmp 0x2e3e
movq %r15, %rdi
xorl %esi, %esi
movq %r12, %rdx
callq 0x5fcd
movq $0x0, -0x40(%rbp)
rdtsc
movl %edx, %ecx
movl %eax, %esi
negl %ecx
shlq $0x20, %rcx
xorl %eax, %eax
movl $0x1, %edx
lock
cmpxchgq %rdx, (%rbx)
movq %rax, -0x40(%rbp)
rdtsc
movl %eax, %eax
shlq $0x20, %rdx
addq %rax, %rdx
addq 0x8(%r13), %rsi
subq %rsi, %rcx
addq %rdx, %rcx
movq %rcx, 0x40(%r13,%r12,8)
movq -0x40(%rbp), %rax
incq %r12
cmpq %r12, -0xe8(%rbp)
jne 0x2d98
cmpq $0x0, -0xe0(%rbp)
je 0x2f31
xorl %r12d, %r12d
movl $0x5, %edx
movq %r15, %rdi
movl %r14d, %esi
callq 0x5ff2
testl %r14d, %r14d
jne 0x2ed8
movq %r15, %rdi
xorl %esi, %esi
movq %r12, %rdx
callq 0x5fcd
movq $0x0, -0x40(%rbp)
rdtsc
movl %edx, %ecx
movl %eax, %esi
negl %ecx
xorl %eax, %eax
movl $0x1, %edx
lock
cmpxchgq %rdx, (%rbx)
shlq $0x20, %rcx
movq %rax, -0x40(%rbp)
rdtsc
movl %eax, %eax
shlq $0x20, %rdx
addq %rax, %rdx
addq 0x8(%r13), %rsi
subq %rsi, %rcx
addq %rdx, %rcx
movq %rcx, 0x40(%r13,%r12,8)
movq -0x40(%rbp), %rax
addq %rax, -0xc8(%rbp)
incq %r12
cmpq %r12, -0xe0(%rbp)
jne 0x2e5f
jmp 0x2f31
movq $0x0, -0x40(%rbp)
rdtsc
movl %edx, %ecx
movl %eax, %esi
negl %ecx
xorl %eax, %eax
movl $0x1, %edx
lock
cmpxchgq %rdx, (%rbx)
shlq $0x20, %rcx
movq %rax, -0x40(%rbp)
rdtsc
movl %eax, %eax
shlq $0x20, %rdx
addq %rax, %rdx
addq 0x8(%r13), %rsi
subq %rsi, %rcx
addq %rdx, %rcx
movq %rcx, 0x40(%r13,%r12,8)
movq -0x40(%rbp), %rax
addq %rax, -0xc8(%rbp)
movq %r15, %rdi
movl %r14d, %esi
movq %r12, %rdx
callq 0x5fcd
jmp 0x2eca
movq %r13, %rdi
movq -0xd8(%rbp), %r12
movq %r12, %rsi
callq 0x59b9
movq %r12, %rax
movq 0x8(%r12), %r12
testl %r14d, %r14d
jne 0x3056
movsd 0x20(%rax), %xmm0
testq %r12, %r12
movl -0x38(%rbp), %eax
js 0x30bb
xorps %xmm1, %xmm1
cvtsi2sdl -0x90(%rbp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x2f8d
cmpq %r12, -0x98(%rbp)
jne 0x302c
cmpq %r12, -0x50(%rbp)
jne 0x302c
cltq
movq 0xe302(%rip), %rcx      # 0x11298
addq -0x110(%rbp), %rcx
movq %r12, (%rcx,%rax,8)
movq -0x50(%rbp), %rax
movq %rax, -0x98(%rbp)
movq %r12, -0x50(%rbp)
cmpl $0x0, -0xcc(%rbp)
jne 0x312a
movl -0x44(%rbp), %r12d
movl $0x6, %edx
movq %r15, %rdi
movl %r14d, %esi
callq 0x5ff2
cmpl $0x0, 0xe2e0(%rip)      # 0x112b8
jne 0x3076
movl 0xe21c(%rip), %eax      # 0x11200
movq %rax, -0x90(%rbp)
movl -0x38(%rbp), %eax
incl %eax
movq $0x0, -0x98(%rbp)
movq $0x0, -0x50(%rbp)
movl $0x0, -0x5c(%rbp)
cmpl -0xb8(%rbp), %eax
movsd -0x78(%rbp), %xmm0
movsd -0x70(%rbp), %xmm1
movq -0xb0(%rbp), %rcx
jb 0x2d65
jmp 0x3171
movq -0x88(%rbp), %rdi
movl -0x58(%rbp), %esi
movl -0x2c(%rbp), %edx
movsd %xmm0, -0xa8(%rbp)
callq 0x2627
movsd -0xa8(%rbp), %xmm0
movl -0x38(%rbp), %eax
jmp 0x2f8d
movq 0xe23b(%rip), %rax      # 0x11298
movl -0x38(%rbp), %ecx
imull -0xb8(%rbp), %ecx
addl -0x68(%rbp), %ecx
movslq %ecx, %rcx
movq %r12, (%rax,%rcx,8)
jmp 0x2fbd
movl $0x7, %edx
movq %r15, %rdi
movl %r14d, %esi
callq 0x5ff2
movq -0x90(%rbp), %rcx
incl %ecx
movslq %ecx, %rcx
movq 0xe237(%rip), %rax      # 0x112d0
cmpq %rcx, %rax
cmovbl %eax, %ecx
movq %rcx, -0x90(%rbp)
movl $0x0, 0xe208(%rip)      # 0x112b8
incl -0x5c(%rbp)
movl -0x38(%rbp), %eax
jmp 0x300a
movsd %xmm0, -0xa8(%rbp)
movl $0x1, 0xe1eb(%rip)      # 0x112b8
movq 0xe1dc(%rip), %rdi      # 0x112b0
testq %rdi, %rdi
movq -0x88(%rbp), %rsi
je 0x30ef
movl -0x58(%rbp), %edx
callq 0x589e
movq -0x88(%rbp), %rsi
movq %rsi, %rdi
movl -0x2c(%rbp), %esi
callq 0x5858
movq %rax, 0xe1af(%rip)      # 0x112b0
cmpl $0x64, -0x5c(%rbp)
jne 0x311d
leaq 0x8a4a(%rip), %rdi      # 0xbb58
callq 0x2080
movl $0x1, %edi
callq 0x2320
movsd -0xa8(%rbp), %xmm0
jmp 0x2fb0
cmpl $0x0, 0xe187(%rip)      # 0x112b8
leaq 0x8094(%rip), %r9       # 0xb1cc
leaq 0x8167(%rip), %rax      # 0xb2a6
cmoveq %rax, %r9
leaq 0x8042(%rip), %rdi      # 0xb18c
movq -0x68(%rbp), %rsi
movl -0x38(%rbp), %edx
movq %r12, %rcx
movq -0x90(%rbp), %r8
movb $0x1, %al
callq 0x2100
jmp 0x2fbd
movsd -0x78(%rbp), %xmm0
movsd -0x70(%rbp), %xmm1
testl %r14d, %r14d
je 0x3182
movq -0xc0(%rbp), %rbx
jmp 0x3214
callq 0x20d0
movsd -0x70(%rbp), %xmm1
movsd -0x78(%rbp), %xmm0
subq -0x108(%rbp), %rax
xorps %xmm2, %xmm2
cvtsi2sd %rax, %xmm2
divsd 0x7e70(%rip), %xmm2     # 0xb018
addsd %xmm2, %xmm1
addsd -0xf8(%rbp), %xmm0
cmpl $0x0, 0xe0cd(%rip)      # 0x11288
movq -0xc0(%rbp), %rbx
jne 0x31ff
leaq 0x8008(%rip), %rdi      # 0xb1d3
movsd %xmm0, -0x78(%rbp)
movsd -0x78(%rbp), %xmm0
movsd %xmm1, -0x70(%rbp)
movsd -0x70(%rbp), %xmm1
movb $0x3, %al
callq 0x2100
movq 0xdddb(%rip), %rax      # 0x10fc8
movq (%rax), %rdi
callq 0x21e0
movsd -0x70(%rbp), %xmm1
movsd -0x78(%rbp), %xmm0
cmpq $0x0, -0xc8(%rbp)
movq -0xb0(%rbp), %rcx
je 0x337f
movq %rcx, -0x68(%rbp)
cmpq -0xb8(%rbp), %rcx
jne 0x2c86
jmp 0x3346
movq %rsp, -0x98(%rbp)
movq %rsp, %rbx
subq -0xf0(%rbp), %rbx
movq %rbx, %rsp
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rax, -0x38(%rbp)
cmpl $0x0, -0x80(%rbp)
je 0x332a
xorl %r12d, %r12d
cmpl $0x0, -0x9c(%rbp)
jne 0x3292
movq 0xe064(%rip), %rax      # 0x112c8
movq (%rax,%r12,8), %rdi
movq $0x0, -0x50(%rbp)
movl $0xf4240, %esi          # imm = 0xF4240
callq 0x5c40
movq %rax, (%rbx,%r12,8)
cmpl $0x0, -0x9c(%rbp)
jne 0x32c0
incq %r12
cmpq %r12, -0x80(%rbp)
jne 0x3254
jmp 0x32d0
movl $0x20000000, %edi       # imm = 0x20000000
movl %r12d, %esi
callq 0x21f0
movq %rax, -0xb0(%rbp)
movl $0x20000000, %esi       # imm = 0x20000000
movq %rax, %rdi
callq 0x5cac
movq -0xb0(%rbp), %rdi
movq %rdi, -0x50(%rbp)
jmp 0x3270
movl $0x20000000, %esi       # imm = 0x20000000
movq -0x50(%rbp), %rdi
callq 0x20c0
jmp 0x3287
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
cmpq $0x0, -0x80(%rbp)
movl -0x44(%rbp), %r12d
je 0x3331
movq 0xdfb7(%rip), %rax      # 0x112a0
movq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq $-0x1, -0x38(%rbp)
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
xorl %ecx, %ecx
movq (%rbx,%rcx,8), %rdx
cmpq -0x38(%rbp), %rdx
jae 0x3317
movq (%rbx,%rcx,8), %rdx
movq %rdx, -0x38(%rbp)
movl %ecx, -0x2c(%rbp)
movq (%rbx,%rcx,8), %rdx
movq %rdx, (%rax,%rcx,8)
incq %rcx
cmpq %rcx, -0x80(%rbp)
jne 0x3302
jmp 0x3331
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
movq -0x38(%rbp), %rdi
callq 0x22a0
movq -0x98(%rbp), %rsp
jmp 0x2cda
testl %r14d, %r14d
je 0x3370
movq %r13, %rdi
callq 0x59b4
movq -0xd8(%rbp), %rdi
callq 0x2030
xorl %eax, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl -0x54(%rbp), %edi
movl %r12d, %esi
movl %ebx, %edx
callq 0x2669
jmp 0x334b
leaq 0x7e92(%rip), %rdi      # 0xb218
leaq 0x7e94(%rip), %rsi      # 0xb221
leaq 0x7e99(%rip), %rcx      # 0xb22d
movl $0x140, %edx            # imm = 0x140
callq 0x2110
leaq 0x9fa3(%rip), %rdi      # 0xd348
leaq 0x8753(%rip), %rsi      # 0xbaff
leaq 0x8765(%rip), %rcx      # 0xbb18
movl $0x59, %edx
callq 0x2110