// File: sisong[P]ApkDiffPatch/lzma/C/MtCoder.c
// Function: MtCoder_Code
SRes MtCoder_Code(CMtCoder *p)
{
  unsigned numThreads = p->numThreadsMax;
  unsigned numBlocksMax;
  unsigned i;
  SRes res = SZ_OK;

  if (numThreads > MTCODER_THREADS_MAX)
      numThreads = MTCODER_THREADS_MAX;
  numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads);
  
  if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++;
  if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++;
  if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++;

  if (numBlocksMax > MTCODER_BLOCKS_MAX)
      numBlocksMax = MTCODER_BLOCKS_MAX;

  if (p->blockSize != p->allocatedBufsSize)
  {
    for (i = 0; i < MTCODER_THREADS_MAX; i++)
    {
      CMtCoderThread *t = &p->threads[i];
      if (t->inBuf)
      {
        ISzAlloc_Free(p->allocBig, t->inBuf);
        t->inBuf = NULL;
      }
    }
    p->allocatedBufsSize = p->blockSize;
  }

  p->readRes = SZ_OK;

  MtProgress_Init(&p->mtProgress, p->progress);

  #ifdef MTCODER_USE_WRITE_THREAD
    for (i = 0; i < numBlocksMax; i++)
    {
      RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->writeEvents[i]))
    }
  #else
    RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent))
  #endif

  {
    RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->readEvent))
    RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, (UInt32)numBlocksMax, (UInt32)numBlocksMax))
  }

  for (i = 0; i < MTCODER_BLOCKS_MAX - 1; i++)
    p->freeBlockList[i] = i + 1;
  p->freeBlockList[MTCODER_BLOCKS_MAX - 1] = (unsigned)(int)-1;
  p->freeBlockHead = 0;

  p->readProcessed = 0;
  p->blockIndex = 0;
  p->numBlocksMax = numBlocksMax;
  p->stopReading = False;

  #ifndef MTCODER_USE_WRITE_THREAD
    p->writeIndex = 0;
    p->writeRes = SZ_OK;
    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
      p->ReadyBlocks[i] = False;
    p->numFinishedThreads = 0;
  #endif

  p->numStartedThreadsLimit = numThreads;
  p->numStartedThreads = 0;

  // for (i = 0; i < numThreads; i++)
  {
    CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++];
    RINOK(MtCoderThread_CreateAndStart(nextThread))
  }

  RINOK_THREAD(Event_Set(&p->readEvent))

  #ifdef MTCODER_USE_WRITE_THREAD
  {
    unsigned bi = 0;

    for (;; bi++)
    {
      if (bi >= numBlocksMax)
        bi = 0;

      RINOK_THREAD(Event_Wait(&p->writeEvents[bi]))

      {
        const CMtCoderBlock *block = &p->blocks[bi];
        unsigned bufIndex = block->bufIndex;
        BoolInt finished = block->finished;
        if (res == SZ_OK && block->res != SZ_OK)
          res = block->res;

        if (bufIndex != (unsigned)(int)-1)
        {
          if (res == SZ_OK)
          {
            res = p->mtCallback->Write(p->mtCallbackObject, bufIndex);
            if (res != SZ_OK)
              MtProgress_SetError(&p->mtProgress, res);
          }
          
          CriticalSection_Enter(&p->cs);
          {
            p->freeBlockList[bufIndex] = p->freeBlockHead;
            p->freeBlockHead = bufIndex;
          }
          CriticalSection_Leave(&p->cs);
        }
        
        RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore))

        if (finished)
          break;
      }
    }
  }
  #else
  {
    WRes wres = Event_Wait(&p->finishedEvent);
    res = MY_SRes_HRESULT_FROM_WRes(wres);
  }
  #endif

  if (res == SZ_OK)
    res = p->readRes;

  if (res == SZ_OK)
    res = p->mtProgress.res;

  #ifndef MTCODER_USE_WRITE_THREAD
    if (res == SZ_OK)
      res = p->writeRes;
  #endif

  if (res != SZ_OK)
    MtCoder_Free(p);
  return res;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x14(%rbp)
movl $0x0, -0x20(%rbp)
cmpl $0x40, -0x14(%rbp)
jbe 0x7874a
movl $0x40, -0x14(%rbp)
movl -0x14(%rbp), %eax
movl -0x14(%rbp), %ecx
shrl $0x3, %ecx
addl %ecx, %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x4000000, (%rax)      # imm = 0x4000000
jae 0x78771
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x1000000, (%rax)      # imm = 0x1000000
jae 0x78787
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x400000, (%rax)       # imm = 0x400000
jae 0x7879d
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
cmpl $0x4c, -0x18(%rbp)
jbe 0x787aa
movl $0x4c, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x10(%rbp), %rcx
cmpq 0x50(%rcx), %rax
je 0x78834
movl $0x0, -0x1c(%rbp)
cmpl $0x40, -0x1c(%rbp)
jae 0x78825
movq -0x10(%rbp), %rax
addq $0x740, %rax            # imm = 0x740
movl -0x1c(%rbp), %ecx
imulq $0x90, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0x78818
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x8(%rax), %rax
movq -0x10(%rbp), %rcx
movq 0x38(%rcx), %rdi
movq -0x28(%rbp), %rcx
movq 0x10(%rcx), %rsi
callq *%rax
movq -0x28(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0x7881a
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x787c2
movq -0x10(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x50(%rax)
movq -0x10(%rbp), %rax
movl $0x0, 0x12c(%rax)
movq -0x10(%rbp), %rdi
addq $0x368, %rdi            # imm = 0x368
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rsi
callq 0x79370
movq -0x10(%rbp), %rdi
addq $0x130, %rdi            # imm = 0x130
callq 0x7bb80
cmpl $0x0, %eax
je 0x7887b
movl $0xc, -0x4(%rbp)
jmp 0x78aa0
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x7bb80
cmpl $0x0, %eax
je 0x78899
movl $0xc, -0x4(%rbp)
jmp 0x78aa0
movq -0x10(%rbp), %rdi
addq $0xc0, %rdi
movl -0x18(%rbp), %esi
movl -0x18(%rbp), %edx
callq 0x7b860
cmpl $0x0, %eax
je 0x788c0
movl $0xc, -0x4(%rbp)
jmp 0x78aa0
movl $0x0, -0x1c(%rbp)
cmpl $0x4b, -0x1c(%rbp)
jae 0x788ec
movl -0x1c(%rbp), %edx
addl $0x1, %edx
movq -0x10(%rbp), %rax
movl -0x1c(%rbp), %ecx
movl %edx, 0x234(%rax,%rcx,4)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x788c7
movq -0x10(%rbp), %rax
movl $0xffffffff, 0x360(%rax) # imm = 0xFFFFFFFF
movq -0x10(%rbp), %rax
movl $0x0, 0x230(%rax)
movq -0x10(%rbp), %rax
movq $0x0, 0x200(%rax)
movq -0x10(%rbp), %rax
movl $0x0, 0x1fc(%rax)
movl -0x18(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x1f8(%rax)
movq -0x10(%rbp), %rax
movl $0x0, 0x128(%rax)
movq -0x10(%rbp), %rax
movl $0x0, 0x19c(%rax)
movq -0x10(%rbp), %rax
movl $0x0, 0x198(%rax)
movl $0x0, -0x1c(%rbp)
cmpl $0x4c, -0x1c(%rbp)
jae 0x78983
movq -0x10(%rbp), %rax
movl -0x1c(%rbp), %ecx
movb $0x0, 0x1a0(%rax,%rcx)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x78963
movq -0x10(%rbp), %rax
movl $0x0, 0x1ec(%rax)
movl -0x14(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x1f0(%rax)
movq -0x10(%rbp), %rax
movl $0x0, 0x1f4(%rax)
movq -0x10(%rbp), %rax
addq $0x740, %rax            # imm = 0x740
movq -0x10(%rbp), %rdx
movl 0x1f4(%rdx), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, 0x1f4(%rdx)
movl %ecx, %ecx
imulq $0x90, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
callq 0x78ab0
movl %eax, -0x34(%rbp)
cmpl $0x0, -0x34(%rbp)
je 0x789f8
movl -0x34(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x78aa0
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x7b600
cmpl $0x0, %eax
je 0x78a16
movl $0xc, -0x4(%rbp)
jmp 0x78aa0
movq -0x10(%rbp), %rdi
addq $0x130, %rdi            # imm = 0x130
callq 0x7b6d0
movl %eax, -0x38(%rbp)
cmpl $0x0, -0x38(%rbp)
jg 0x78a37
movl -0x38(%rbp), %eax
movl %eax, -0x3c(%rbp)
jmp 0x78a4c
movl -0x38(%rbp), %eax
andl $0xffff, %eax           # imm = 0xFFFF
orl $0x8000000, %eax        # imm = 0x8000000
orl $0x80000000, %eax       # imm = 0x80000000
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jne 0x78a65
movq -0x10(%rbp), %rax
movl 0x12c(%rax), %eax
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jne 0x78a78
movq -0x10(%rbp), %rax
movl 0x370(%rax), %eax
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jne 0x78a8b
movq -0x10(%rbp), %rax
movl 0x198(%rax), %eax
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
je 0x78a9a
movq -0x10(%rbp), %rdi
callq 0x786a0
movl -0x20(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax)