// File: /workspace/github_c_makefile_star2_O3/felipelouza[P]egap/threads.c
// Function: merger
void *merger(void *v)
{
  pc_system *pc = (pc_system *) v;
  g_data g, *buffer= (g_data *)pc->buffer;
  
  int tot=0;
  while(1) {
    int e=sem_wait(pc->ready); // wait there is something to do
    if(e) die("consumer wait");
    e = pthread_mutex_lock(&pc->cmutex); // get esclusive access to queue
    if(e) die("consumer lock");
    g = buffer[(pc->cindex)++ % pc->buf_size];
    e = pthread_mutex_unlock(&pc->cmutex); // fine accesso a zona comune
    if(e) die("consumer unlock");
    e = sem_post(pc->free_slots);
    if(e) die("consumer post");
    if(g.numBwt==0) break;
    else {
      if(g.verbose>2) printf("Working on range ["CUSTOM_FORMAT","CUSTOM_FORMAT")\n", g.symb_offset,g.symb_offset+g.mergeLen-1);
      if(pc->hm)  holtMcMillan(&g, false);
      else gap(&g, false);
      // merge statistics 
      for(int i=1;i<g.numBwt;i++) {
        g.bwtLen[0] += g.bwtLen[i];
        if(g.smallAlpha)
          for(int j=0;j<g.sizeOfAlpha;j++)
            g.bwtOcc[0][j] += g.bwtOcc[i][j];
      }
      assert(g.bwtLen[0]==g.mergeLen);
      tot++;
      // update # remaining segments when we reach 0 round is completed
      e = pthread_mutex_lock(&pc->remutex); 
      if(e) die("remaining locking in thread");
      if(--pc->remaining==0) {
        e = pthread_cond_signal(&pc->recond);
        if(e) die("remaining signaling in thread");
      }
      e = pthread_mutex_unlock(&pc->remutex); 
      if(e) die("remaining unlocking in thread");
    }    
  }
  if(g.verbose>1)  printf("Thread terminated. %d merges processed\n",tot);
  pthread_exit(NULL); 
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x5138, %rsp           # imm = 0x5138
movq %rdi, %rbx
movq 0x40(%rdi), %rax
movq %rax, 0x10(%rsp)
leaq 0x8(%rdi), %r14
leaq 0x50(%rdi), %r15
leaq 0x78(%rdi), %rax
movq %rax, 0x8(%rsp)
leaq 0x18(%rsp), %r13
xorl %ebp, %ebp
movq 0x38(%rbx), %rdi
callq 0x2080
testl %eax, %eax
je 0xcc52
leaq 0x388f(%rip), %rdi      # 0x104dc
callq 0x39fc
movq %r14, %rdi
callq 0x23f0
testl %eax, %eax
je 0xcc6a
leaq 0x3885(%rip), %rdi      # 0x104ea
callq 0x39fc
movl 0x4(%rbx), %eax
leal 0x1(%rax), %ecx
movl %ecx, 0x4(%rbx)
cltd
idivl 0x48(%rbx)
movslq %edx, %rax
imulq $0x5120, %rax, %rsi     # imm = 0x5120
addq 0x10(%rsp), %rsi
movl $0x5120, %edx           # imm = 0x5120
movq %r13, %rdi
callq 0x21f0
movq %r14, %rdi
callq 0x2240
testl %eax, %eax
je 0xccab
leaq 0x3852(%rip), %rdi      # 0x104f8
callq 0x39fc
movq 0x30(%rbx), %rdi
callq 0x2170
testl %eax, %eax
je 0xccc4
leaq 0x3849(%rip), %rdi      # 0x10508
callq 0x39fc
cmpl $0x0, 0x38(%rsp)
movl 0xac(%rsp), %eax
je 0xcdd0
cmpl $0x3, %eax
jl 0xccfa
movq 0x40(%rsp), %rax
movq 0x48(%rsp), %rsi
leaq (%rsi,%rax), %rdx
decq %rdx
leaq 0x3823(%rip), %rdi      # 0x10516
xorl %eax, %eax
callq 0x2100
cmpb $0x1, 0xa8(%rbx)
jne 0xcd0f
movq %r13, %rdi
xorl %esi, %esi
callq 0xbf20
jmp 0xcd19
movq %r13, %rdi
xorl %esi, %esi
callq 0xa789
movslq 0x38(%rsp), %rax
cmpq $0x2, %rax
jl 0xcd76
movq 0x20(%rsp), %rcx
movq 0x30(%rsp), %rdx
movl 0x50(%rsp), %edi
testl %edi, %edi
setg %sil
andb 0x80(%rsp), %sil
movl %edi, %edi
movl $0x1, %r8d
movq (%rcx,%r8,8), %r9
addq %r9, (%rcx)
testb %sil, %sil
je 0xcd6e
movq (%rdx,%r8,8), %r9
movq (%rdx), %r10
xorl %r11d, %r11d
movq (%r9,%r11,8), %r12
addq %r12, (%r10,%r11,8)
incq %r11
cmpq %r11, %rdi
jne 0xcd5e
incq %r8
cmpq %rax, %r8
jne 0xcd48
movq %r15, %rdi
callq 0x23f0
testl %eax, %eax
je 0xcd8e
leaq 0x37a9(%rip), %rdi      # 0x10532
callq 0x39fc
decl 0x4c(%rbx)
jne 0xcdad
movq 0x8(%rsp), %rdi
callq 0x21b0
testl %eax, %eax
je 0xcdad
leaq 0x37a6(%rip), %rdi      # 0x1054e
callq 0x39fc
incl %ebp
movq %r15, %rdi
callq 0x2240
testl %eax, %eax
je 0xcc39
leaq 0x37a6(%rip), %rdi      # 0x1056c
callq 0x39fc
jmp 0xcc39
cmpl $0x2, %eax
jl 0xcde5
leaq 0x37ae(%rip), %rdi      # 0x1058a
movl %ebp, %esi
xorl %eax, %eax
callq 0x2100
xorl %edi, %edi
callq 0x2250