// File: sisong[P]ApkDiffPatch/lzma/C/MtCoder.c
// Function: ThreadFunc2
static SRes ThreadFunc2(CMtCoderThread *t)
{
  CMtCoder *mtc = t->mtCoder;

  for (;;)
  {
    unsigned bi;
    SRes res;
    SRes res2;
    BoolInt finished;
    unsigned bufIndex;
    size_t size;
    const Byte *inData;
    UInt64 readProcessed = 0;
    
    RINOK_THREAD(Event_Wait(&mtc->readEvent))

    /* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */

    if (mtc->stopReading)
    {
      return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD;
    }

    res = MtProgress_GetError(&mtc->mtProgress);
    
    size = 0;
    inData = NULL;
    finished = True;

    if (res == SZ_OK)
    {
      size = mtc->blockSize;
      if (mtc->inStream)
      {
        if (!t->inBuf)
        {
          t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize);
          if (!t->inBuf)
            res = SZ_ERROR_MEM;
        }
        if (res == SZ_OK)
        {
          res = SeqInStream_ReadMax(mtc->inStream, t->inBuf, &size);
          readProcessed = mtc->readProcessed + size;
          mtc->readProcessed = readProcessed;
        }
        if (res != SZ_OK)
        {
          mtc->readRes = res;
          /* after reading error - we can stop encoding of previous blocks */
          MtProgress_SetError(&mtc->mtProgress, res);
        }
        else
          finished = (size != mtc->blockSize);
      }
      else
      {
        size_t rem;
        readProcessed = mtc->readProcessed;
        rem = mtc->inDataSize - (size_t)readProcessed;
        if (size > rem)
          size = rem;
        inData = mtc->inData + (size_t)readProcessed;
        readProcessed += size;
        mtc->readProcessed = readProcessed;
        finished = (mtc->inDataSize == (size_t)readProcessed);
      }
    }

    /* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */

    res2 = SZ_OK;

    if (Semaphore_Wait(&mtc->blocksSemaphore) != 0)
    {
      res2 = SZ_ERROR_THREAD;
      if (res == SZ_OK)
      {
        res = res2;
        // MtProgress_SetError(&mtc->mtProgress, res);
      }
    }

    bi = mtc->blockIndex;

    if (++mtc->blockIndex >= mtc->numBlocksMax)
      mtc->blockIndex = 0;

    bufIndex = (unsigned)(int)-1;

    if (res == SZ_OK)
      res = MtProgress_GetError(&mtc->mtProgress);

    if (res != SZ_OK)
      finished = True;

    if (!finished)
    {
      if (mtc->numStartedThreads < mtc->numStartedThreadsLimit
          && mtc->expectedDataSize != readProcessed)
      {
        res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]);
        if (res == SZ_OK)
          mtc->numStartedThreads++;
        else
        {
          MtProgress_SetError(&mtc->mtProgress, res);
          finished = True;
        }
      }
    }

    if (finished)
      mtc->stopReading = True;

    RINOK_THREAD(Event_Set(&mtc->readEvent))

    if (res2 != SZ_OK)
      return res2;

    if (res == SZ_OK)
    {
      CriticalSection_Enter(&mtc->cs);
      bufIndex = mtc->freeBlockHead;
      mtc->freeBlockHead = mtc->freeBlockList[bufIndex];
      CriticalSection_Leave(&mtc->cs);
      
      res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex,
          mtc->inStream ? t->inBuf : inData, size, finished);
      
      // MtProgress_Reinit(&mtc->mtProgress, t->index);

      if (res != SZ_OK)
        MtProgress_SetError(&mtc->mtProgress, res);
    }

    {
      CMtCoderBlock *block = &mtc->blocks[bi];
      block->res = res;
      block->bufIndex = bufIndex;
      block->finished = finished;
    }
    
    #ifdef MTCODER_USE_WRITE_THREAD
      RINOK_THREAD(Event_Set(&mtc->writeEvents[bi]))
    #else
    {
      unsigned wi;
      {
        CriticalSection_Enter(&mtc->cs);
        wi = mtc->writeIndex;
        if (wi == bi)
          mtc->writeIndex = (unsigned)(int)-1;
        else
          mtc->ReadyBlocks[bi] = True;
        CriticalSection_Leave(&mtc->cs);
      }

      if (wi != bi)
      {
        if (res != SZ_OK || finished)
          return 0;
        continue;
      }

      if (mtc->writeRes != SZ_OK)
        res = mtc->writeRes;

      for (;;)
      {
        if (res == SZ_OK && bufIndex != (unsigned)(int)-1)
        {
          res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex);
          if (res != SZ_OK)
          {
            mtc->writeRes = res;
            MtProgress_SetError(&mtc->mtProgress, res);
          }
        }

        if (++wi >= mtc->numBlocksMax)
          wi = 0;
        {
          BoolInt isReady;

          CriticalSection_Enter(&mtc->cs);
          
          if (bufIndex != (unsigned)(int)-1)
          {
            mtc->freeBlockList[bufIndex] = mtc->freeBlockHead;
            mtc->freeBlockHead = bufIndex;
          }
          
          isReady = mtc->ReadyBlocks[wi];
          
          if (isReady)
            mtc->ReadyBlocks[wi] = False;
          else
            mtc->writeIndex = wi;
          
          CriticalSection_Leave(&mtc->cs);

          RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore))

          if (!isReady)
            break;
        }

        {
          CMtCoderBlock *block = &mtc->blocks[wi];
          if (res == SZ_OK && block->res != SZ_OK)
            res = block->res;
          bufIndex = block->bufIndex;
          finished = block->finished;
        }
      }
    }
    #endif
      
    if (finished || res != SZ_OK)
      return 0;
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq $0x0, -0x48(%rbp)
movq -0x18(%rbp), %rdi
addq $0x58, %rdi
callq 0x7b6d0
cmpl $0x0, %eax
je 0x78d10
movl $0xc, -0x4(%rbp)
jmp 0x7935a
movq -0x18(%rbp), %rax
cmpl $0x0, 0x128(%rax)
je 0x78d41
movq -0x18(%rbp), %rdi
addq $0x58, %rdi
callq 0x7b600
movl %eax, %edx
movl $0xc, %eax
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovel %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x7935a
movq -0x18(%rbp), %rdi
addq $0x368, %rdi            # imm = 0x368
callq 0x794d0
movl %eax, -0x20(%rbp)
movq $0x0, -0x38(%rbp)
movq $0x0, -0x40(%rbp)
movl $0x1, -0x28(%rbp)
cmpl $0x0, -0x20(%rbp)
jne 0x78ece
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x78e59
movq -0x10(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x78dd5
movq -0x18(%rbp), %rax
movq 0x38(%rax), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
movq 0x38(%rcx), %rdi
movq -0x18(%rbp), %rcx
movq (%rcx), %rsi
callq *%rax
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x78dd3
movl $0x2, -0x20(%rbp)
jmp 0x78dd5
cmpl $0x0, -0x20(%rbp)
jne 0x78e19
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
leaq -0x38(%rbp), %rdx
callq 0x6e930
movl %eax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq 0x200(%rax), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x200(%rax)
cmpl $0x0, -0x20(%rbp)
je 0x78e41
movl -0x20(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x12c(%rax)
movq -0x18(%rbp), %rdi
addq $0x368, %rdi            # imm = 0x368
movl -0x20(%rbp), %esi
callq 0x79510
jmp 0x78e57
movq -0x38(%rbp), %rax
movq -0x18(%rbp), %rcx
cmpq (%rcx), %rax
setne %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x28(%rbp)
jmp 0x78ecc
movq -0x18(%rbp), %rax
movq 0x200(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
subq -0x48(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x50(%rbp), %rax
jbe 0x78e8a
movq -0x50(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
addq -0x48(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
addq -0x48(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x200(%rax)
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
cmpq -0x48(%rbp), %rax
sete %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x28(%rbp)
jmp 0x78ece
movl $0x0, -0x24(%rbp)
movq -0x18(%rbp), %rdi
addq $0xc0, %rdi
callq 0x7b980
cmpl $0x0, %eax
je 0x78eff
movl $0xc, -0x24(%rbp)
cmpl $0x0, -0x20(%rbp)
jne 0x78efd
movl -0x24(%rbp), %eax
movl %eax, -0x20(%rbp)
jmp 0x78eff
movq -0x18(%rbp), %rax
movl 0x1fc(%rax), %eax
movl %eax, -0x1c(%rbp)
movq -0x18(%rbp), %rcx
movl 0x1fc(%rcx), %eax
addl $0x1, %eax
movl %eax, 0x1fc(%rcx)
movq -0x18(%rbp), %rcx
cmpl 0x1f8(%rcx), %eax
jb 0x78f39
movq -0x18(%rbp), %rax
movl $0x0, 0x1fc(%rax)
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
cmpl $0x0, -0x20(%rbp)
jne 0x78f59
movq -0x18(%rbp), %rdi
addq $0x368, %rdi            # imm = 0x368
callq 0x794d0
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
je 0x78f66
movl $0x1, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
jne 0x78ff4
movq -0x18(%rbp), %rax
movl 0x1f4(%rax), %eax
movq -0x18(%rbp), %rcx
cmpl 0x1f0(%rcx), %eax
jae 0x78ff2
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
cmpq -0x48(%rbp), %rax
je 0x78ff2
movq -0x18(%rbp), %rdi
addq $0x740, %rdi            # imm = 0x740
movq -0x18(%rbp), %rax
movl 0x1f4(%rax), %eax
imulq $0x90, %rax, %rax
addq %rax, %rdi
callq 0x78ab0
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jne 0x78fd6
movq -0x18(%rbp), %rax
movl 0x1f4(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x1f4(%rax)
jmp 0x78ff0
movq -0x18(%rbp), %rdi
addq $0x368, %rdi            # imm = 0x368
movl -0x20(%rbp), %esi
callq 0x79510
movl $0x1, -0x28(%rbp)
jmp 0x78ff2
jmp 0x78ff4
cmpl $0x0, -0x28(%rbp)
je 0x79008
movq -0x18(%rbp), %rax
movl $0x1, 0x128(%rax)
movq -0x18(%rbp), %rdi
addq $0x58, %rdi
callq 0x7b600
cmpl $0x0, %eax
je 0x79026
movl $0xc, -0x4(%rbp)
jmp 0x7935a
cmpl $0x0, -0x24(%rbp)
je 0x79037
movl -0x24(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x7935a
cmpl $0x0, -0x20(%rbp)
jne 0x79115
movq -0x18(%rbp), %rdi
addq $0x208, %rdi            # imm = 0x208
callq 0x7bab0
movq -0x18(%rbp), %rax
movl 0x230(%rax), %eax
movl %eax, -0x2c(%rbp)
movq -0x18(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl 0x234(%rax,%rcx,4), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x230(%rax)
movq -0x18(%rbp), %rdi
addq $0x208, %rdi            # imm = 0x208
callq 0x7bae0
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rax
movq (%rax), %rax
movq %rax, -0x80(%rbp)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x78(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x70(%rbp)
movl -0x2c(%rbp), %eax
movl %eax, -0x6c(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x790cd
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x88(%rbp)
jmp 0x790d8
movq -0x40(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x80(%rbp), %rax
movl -0x6c(%rbp), %edx
movl -0x70(%rbp), %esi
movq -0x78(%rbp), %rdi
movq -0x88(%rbp), %rcx
movq -0x38(%rbp), %r8
movl -0x28(%rbp), %r9d
callq *%rax
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
je 0x79113
movq -0x18(%rbp), %rdi
addq $0x368, %rdi            # imm = 0x368
movl -0x20(%rbp), %esi
callq 0x79510
jmp 0x79115
movq -0x18(%rbp), %rax
addq $0x3b0, %rax            # imm = 0x3B0
movl -0x1c(%rbp), %ecx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movl -0x20(%rbp), %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
movl -0x2c(%rbp), %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0x4(%rax)
movl -0x28(%rbp), %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x18(%rbp), %rdi
addq $0x208, %rdi            # imm = 0x208
callq 0x7bab0
movq -0x18(%rbp), %rax
movl 0x19c(%rax), %eax
movl %eax, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jne 0x7917f
movq -0x18(%rbp), %rax
movl $0xffffffff, 0x19c(%rax) # imm = 0xFFFFFFFF
jmp 0x7918e
movq -0x18(%rbp), %rax
movl -0x1c(%rbp), %ecx
movb $0x1, 0x1a0(%rax,%rcx)
movq -0x18(%rbp), %rdi
addq $0x208, %rdi            # imm = 0x208
callq 0x7bae0
movl -0x5c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
je 0x791c3
cmpl $0x0, -0x20(%rbp)
jne 0x791b2
cmpl $0x0, -0x28(%rbp)
je 0x791be
movl $0x0, -0x4(%rbp)
jmp 0x7935a
jmp 0x78cea
movq -0x18(%rbp), %rax
cmpl $0x0, 0x198(%rax)
je 0x791dd
movq -0x18(%rbp), %rax
movl 0x198(%rax), %eax
movl %eax, -0x20(%rbp)
jmp 0x791df
cmpl $0x0, -0x20(%rbp)
jne 0x7922f
cmpl $-0x1, -0x2c(%rbp)
je 0x7922f
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rax
movq 0x8(%rax), %rax
movq -0x18(%rbp), %rcx
movq 0x48(%rcx), %rdi
movl -0x2c(%rbp), %esi
callq *%rax
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
je 0x7922d
movl -0x20(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x198(%rax)
movq -0x18(%rbp), %rdi
addq $0x368, %rdi            # imm = 0x368
movl -0x20(%rbp), %esi
callq 0x79510
jmp 0x7922f
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
movq -0x18(%rbp), %rcx
cmpl 0x1f8(%rcx), %eax
jb 0x7924b
movl $0x0, -0x5c(%rbp)
movq -0x18(%rbp), %rdi
addq $0x208, %rdi            # imm = 0x208
callq 0x7bab0
cmpl $-0x1, -0x2c(%rbp)
je 0x79286
movq -0x18(%rbp), %rax
movl 0x230(%rax), %edx
movq -0x18(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl %edx, 0x234(%rax,%rcx,4)
movl -0x2c(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x230(%rax)
movq -0x18(%rbp), %rax
movl -0x5c(%rbp), %ecx
movzbl 0x1a0(%rax,%rcx), %eax
movl %eax, -0x60(%rbp)
cmpl $0x0, -0x60(%rbp)
je 0x792af
movq -0x18(%rbp), %rax
movl -0x5c(%rbp), %ecx
movb $0x0, 0x1a0(%rax,%rcx)
jmp 0x792bc
movl -0x5c(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x19c(%rax)
movq -0x18(%rbp), %rdi
addq $0x208, %rdi            # imm = 0x208
callq 0x7bae0
movq -0x18(%rbp), %rdi
addq $0xc0, %rdi
movl $0x1, %esi
callq 0x7b8d0
cmpl $0x0, %eax
je 0x792ef
movl $0xc, -0x4(%rbp)
jmp 0x7935a
cmpl $0x0, -0x60(%rbp)
jne 0x792f7
jmp 0x79340
movq -0x18(%rbp), %rax
addq $0x3b0, %rax            # imm = 0x3B0
movl -0x5c(%rbp), %ecx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x68(%rbp)
cmpl $0x0, -0x20(%rbp)
jne 0x79327
movq -0x68(%rbp), %rax
cmpl $0x0, (%rax)
je 0x79327
movq -0x68(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x20(%rbp)
movq -0x68(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x2c(%rbp)
movq -0x68(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x28(%rbp)
jmp 0x791df
cmpl $0x0, -0x28(%rbp)
jne 0x7934c
cmpl $0x0, -0x20(%rbp)
je 0x79355
movl $0x0, -0x4(%rbp)
jmp 0x7935a
jmp 0x78cea
movl -0x4(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)