// File: /workspace/github_c_makefile_star2_O0/google[P]multichase/fairness.c
// Function: main
int main(int argc, char **argv) {
  int c;
  int sweep_max = 1;
  size_t time_slice = 500000;
  char sep = ' ';
  size_t sample_size = 6;

  delay_mask = 0;
  while ((c = getopt(argc, argv, "d:n:s:t:S:")) != -1) {
    switch (c) {
      case 'd':
        delay_mask = strtoul(optarg, 0, 0);
        break;
      case 'n':
        sample_size =  strtof(optarg, 0);
        break;
      case 's':
        sweep_max = strtoul(optarg, 0, 0);
        break;
      case 't':
        time_slice = strtof(optarg, 0) * 1000000;
        break;
      case 'S':
        sep = *optarg;
        break;
      default:
        goto usage;
    }
  }

  if (argc - optind != 0) {
  usage:
    fprintf(
        stderr,
        "usage: %s \n"
        " [-d delay_mask]\n"
        " [-n sample_nr]\n"
        " [-s sweep_max]\n"
        " [-t time]\n"
        "By default runs one thread on each cpu, use taskset(1) to "
        "restrict operation to fewer cpus/threads.\n"
        "The optional delay_mask specifies a mask of cpus on which to delay "
        "the startup.\n"
        "The optional sample_nr determines the number of samples taken for "
        "each test point.\n"
        "The optional sweep_max causes testing across multiple different "
        "cache lines.\n"
        "The optional time determines how often to poll results (float in "
        "seconds).\n",
        argv[0]);
    exit(1);
  }

  setvbuf(stdout, NULL, _IONBF, BUFSIZ);

  // find the active cpus
  cpu_set_t cpus;
  if (sched_getaffinity(getpid(), sizeof(cpus), &cpus)) {
    perror("sched_getaffinity");
    exit(1);
  }

  // could do this more efficiently, but whatever
  size_t nr_threads = 0;
  int i;
  for (i = 0; i < CPU_SETSIZE; ++i) {
    if (CPU_ISSET(i, &cpus)) {
      ++nr_threads;
    }
  }

  per_thread_t *thread_args = calloc(nr_threads, sizeof(*thread_args));
  nr_to_startup = nr_threads + 1;
  size_t u;
  i = 0;
  for (u = 0; u < nr_threads; ++u) {
    while (!CPU_ISSET(i, &cpus)) {
      ++i;
    }
    thread_args[u].x.cpu = i;
    ++i;
    thread_args[u].x.count = 0;
    pthread_t dummy;
    if (pthread_create(&dummy, NULL, worker, &thread_args[u])) {
      perror("pthread_create");
      exit(1);
    }
  }

  wait_for_startup();

  atomic_t *samples = calloc(nr_threads, sizeof(*samples));

  printf(
      "results are avg latency per locked increment in ns, one column per "
      "thread\n");
  char *fmt, *tail = "";
  if (sep == ',') {
    printf("relaxed,sweep");
    fmt = ",cpu-%u";
    tail = ",avg,stdev,min,max";
  } else {
    fmt = "%6u  ";
    printf("cpu:");
  }
  for (u = 0; u < nr_threads; ++u) {
    printf(fmt, thread_args[u].x.cpu);
  }
  printf("%s\n", tail);
  global_counter.sweep_id = 0;
  for (relaxed = 0; relaxed < 2; ++relaxed) {
    if (sep != ',') printf(relaxed ? "relaxed:\n" : "unrelaxed:\n");
    for (int sweep = 0; sweep < sweep_max; sweep++) {
      global_counter.sweep_id = sweep;
      uint64_t last_stamp = now_nsec();
      size_t sample_nr;
      // The first sample is thrown out, so increment sample_size by 1 to get
      // the requested number of samples.
      for (sample_nr = 0; sample_nr < sample_size + 1; ++sample_nr) {
        double min = 1.0 / 0., max = 0.;
        usleep(time_slice);
        for (u = 0; u < nr_threads; ++u) {
          samples[u] = __sync_lock_test_and_set(&thread_args[u].x.count, 0);
        }
        uint64_t stamp = now_nsec();
        int64_t time_delta = stamp - last_stamp;
        last_stamp = stamp;

        // throw away the first sample to avoid race issues at startup / mode
        // switch
        if (sample_nr == 0) continue;
        if (sep == ',')
          printf("%d,%p", relaxed,
                 &(global_counter.x[global_counter.sweep_id].count));

        if (sep == ',') {
          fmt = ",%.1f";
        } else {
          fmt = "  %6.1f";
          printf("  ");
        }
        double sum = 0.;
        double sum_squared = 0.;
        for (u = 0; u < nr_threads; ++u) {
          double s = time_delta / (double)samples[u];
          printf(fmt, s);
          min = min < s ? min : s;
          max = max > s ? max : s;
          sum += s;
          sum_squared += s * s;
        }
        if (sep == ',') {
          fmt = ",%.1f,%.1f,%.1f,%.1f\n";
        } else {
          fmt = " : avg %6.1f  sdev %6.1f  min %6.1f  max %6.1f\n";
        }
        printf(fmt, sum / nr_threads,
               sqrt((sum_squared - sum * sum / nr_threads) / (nr_threads - 1)),
               min, max);
        fflush(stdout);
      }
    }
  }
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x190, %rsp            # imm = 0x190
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x1, -0x18(%rbp)
movq $0x7a120, -0x20(%rbp)   # imm = 0x7A120
movb $0x20, -0x21(%rbp)
movq $0x6, -0x30(%rbp)
movq $0x0, 0xecb71(%rip) # 0x4ee310
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0xb6913(%rip), %rdx     # 0x4b80c0
callq 0x463af0
movl %eax, -0x14(%rbp)
cmpl $-0x1, %eax
je 0x4018ca
movl -0x14(%rbp), %eax
addl $-0x53, %eax
movl %eax, %ecx
movq %rcx, -0x168(%rbp)
subl $0x21, %eax
ja 0x4018c3
movq -0x168(%rbp), %rax
leaq 0xb6854(%rip), %rcx     # 0x4b8038
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq $0x4f7360, %rax         # imm = 0x4F7360
movq (%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x40bec0
movq %rax, 0xecb07(%rip)     # 0x4ee310
jmp 0x4018c5
movq $0x4f7360, %rax         # imm = 0x4F7360
movq (%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x40c3d0
movaps %xmm0, %xmm1
cvttss2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movss 0xb67fc(%rip), %xmm1    # 0x4b8034
subss %xmm1, %xmm0
cvttss2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, -0x30(%rbp)
jmp 0x4018c5
movq $0x4f7360, %rax         # imm = 0x4F7360
movq (%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x40bec0
movl %eax, -0x18(%rbp)
jmp 0x4018c5
movq $0x4f7360, %rax         # imm = 0x4F7360
movq (%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x40c3d0
movss 0xb67ae(%rip), %xmm1    # 0x4b8030
mulss %xmm1, %xmm0
movaps %xmm0, %xmm1
cvttss2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movss 0xb6797(%rip), %xmm1    # 0x4b8034
subss %xmm1, %xmm0
cvttss2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, -0x20(%rbp)
jmp 0x4018c5
movq $0x4f7360, %rax         # imm = 0x4F7360
movq (%rax), %rax
movb (%rax), %al
movb %al, -0x21(%rbp)
jmp 0x4018c5
jmp 0x4018dd
jmp 0x40179f
movl -0x8(%rbp), %eax
movq $0x4ed0a0, %rcx         # imm = 0x4ED0A0
subl (%rcx), %eax
cmpl $0x0, %eax
je 0x401906
jmp 0x4018dd
movq $0x4ec708, %rax         # imm = 0x4EC708
movq (%rax), %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rdx
leaq 0xb67d6(%rip), %rsi     # 0x4b80cb
movb $0x0, %al
callq 0x410f60
movl $0x1, %edi
callq 0x40bbb0
movq $0x4ec710, %rax         # imm = 0x4EC710
movq (%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0x2, %edx
movl $0x2000, %ecx           # imm = 0x2000
callq 0x418040
callq 0x462420
movl %eax, %edi
movl $0x80, %esi
leaq -0xb0(%rbp), %rdx
callq 0x463cf0
cmpl $0x0, %eax
je 0x401956
leaq 0xb696b(%rip), %rdi     # 0x4b82b2
callq 0x411250
movl $0x1, %edi
callq 0x40bbb0
movq $0x0, -0xb8(%rbp)
movl $0x0, -0xbc(%rbp)
cmpl $0x400, -0xbc(%rbp)     # imm = 0x400
jge 0x401a23
movslq -0xbc(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
shrq $0x3, %rax
cmpq $0x80, %rax
jae 0x4019dc
movq -0xc8(%rbp), %rax
shrq $0x6, %rax
movq -0xb0(%rbp,%rax,8), %rax
movq -0xc8(%rbp), %rcx
andq $0x3f, %rcx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
setne %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x16c(%rbp)
jmp 0x4019e6
xorl %eax, %eax
movl %eax, -0x16c(%rbp)
jmp 0x4019e6
movl -0x16c(%rbp), %eax
movl %eax, -0xcc(%rbp)
cmpl $0x0, -0xcc(%rbp)
je 0x401a0d
movq -0xb8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb8(%rbp)
jmp 0x401a0f
movl -0xbc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xbc(%rbp)
jmp 0x40196b
movq -0xb8(%rbp), %rdi
movl $0x400, %esi            # imm = 0x400
callq 0x42c0b0
movq %rax, -0xd8(%rbp)
movq -0xb8(%rbp), %rax
addq $0x1, %rax
movq %rax, 0xec8cb(%rip)     # 0x4ee318
movl $0x0, -0xbc(%rbp)
movq $0x0, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
cmpq -0xb8(%rbp), %rax
jae 0x401bbd
jmp 0x401a78
movslq -0xbc(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rax
shrq $0x3, %rax
cmpq $0x80, %rax
jae 0x401ad9
movq -0xe8(%rbp), %rax
shrq $0x6, %rax
movq -0xb0(%rbp,%rax,8), %rax
movq -0xe8(%rbp), %rcx
andq $0x3f, %rcx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
setne %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x170(%rbp)
jmp 0x401ae3
xorl %eax, %eax
movl %eax, -0x170(%rbp)
jmp 0x401ae3
movl -0x170(%rbp), %eax
movl %eax, -0xec(%rbp)
cmpl $0x0, -0xec(%rbp)
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x401b01
jmp 0x401b15
movl -0xbc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xbc(%rbp)
jmp 0x401a78
movl -0xbc(%rbp), %ecx
movq -0xd8(%rbp), %rax
movq -0xe0(%rbp), %rdx
shlq $0xa, %rdx
addq %rdx, %rax
movl %ecx, 0x4(%rax)
movl -0xbc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xbc(%rbp)
movq -0xd8(%rbp), %rax
movq -0xe0(%rbp), %rcx
shlq $0xa, %rcx
addq %rcx, %rax
movl $0x0, (%rax)
movq -0xd8(%rbp), %rcx
movq -0xe0(%rbp), %rax
shlq $0xa, %rax
addq %rax, %rcx
leaq -0xf8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
leaq 0x58c(%rip), %rdx       # 0x402110
callq 0x422180
cmpl $0x0, %eax
je 0x401ba4
leaq 0xb672f(%rip), %rdi     # 0x4b82c4
callq 0x411250
movl $0x1, %edi
callq 0x40bbb0
jmp 0x401ba6
movq -0xe0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xe0(%rbp)
jmp 0x401a62
callq 0x4027a0
movq -0xb8(%rbp), %rdi
movl $0x4, %esi
callq 0x42c0b0
movq %rax, -0x100(%rbp)
leaq 0xb66f2(%rip), %rdi     # 0x4b82d3
movb $0x0, %al
callq 0x411020
leaq 0xd2646(%rip), %rax     # 0x4d4235
movq %rax, -0x110(%rbp)
movsbl -0x21(%rbp), %eax
cmpl $0x2c, %eax
jne 0x401c2b
leaq 0xb6718(%rip), %rdi     # 0x4b831e
movb $0x0, %al
callq 0x411020
leaq 0xb6718(%rip), %rax     # 0x4b832c
movq %rax, -0x108(%rbp)
leaq 0xb6712(%rip), %rax     # 0x4b8334
movq %rax, -0x110(%rbp)
jmp 0x401c47
leaq 0xb6715(%rip), %rax     # 0x4b8347
movq %rax, -0x108(%rbp)
leaq 0xb670d(%rip), %rdi     # 0x4b834d
movb $0x0, %al
callq 0x411020
movq $0x0, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
cmpq -0xb8(%rbp), %rax
jae 0x401c9c
movq -0x108(%rbp), %rdi
movq -0xd8(%rbp), %rax
movq -0xe0(%rbp), %rcx
shlq $0xa, %rcx
addq %rcx, %rax
movl 0x4(%rax), %esi
movb $0x0, %al
callq 0x411020
movq -0xe0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xe0(%rbp)
jmp 0x401c52
movq -0x110(%rbp), %rsi
leaq 0xd1e9d(%rip), %rdi     # 0x4d3b47
movb $0x0, %al
callq 0x411020
movl $0x0, 0xf0665(%rip)     # 0x4f2320
movl $0x0, 0xf065f(%rip)     # 0x4f2324
movl 0xf0659(%rip), %eax     # 0x4f2324
cmpl $0x2, %eax
jge 0x4020fb
movsbl -0x21(%rbp), %eax
cmpl $0x2c, %eax
je 0x401cff
movl 0xf0641(%rip), %ecx     # 0x4f2324
leaq 0xb6668(%rip), %rdi     # 0x4b8352
leaq 0xb6663(%rip), %rax     # 0x4b8354
cmpl $0x0, %ecx
cmovneq %rax, %rdi
movb $0x0, %al
callq 0x411020
movl $0x0, -0x114(%rbp)
movl -0x114(%rbp), %eax
cmpl -0x18(%rbp), %eax
jge 0x4020e5
movl -0x114(%rbp), %eax
movl %eax, 0xf05fc(%rip)     # 0x4f2320
callq 0x402800
movq %rax, -0x120(%rbp)
movq $0x0, -0x128(%rbp)
movq -0x128(%rbp), %rax
movq -0x30(%rbp), %rcx
addq $0x1, %rcx
cmpq %rcx, %rax
jae 0x4020cf
movsd 0xb62ad(%rip), %xmm0    # 0x4b8008
movsd %xmm0, -0x130(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x138(%rbp)
movq -0x20(%rbp), %rax
movl %eax, %edi
callq 0x464e30
movq $0x0, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
cmpq -0xb8(%rbp), %rax
jae 0x401dd0
movq -0xd8(%rbp), %rax
movq -0xe0(%rbp), %rcx
shlq $0xa, %rcx
xorl %edx, %edx
xchgl %edx, (%rax,%rcx)
movq -0x100(%rbp), %rax
movq -0xe0(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0xe0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xe0(%rbp)
jmp 0x401d84
callq 0x402800
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rax
subq -0x120(%rbp), %rax
movq %rax, -0x148(%rbp)
movq -0x140(%rbp), %rax
movq %rax, -0x120(%rbp)
cmpq $0x0, -0x128(%rbp)
jne 0x401e0e
jmp 0x4020b8
movsbl -0x21(%rbp), %eax
cmpl $0x2c, %eax
jne 0x401e40
movl 0xf0507(%rip), %esi     # 0x4f2324
movslq 0xf04fc(%rip), %rax     # 0x4f2320
leaq 0xec4f5(%rip), %rdx     # 0x4ee320
shlq $0x6, %rax
addq %rax, %rdx
leaq 0xb6525(%rip), %rdi     # 0x4b835e
movb $0x0, %al
callq 0x411020
movsbl -0x21(%rbp), %eax
cmpl $0x2c, %eax
jne 0x401e59
leaq 0xb6514(%rip), %rax     # 0x4b8364
movq %rax, -0x108(%rbp)
jmp 0x401e75
leaq 0xb650a(%rip), %rax     # 0x4b836a
movq %rax, -0x108(%rbp)
leaq 0xb64dc(%rip), %rdi     # 0x4b834a
movb $0x0, %al
callq 0x411020
xorps %xmm0, %xmm0
movsd %xmm0, -0x150(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x158(%rbp)
movq $0x0, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
cmpq -0xb8(%rbp), %rax
jae 0x401fce
cvtsi2sdq -0x148(%rbp), %xmm0
movq -0x100(%rbp), %rax
movq -0xe0(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cvtsi2sd %rax, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x160(%rbp)
movq -0x108(%rbp), %rdi
movsd -0x160(%rbp), %xmm0
movb $0x1, %al
callq 0x411020
movsd -0x130(%rbp), %xmm1
movsd -0x160(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x401f13
movsd -0x130(%rbp), %xmm0
movsd %xmm0, -0x178(%rbp)
jmp 0x401f23
movsd -0x160(%rbp), %xmm0
movsd %xmm0, -0x178(%rbp)
movsd -0x178(%rbp), %xmm0
movsd %xmm0, -0x130(%rbp)
movsd -0x138(%rbp), %xmm0
ucomisd -0x160(%rbp), %xmm0
jbe 0x401f57
movsd -0x138(%rbp), %xmm0
movsd %xmm0, -0x180(%rbp)
jmp 0x401f67
movsd -0x160(%rbp), %xmm0
movsd %xmm0, -0x180(%rbp)
movsd -0x180(%rbp), %xmm0
movsd %xmm0, -0x138(%rbp)
movsd -0x160(%rbp), %xmm0
addsd -0x150(%rbp), %xmm0
movsd %xmm0, -0x150(%rbp)
movsd -0x160(%rbp), %xmm0
movsd -0x160(%rbp), %xmm2
movsd -0x158(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x158(%rbp)
movq -0xe0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xe0(%rbp)
jmp 0x401e96
movsbl -0x21(%rbp), %eax
cmpl $0x2c, %eax
jne 0x401fe7
leaq 0xb6394(%rip), %rax     # 0x4b8372
movq %rax, -0x108(%rbp)
jmp 0x401ff5
leaq 0xb639a(%rip), %rax     # 0x4b8388
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rax
movq %rax, -0x190(%rbp)
movsd -0x150(%rbp), %xmm1
movq -0xb8(%rbp), %rax
movq %rax, %xmm4
movaps 0xb5ff2(%rip), %xmm3    # 0x4b8010
punpckldq %xmm3, %xmm4    # xmm4 = xmm4[0],xmm3[0],xmm4[1],xmm3[1]
movapd 0xb5ff6(%rip), %xmm2    # 0x4b8020
subpd %xmm2, %xmm4
movaps %xmm4, %xmm0
unpckhpd %xmm4, %xmm4            # xmm4 = xmm4[1,1]
addsd %xmm0, %xmm4
movaps %xmm1, %xmm0
divsd %xmm4, %xmm0
movsd %xmm0, -0x188(%rbp)
movsd -0x158(%rbp), %xmm0
mulsd %xmm1, %xmm1
divsd %xmm4, %xmm1
subsd %xmm1, %xmm0
decq %rax
movq %rax, %xmm1
punpckldq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
callq 0x402840
movq -0x190(%rbp), %rdi
movaps %xmm0, %xmm1
movsd -0x188(%rbp), %xmm0
movsd -0x130(%rbp), %xmm2
movsd -0x138(%rbp), %xmm3
movb $0x4, %al
callq 0x411020
movq $0x4ec710, %rax         # imm = 0x4EC710
movq (%rax), %rdi
callq 0x417bb0
movq -0x128(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x128(%rbp)
jmp 0x401d3b
jmp 0x4020d1
movl -0x114(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x114(%rbp)
jmp 0x401d09
jmp 0x4020e7
movl 0xf0237(%rip), %eax     # 0x4f2324
addl $0x1, %eax
movl %eax, 0xf022e(%rip)     # 0x4f2324
jmp 0x401cc5
xorl %eax, %eax
addq $0x190, %rsp            # imm = 0x190
popq %rbp
retq
nopw %cs:(%rax,%rax)