// File: /workspace/github_c_makefile_star2_O3/mvermeulen[P]wspy/wspy.c
// Function: main
int main(int argc,char *const argv[],char *const envp[]){
  int i;
  int status;
  struct rusage rusage;
  struct counter_group *cgroup;
  outfile = stdout;
  num_procs = get_nprocs();
  clocks_per_second = sysconf(_SC_CLK_TCK);
  
  if (parse_options(argc,argv)){
      fatal("usage: %s -[abcistv][-o <file>] <cmd><args>...\n"
	    "\t--per-core or -a          - metrics per core\n"
	    "\t--rusage or -r            - show getrusage(2) information\n"
	    "\t--tree <file>             - create CSV of processes\n"
	    "\t--tree-cmdline            - record full command lines\n"
	    "\t--tree-vmsize             - virtual memory size\n"
	    "\t-o <file>                 - send output to file\n"
	    "\t--csv                     - create csv output\n"
	    "\t--interval <sec>          - read every <sec> seconds\n"
	    "\t--verbose or -v           - print verbose information\n"
	    "\n"
	    "\t--software or -s          - software counters\n"
	    "\t--ipc or i                - IPC counters\n"
	    "\t--branch or -b            - branch counters\n"
	    "\t--dcache                  - L1 dcache counters\n"
	    "\t--icache                  - L1 icache counters\n"
	    "\t--cache2 or -c            - L2 cache counters\n"
	    "\t--cache3                  - L3 cache counters\n"
	    "\t--memory                  - memory counters\n"
	    "\t--opcache                 - opcache counters\n"
	    "\t--tlb                     - TLB counters\n"
	    "\t--topdown or -t           - topdown counters, level 1\n"
	    "\t--topdown2                - topdown counters, level 2\n"
	    "\t--topdown-frontend        - topdown related to fe\n"
	    "\t--topdown-optlb           - topdown related to opcache, dtlb\n"
	    ,argv[0]);
  }

  if (inventory_cpu() != 0){
    fatal("unable to query CPU information\n");
  }

  check_nmi_watchdog();

#if AMDGPU
  gpu_info_initialize();
#endif

  // parse the event tables
  setup_raw_events();

  // set up either system-wide or core-specific counters
  if (aflag){
    for (i=0;i<cpu_info->num_cores;i++){
      if (cpu_info->coreinfo[i].is_available &&
	  ((cpu_info->coreinfo[i].vendor == CORE_AMD_ZEN)||(cpu_info->coreinfo[i].vendor == CORE_AMD_ZEN5)||(cpu_info->coreinfo[i].vendor == CORE_INTEL_CORE))){
	setup_counter_groups(&cpu_info->coreinfo[i].core_specific_counters);
      }
    }
  } else {
    setup_counter_groups(&cpu_info->systemwide_counters);
  }
  // software counters are only system-wide
  if (counter_mask & COUNTER_SOFTWARE){
    if (cgroup = software_counter_group("software")){
      cgroup->next = cpu_info->systemwide_counters;
      cpu_info->systemwide_counters = cgroup;
    }
  }

  // set up core-specific and system-wide counters
  for (i=0;i<cpu_info->num_cores;i++){
    if (cpu_info->coreinfo[i].core_specific_counters)
      setup_counters(cpu_info->coreinfo[i].core_specific_counters);
  }
  setup_counters(cpu_info->systemwide_counters);

  // start core-specific and system-wide counters
  for (i=0;i<cpu_info->num_cores;i++){
    if (cpu_info->coreinfo[i].core_specific_counters)
      start_counters(cpu_info->coreinfo[i].core_specific_counters);
  }
  start_counters(cpu_info->systemwide_counters);

  signal(SIGINT,SIG_IGN);

  // create CSV headers
  if (csvflag){
    if (interval){
      fprintf(outfile,"time,");
    }
    if (sflag) print_system(PRINT_CSV_HEADER);
    if (!interval && xflag) print_usage(NULL,PRINT_CSV_HEADER);
    print_metrics(cpu_info->systemwide_counters,PRINT_CSV_HEADER);
    fprintf(outfile,"\n");
  }

  // let the child start after two seconds
  sleep(2);

  if (sflag) read_system();

  clock_gettime(CLOCK_REALTIME,&start_time);
  if (launch_child(command_line_argc,command_line_argv,envp)){
    fatal("unable to launch %s\n",command_line_argv[0]);
  }

  if (interval){
    signal(SIGALRM,timer_callback);
    alarm(interval);
  }

  write(child_pipe[1],"start\n",6);
  if (treeflag){
    ptrace_setup(child_pid);
    fprintf(treefile,"0.000 %d root\n",child_pid);
    ptrace_loop();
    getrusage(RUSAGE_CHILDREN,&rusage);
  } else {
    // without ptrace, this process waits to complete
    wait4(child_pid,&status,0,&rusage);
  }

  is_still_running = 0;
  
  clock_gettime(CLOCK_REALTIME,&finish_time);

  read_system();

  // -----  
  // stop core-specific and system-wide counters
  for (i=0;i<cpu_info->num_cores;i++){
    if (cpu_info->coreinfo[i].core_specific_counters)
      read_counters(cpu_info->coreinfo[i].core_specific_counters,1);
  }
  read_counters(cpu_info->systemwide_counters,1);

  if (csvflag){
    if (interval){
      double elapsed;
  
      elapsed = finish_time.tv_sec + finish_time.tv_nsec / 1000000000.0 -
	start_time.tv_sec - start_time.tv_nsec / 1000000000.0;    
      fprintf(outfile,"%4.1f,",elapsed);
    }
    if (sflag) print_system(PRINT_CSV);
    if (xflag && !interval) print_usage(&rusage,PRINT_CSV);
    print_metrics(cpu_info->systemwide_counters,PRINT_CSV);    
    fprintf(outfile,"\n");    
  } else {
    if (sflag) print_system(PRINT_NORMAL);
    if (xflag) print_usage(&rusage,PRINT_NORMAL);
    print_metrics(cpu_info->systemwide_counters,PRINT_NORMAL);
  }

  for (i=0;i<cpu_info->num_cores;i++){
    if (cpu_info->coreinfo[i].core_specific_counters){
      if (csvflag){
	print_usage(&rusage,PRINT_CSV);
      } else {
	fprintf(outfile,"##### core %2d #######################\n",i);
      }
      print_metrics(cpu_info->coreinfo[i].core_specific_counters,csvflag?PRINT_CSV:PRINT_NORMAL);
      if (csvflag) fprintf(outfile,"\n");
    }
  }

  if (oflag) fclose(outfile);
  // -----

#if AMDGPU
  gpu_info_finalize();
#endif
  
  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rdx, %rbx
movq %rsi, %r14
movl %edi, %ebp
movq 0xd755(%rip), %rax      # 0x10fc0
movq (%rax), %rax
movq %rax, 0xe883(%rip)      # 0x120f8
callq 0x3340
movl %eax, 0xe88c(%rip)      # 0x1210c
movl $0x2, %edi
callq 0x3280
movl %eax, 0xe880(%rip)      # 0x12110
movl %ebp, %edi
movq %r14, %rsi
callq 0x345c
testl %eax, %eax
je 0x38af
movq (%r14), %rsi
leaq 0x7af8(%rip), %rdi      # 0xb3a0
xorl %eax, %eax
callq 0x913b
callq 0x8c9c
testl %eax, %eax
je 0x38c6
leaq 0x7f8d(%rip), %rdi      # 0xb84c
xorl %eax, %eax
callq 0x913b
callq 0x5544
callq 0x406c
cmpl $0x0, 0xe7f1(%rip)      # 0x120c8
leaq 0xf882(%rip), %r12      # 0x13160
movq (%r12), %rdi
je 0x3933
cmpl $0x0, 0xc(%rdi)
je 0x393c
movl $0x48, %r14d
xorl %r15d, %r15d
movl $0x4c, %ebp
movq 0x18(%rdi), %rax
testb $0x1, -0x44(%rax,%r14)
je 0x3922
movl -0x48(%rax,%r14), %ecx
cmpl $0x6, %ecx
ja 0x3922
btl %ecx, %ebp
jae 0x3922
addq %r14, %rax
movq %rax, %rdi
callq 0x4efe
movq (%r12), %rdi
incq %r15
movl 0xc(%rdi), %eax
addq $0x60, %r14
cmpq %rax, %r15
jb 0x38f8
jmp 0x393c
addq $0x20, %rdi
callq 0x4efe
testb $-0x80, 0xd882(%rip)    # 0x111c5
jne 0x394b
movq (%r12), %rcx
jmp 0x396c
leaq 0x791e(%rip), %rdi      # 0xb270
callq 0x4bb3
movq (%r12), %rcx
testq %rax, %rax
je 0x396c
movq 0x20(%rcx), %rdx
movq %rdx, 0x20(%rax)
movq %rax, 0x20(%rcx)
cmpl $0x0, 0xc(%rcx)
je 0x39a0
movl $0x48, %r14d
xorl %r15d, %r15d
movq 0x18(%rcx), %rax
movq (%rax,%r14), %rdi
testq %rdi, %rdi
je 0x3991
callq 0x5100
movq (%r12), %rcx
incq %r15
movl 0xc(%rcx), %eax
addq $0x60, %r14
cmpq %rax, %r15
jb 0x397b
movq 0x20(%rcx), %rdi
callq 0x5100
movq (%r12), %rax
cmpl $0x0, 0xc(%rax)
je 0x39e1
movl $0x48, %r14d
xorl %r15d, %r15d
movq 0x18(%rax), %rcx
movq (%rcx,%r14), %rdi
testq %rdi, %rdi
je 0x39d2
callq 0x5310
movq (%r12), %rax
incq %r15
movl 0xc(%rax), %ecx
addq $0x60, %r14
cmpq %rcx, %r15
jb 0x39bc
movq 0x20(%rax), %rdi
callq 0x5310
movl $0x1, %esi
movl $0x2, %edi
callq 0x31b0
cmpl $0x0, 0xe6d8(%rip)      # 0x120d8
je 0x3a7c
cmpl $0x0, 0xe6d3(%rip)      # 0x120dc
je 0x3a28
movq 0xe6e6(%rip), %rcx      # 0x120f8
leaq 0x926d(%rip), %rdi      # 0xcc86
movl $0x5, %esi
movl $0x1, %edx
callq 0x32c0
cmpl $0x0, 0xe6a1(%rip)      # 0x120d0
je 0x3a3b
movl $0x2, %edi
callq 0x9cca
cmpl $0x0, 0xe69a(%rip)      # 0x120dc
jne 0x3a59
cmpl $0x0, 0xd775(%rip)      # 0x111c0
je 0x3a59
xorl %edi, %edi
movl $0x2, %esi
callq 0x5590
movq (%r12), %rax
movq 0x20(%rax), %rdi
movl $0x2, %esi
callq 0x8964
movq 0xe686(%rip), %rsi      # 0x120f8
movl $0xa, %edi
callq 0x3150
movl $0x2, %edi
callq 0x3300
cmpl $0x0, 0xe643(%rip)      # 0x120d0
je 0x3a94
callq 0x9909
leaq 0xf6b5(%rip), %r14      # 0x13150
xorl %edi, %edi
movq %r14, %rsi
callq 0x3070
movl 0xe65d(%rip), %edi      # 0x12108
movq 0xe64e(%rip), %rsi      # 0x12100
movq %rbx, %rdx
callq 0x4116
testl %eax, %eax
je 0x3ad6
movq 0xe63b(%rip), %rax      # 0x12100
movq (%rax), %rsi
leaq 0x7d9e(%rip), %rdi      # 0xb86d
xorl %eax, %eax
callq 0x913b
cmpl $0x0, 0xe5ff(%rip)      # 0x120dc
je 0x3afb
leaq 0x506e(%rip), %rsi      # 0x8b54
movl $0xe, %edi
callq 0x31b0
movl 0xe5e6(%rip), %edi      # 0x120dc
callq 0x3120
leaq 0xe62a(%rip), %rax      # 0x1212c
movl 0x4(%rax), %edi
leaq 0x7d76(%rip), %rsi      # 0xb882
movl $0x6, %edx
callq 0x3080
cmpl $0x0, 0xe5c3(%rip)      # 0x120e0
leaq 0xe604(%rip), %rbx      # 0x12128
movl (%rbx), %edi
je 0x3b5a
callq 0x4293
movq 0xe5bc(%rip), %rdi      # 0x120f0
movl (%rbx), %edx
leaq 0x7d4c(%rip), %rsi      # 0xb889
xorl %eax, %eax
callq 0x31c0
callq 0x43e0
leaq 0x8(%rsp), %rsi
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3260
jmp 0x3b6b
leaq 0x4(%rsp), %rsi
leaq 0x8(%rsp), %rcx
xorl %edx, %edx
callq 0x3230
leaq 0xe5c2(%rip), %rax      # 0x12134
movl $0x0, (%rax)
leaq 0xf5c1(%rip), %rbx      # 0x13140
xorl %edi, %edi
movq %rbx, %rsi
callq 0x3070
callq 0x9909
movq (%r12), %rax
cmpl $0x0, 0xc(%rax)
je 0x3bcb
movl $0x48, %r15d
xorl %r13d, %r13d
movq 0x18(%rax), %rcx
movq (%rcx,%r15), %rdi
testq %rdi, %rdi
je 0x3bbc
movl $0x1, %esi
callq 0x53df
movq (%r12), %rax
incq %r13
movl 0xc(%rax), %ecx
addq $0x60, %r15
cmpq %rcx, %r13
jb 0x3ba1
movq 0x20(%rax), %rdi
movl $0x1, %esi
callq 0x53df
cmpl $0x0, 0xe4f8(%rip)      # 0x120d8
je 0x3c92
cmpl $0x0, 0xe4ef(%rip)      # 0x120dc
je 0x3c39
cvtsi2sdq (%rbx), %xmm1
cvtsi2sdq 0x8(%rbx), %xmm0
movsd 0x75e6(%rip), %xmm2     # 0xb1e8
divsd %xmm2, %xmm0
addsd %xmm1, %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq (%r14), %xmm1
cvtsi2sdq 0x8(%r14), %xmm3
subsd %xmm1, %xmm0
divsd %xmm2, %xmm3
subsd %xmm3, %xmm0
movq 0xe4cd(%rip), %rdi      # 0x120f8
leaq 0x94fd(%rip), %rsi      # 0xd12f
movb $0x1, %al
callq 0x31c0
cmpl $0x0, 0xe490(%rip)      # 0x120d0
je 0x3c4c
movl $0x1, %edi
callq 0x9cca
cmpl $0x0, 0xd56d(%rip)      # 0x111c0
je 0x3c6d
cmpl $0x0, 0xe480(%rip)      # 0x120dc
jne 0x3c6d
leaq 0x8(%rsp), %rdi
movl $0x1, %esi
callq 0x5590
movq (%r12), %rax
movq 0x20(%rax), %rdi
movl $0x1, %esi
callq 0x8964
movq 0xe472(%rip), %rsi      # 0x120f8
movl $0xa, %edi
callq 0x3150
jmp 0x3cc6
cmpl $0x0, 0xe437(%rip)      # 0x120d0
je 0x3ca2
xorl %edi, %edi
callq 0x9cca
cmpl $0x0, 0xd517(%rip)      # 0x111c0
je 0x3cb7
leaq 0x8(%rsp), %rdi
xorl %esi, %esi
callq 0x5590
movq (%r12), %rax
movq 0x20(%rax), %rdi
xorl %esi, %esi
callq 0x8964
movq (%r12), %rax
cmpl $0x0, 0xc(%rax)
je 0x3d6f
movl $0x48, %r13d
leaq 0x7bb7(%rip), %rbx      # 0xb898
leaq 0x8(%rsp), %r14
xorl %r15d, %r15d
movq 0x18(%rax), %rax
cmpq $0x0, (%rax,%r13)
je 0x3d58
cmpl $0x0, 0xe3dd(%rip)      # 0x120d8
je 0x3d0c
movq %r14, %rdi
movl $0x1, %esi
callq 0x5590
jmp 0x3d20
movq 0xe3e5(%rip), %rdi      # 0x120f8
movq %rbx, %rsi
movl %r15d, %edx
xorl %eax, %eax
callq 0x31c0
movq (%r12), %rax
movq 0x18(%rax), %rax
movq (%rax,%r13), %rdi
xorl %esi, %esi
cmpl $0x0, 0xe3a3(%rip)      # 0x120d8
setne %sil
callq 0x8964
cmpl $0x0, 0xe393(%rip)      # 0x120d8
je 0x3d58
movq 0xe3aa(%rip), %rsi      # 0x120f8
movl $0xa, %edi
callq 0x3150
incq %r15
movq (%r12), %rax
movl 0xc(%rax), %ecx
addq $0x60, %r13
cmpq %rcx, %r15
jb 0x3ce9
cmpl $0x0, 0xe356(%rip)      # 0x120cc
je 0x3d84
movq 0xe379(%rip), %rdi      # 0x120f8
callq 0x30a0
xorl %eax, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq