// File: /workspace/github_c_makefile_star2_O3/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), %r13d
movq 0x18(%rdi), %rax
movq %rax, -0x100(%rbp)
movq 0x10(%rdi), %r14
movslq 0xd737(%rip), %r12      # 0x102c0
movl 0xd661(%rip), %edi      # 0x101f0
movl 0xd6fb(%rip), %eax      # 0x10290
movq %rax, -0xe8(%rbp)
movl 0xd666(%rip), %ebx      # 0x10208
movl 0xd680(%rip), %eax      # 0x10228
movq %rax, -0x78(%rbp)
movl 0xd66a(%rip), %eax      # 0x1021c
movl %eax, -0x44(%rbp)
movl 0xd6ed(%rip), %eax      # 0x102a8
movl %eax, -0xbc(%rbp)
movl 0xd6c1(%rip), %eax      # 0x10288
movl %eax, -0xc4(%rbp)
movl 0xd6b9(%rip), %eax      # 0x1028c
movl %eax, -0x9c(%rbp)
movq 0xd620(%rip), %rax      # 0x10200
movq %rax, -0x90(%rbp)
movq %rdi, -0xe0(%rbp)
callq 0x58a8
movq %rax, %r15
movl $0x28, %edi
callq 0x21d0
movq %rax, -0xd0(%rbp)
testq %rax, %rax
je 0x337b
movl %r12d, %eax
movq %rax, -0x88(%rbp)
shll $0x6, %ebx
movq $0x0, -0xb8(%rbp)
testl %r12d, %r12d
je 0x3317
cvtsi2sd %r12d, %xmm0
movsd 0x73ca(%rip), %xmm1     # 0xa008
divsd %xmm0, %xmm1
movsd %xmm1, -0xf8(%rbp)
xorl %eax, %eax
cmpl $0x1, -0x44(%rbp)
sete %al
movl %eax, -0x48(%rbp)
movl %ebx, %eax
movq %rax, -0x80(%rbp)
incq -0xe8(%rbp)
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
movq $0x0, -0x58(%rbp)
xorpd %xmm0, %xmm0
movq -0x78(%rbp), %rax
leaq 0xf(,%rax,8), %rax
andq $-0x10, %rax
movq %rax, -0xf0(%rbp)
xorpd %xmm1, %xmm1
movl $0x0, -0x4c(%rbp)
movl %ebx, -0xc0(%rbp)
movq %r12, -0xb0(%rbp)
movsd %xmm1, -0x60(%rbp)
movsd %xmm0, -0x68(%rbp)
callq 0x20d0
movq %rax, -0x108(%rbp)
testl %r13d, %r13d
jne 0x2d27
xorl %edi, %edi
movq -0x58(%rbp), %rsi
callq 0x2998
cmpl $0x0, -0x9c(%rbp)
je 0x2ce8
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0x732f(%rip), %xmm0     # 0xa010
xorl %esi, %esi
callq 0x5dbd
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
cmpl $0x1, -0x44(%rbp)
je 0x3230
movq 0xd5b0(%rip), %rdi      # 0x102b0
testq %rdi, %rdi
movq -0x80(%rbp), %rsi
je 0x2d15
movl -0x48(%rbp), %edx
callq 0x589a
movq -0x80(%rbp), %rsi
movq %rsi, %rdi
movl -0x2c(%rbp), %esi
callq 0x5854
movq %rax, 0xd589(%rip)      # 0x102b0
movq -0x100(%rbp), %rdi
callq 0x2090
movq -0x58(%rbp), %rax
leaq 0x1(%rax), %rcx
cmpq -0x88(%rbp), %rcx
movq %rcx, -0xd8(%rbp)
jae 0x3176
movq 0xd55a(%rip), %rbx      # 0x102b0
imulq %r12, %rax
shlq $0x3, %rax
movq %rax, -0x110(%rbp)
movl %ecx, %eax
movq $0x0, -0x70(%rbp)
movq $0x0, -0x98(%rbp)
movl %eax, -0x38(%rbp)
cmpl $0x1, %r13d
jne 0x2daa
xorl %edi, %edi
movl -0x38(%rbp), %esi
callq 0x2998
cmpl $0x0, -0x9c(%rbp)
je 0x2daa
movl $0x6acfc0, %edi         # imm = 0x6ACFC0
movsd 0x726d(%rip), %xmm0     # 0xa010
xorl %esi, %esi
callq 0x5dbd
xorl %r12d, %r12d
testl %r13d, %r13d
je 0x2e04
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(%r15), %rsi
subq %rsi, %rcx
addq %rdx, %rcx
movq %rcx, 0x40(%r15,%r12,8)
movq -0x40(%rbp), %rax
movq %r14, %rdi
movl %r13d, %esi
movq %r12, %rdx
callq 0x5f6d
jmp 0x2e53
movq %r14, %rdi
xorl %esi, %esi
movq %r12, %rdx
callq 0x5f6d
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(%r15), %rsi
subq %rsi, %rcx
addq %rdx, %rcx
movq %rcx, 0x40(%r15,%r12,8)
movq -0x40(%rbp), %rax
incq %r12
cmpq %r12, -0xe8(%rbp)
jne 0x2dad
cmpq $0x0, -0xe0(%rbp)
je 0x2f46
xorl %r12d, %r12d
movl $0x5, %edx
movq %r14, %rdi
movl %r13d, %esi
callq 0x5f92
testl %r13d, %r13d
jne 0x2eed
movq %r14, %rdi
xorl %esi, %esi
movq %r12, %rdx
callq 0x5f6d
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(%r15), %rsi
subq %rsi, %rcx
addq %rdx, %rcx
movq %rcx, 0x40(%r15,%r12,8)
movq -0x40(%rbp), %rax
addq %rax, -0xb8(%rbp)
incq %r12
cmpq %r12, -0xe0(%rbp)
jne 0x2e74
jmp 0x2f46
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(%r15), %rsi
subq %rsi, %rcx
addq %rdx, %rcx
movq %rcx, 0x40(%r15,%r12,8)
movq -0x40(%rbp), %rax
addq %rax, -0xb8(%rbp)
movq %r14, %rdi
movl %r13d, %esi
movq %r12, %rdx
callq 0x5f6d
jmp 0x2edf
movq %r15, %rdi
movq -0xd0(%rbp), %r12
movq %r12, %rsi
callq 0x59b5
movq %r12, %rax
movq 0x8(%r12), %r12
testl %r13d, %r13d
jne 0x306b
movsd 0x20(%rax), %xmm0
testq %r12, %r12
movl -0x38(%rbp), %eax
js 0x30d0
xorps %xmm1, %xmm1
cvtsi2sdl -0x90(%rbp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x2fa2
cmpq %r12, -0x98(%rbp)
jne 0x3044
cmpq %r12, -0x70(%rbp)
jne 0x3044
cltq
movq 0xd2ed(%rip), %rcx      # 0x10298
addq -0x110(%rbp), %rcx
movq %r12, (%rcx,%rax,8)
movq -0x70(%rbp), %rax
movq %rax, -0x98(%rbp)
movq %r12, -0x70(%rbp)
cmpl $0x0, -0xc4(%rbp)
jne 0x3139
movq -0xb0(%rbp), %r12
movl $0x6, %edx
movq %r14, %rdi
movl %r13d, %esi
callq 0x5f92
cmpl $0x0, 0xd2c8(%rip)      # 0x102b8
jne 0x308b
movl 0xd204(%rip), %eax      # 0x10200
movq %rax, -0x90(%rbp)
movl -0x38(%rbp), %eax
incl %eax
movq $0x0, -0x98(%rbp)
movq $0x0, -0x70(%rbp)
movl $0x0, -0x4c(%rbp)
cmpl -0x88(%rbp), %eax
movsd -0x68(%rbp), %xmm0
movsd -0x60(%rbp), %xmm1
movq -0xd8(%rbp), %rcx
jb 0x2d7a
jmp 0x3180
movq -0x80(%rbp), %rdi
movl -0x48(%rbp), %esi
movl -0x2c(%rbp), %edx
movsd %xmm0, -0xa8(%rbp)
callq 0x2664
movsd -0xa8(%rbp), %xmm0
movl -0x38(%rbp), %eax
jmp 0x2fa2
movq 0xd226(%rip), %rax      # 0x10298
movl -0x38(%rbp), %ecx
imull -0x88(%rbp), %ecx
addl -0x58(%rbp), %ecx
movslq %ecx, %rcx
movq %r12, (%rax,%rcx,8)
jmp 0x2fd2
movl $0x7, %edx
movq %r14, %rdi
movl %r13d, %esi
callq 0x5f92
movq -0x90(%rbp), %rcx
incl %ecx
movslq %ecx, %rcx
movq 0xd222(%rip), %rax      # 0x102d0
cmpq %rcx, %rax
cmovbl %eax, %ecx
movq %rcx, -0x90(%rbp)
movl $0x0, 0xd1f3(%rip)      # 0x102b8
incl -0x4c(%rbp)
movl -0x38(%rbp), %eax
jmp 0x3022
movsd %xmm0, -0xa8(%rbp)
movl $0x1, 0xd1d6(%rip)      # 0x102b8
movq 0xd1c7(%rip), %rdi      # 0x102b0
testq %rdi, %rdi
movq -0x80(%rbp), %rsi
je 0x30fe
movl -0x48(%rbp), %edx
callq 0x589a
movq -0x80(%rbp), %rsi
movq %rsi, %rdi
movl -0x2c(%rbp), %esi
callq 0x5854
movq %rax, 0xd1a0(%rip)      # 0x102b0
cmpl $0x64, -0x4c(%rbp)
jne 0x312c
leaq 0x7a3b(%rip), %rdi      # 0xab58
callq 0x2080
movl $0x1, %edi
callq 0x2310
movsd -0xa8(%rbp), %xmm0
jmp 0x2fc5
cmpl $0x0, 0xd178(%rip)      # 0x102b8
leaq 0x7085(%rip), %r9       # 0xa1cc
leaq 0x7158(%rip), %rax      # 0xa2a6
cmoveq %rax, %r9
leaq 0x7033(%rip), %rdi      # 0xa18c
movq -0x58(%rbp), %rsi
movl -0x38(%rbp), %edx
movq %r12, %rcx
movq -0x90(%rbp), %r8
movb $0x1, %al
callq 0x2100
jmp 0x2fd2
movsd -0x68(%rbp), %xmm0
movsd -0x60(%rbp), %xmm1
testl %r13d, %r13d
movl -0xc0(%rbp), %ebx
jne 0x321a
callq 0x20d0
movsd -0x60(%rbp), %xmm1
movsd -0x68(%rbp), %xmm0
subq -0x108(%rbp), %rax
xorps %xmm2, %xmm2
cvtsi2sd %rax, %xmm2
divsd 0x6e63(%rip), %xmm2     # 0xa018
addsd %xmm2, %xmm1
addsd -0xf8(%rbp), %xmm0
cmpl $0x0, 0xd0c0(%rip)      # 0x10288
jne 0x3205
leaq 0x7002(%rip), %rdi      # 0xa1d3
movsd %xmm0, -0x68(%rbp)
movsd -0x68(%rbp), %xmm0
movsd %xmm1, -0x60(%rbp)
movsd -0x60(%rbp), %xmm1
movb $0x3, %al
callq 0x2100
movq 0xcdd5(%rip), %rax      # 0xffc8
movq (%rax), %rdi
callq 0x21e0
movsd -0x60(%rbp), %xmm1
movsd -0x68(%rbp), %xmm0
cmpq $0x0, -0xb8(%rbp)
movq -0xd8(%rbp), %rcx
je 0x335c
movq %rcx, -0x58(%rbp)
cmpq -0x88(%rbp), %rcx
jne 0x2ca5
jmp 0x3317
movq %rsp, -0x70(%rbp)
movq %rsp, %rbx
subq -0xf0(%rbp), %rbx
movq %rbx, %rsp
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rax, -0x38(%rbp)
cmpl $0x0, -0x78(%rbp)
je 0x32fe
movq %rbx, -0x98(%rbp)
xorl %r12d, %r12d
cmpl $0x0, -0xbc(%rbp)
jne 0x328e
movq 0xd05a(%rip), %rax      # 0x102c8
movq (%rax,%r12,8), %rdi
movl $0xf4240, %esi          # imm = 0xF4240
callq 0x5c1c
movq %rax, (%rbx)
incq %r12
addq $0x8, %rbx
cmpq %r12, -0x78(%rbp)
jne 0x325e
jmp 0x329b
movq %r12, %rdi
movq %rbx, %rsi
callq 0x261c
jmp 0x327f
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
cmpl $0x0, -0x78(%rbp)
movq -0xb0(%rbp), %r12
je 0x3305
movq 0xcfea(%rip), %rax      # 0x102a0
movq -0x58(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq $-0x1, -0x38(%rbp)
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
xorl %ecx, %ecx
movq -0x98(%rbp), %rsi
movq (%rsi,%rcx,8), %rdx
cmpq -0x38(%rbp), %rdx
jae 0x32eb
movq (%rsi,%rcx,8), %rdx
movq %rdx, -0x38(%rbp)
movl %ecx, -0x2c(%rbp)
movq (%rsi,%rcx,8), %rdx
movq %rdx, (%rax,%rcx,8)
incq %rcx
cmpq %rcx, -0x78(%rbp)
jne 0x32d6
jmp 0x3305
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
movq -0x38(%rbp), %rdi
callq 0x22a0
movq -0x70(%rbp), %rsp
jmp 0x2cf9
testl %r13d, %r13d
je 0x3341
movq %r15, %rdi
callq 0x59b0
movq -0xd0(%rbp), %rdi
callq 0x2030
xorl %eax, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %edx, %edx
testl %r12d, %r12d
sete %dl
movl -0x44(%rbp), %edi
movl %ebx, %esi
movq -0x88(%rbp), %rcx
callq 0x26a6
jmp 0x331c
leaq 0x6eb5(%rip), %rdi      # 0xa218
leaq 0x6eb7(%rip), %rsi      # 0xa221
leaq 0x6ebc(%rip), %rcx      # 0xa22d
movl $0x140, %edx            # imm = 0x140
callq 0x2110
leaq 0x8fc6(%rip), %rdi      # 0xc348
leaq 0x7776(%rip), %rsi      # 0xaaff
leaq 0x7788(%rip), %rcx      # 0xab18
movl $0x59, %edx
callq 0x2110