// File: /workspace/github_c_makefile_star2_O1/barabo[P]advanced-shell-history/src/sqlite3.c
// Function: walTryBeginRead
static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
  volatile WalCkptInfo *pInfo;    /* Checkpoint information in wal-index */
  u32 mxReadMark;                 /* Largest aReadMark[] value */
  int mxI;                        /* Index of largest aReadMark[] value */
  int i;                          /* Loop counter */
  int rc = SQLITE_OK;             /* Return code  */

  assert( pWal->readLock<0 );     /* Not currently locked */

  /* Take steps to avoid spinning forever if there is a protocol error.
  **
  ** Circumstances that cause a RETRY should only last for the briefest
  ** instances of time.  No I/O or other system calls are done while the
  ** locks are held, so the locks should not be held for very long. But 
  ** if we are unlucky, another process that is holding a lock might get
  ** paged out or take a page-fault that is time-consuming to resolve, 
  ** during the few nanoseconds that it is holding the lock.  In that case,
  ** it might take longer than normal for the lock to free.
  **
  ** After 5 RETRYs, we begin calling sqlite3OsSleep().  The first few
  ** calls to sqlite3OsSleep() have a delay of 1 microsecond.  Really this
  ** is more of a scheduler yield than an actual delay.  But on the 10th
  ** an subsequent retries, the delays start becoming longer and longer, 
  ** so that on the 100th (and last) RETRY we delay for 21 milliseconds.
  ** The total delay time before giving up is less than 1 second.
  */
  if( cnt>5 ){
    int nDelay = 1;                      /* Pause time in microseconds */
    if( cnt>100 ){
      VVA_ONLY( pWal->lockError = 1; )
      return SQLITE_PROTOCOL;
    }
    if( cnt>=10 ) nDelay = (cnt-9)*238;  /* Max delay 21ms. Total delay 996ms */
    sqlite3OsSleep(pWal->pVfs, nDelay);
  }

  if( !useWal ){
    rc = walIndexReadHdr(pWal, pChanged);
    if( rc==SQLITE_BUSY ){
      /* If there is not a recovery running in another thread or process
      ** then convert BUSY errors to WAL_RETRY.  If recovery is known to
      ** be running, convert BUSY to BUSY_RECOVERY.  There is a race here
      ** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY
      ** would be technically correct.  But the race is benign since with
      ** WAL_RETRY this routine will be called again and will probably be
      ** right on the second iteration.
      */
      if( pWal->apWiData[0]==0 ){
        /* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
        ** We assume this is a transient condition, so return WAL_RETRY. The
        ** xShmMap() implementation used by the default unix and win32 VFS 
        ** modules may return SQLITE_BUSY due to a race condition in the 
        ** code that determines whether or not the shared-memory region 
        ** must be zeroed before the requested page is returned.
        */
        rc = WAL_RETRY;
      }else if( SQLITE_OK==(rc = walLockShared(pWal, WAL_RECOVER_LOCK)) ){
        walUnlockShared(pWal, WAL_RECOVER_LOCK);
        rc = WAL_RETRY;
      }else if( rc==SQLITE_BUSY ){
        rc = SQLITE_BUSY_RECOVERY;
      }
    }
    if( rc!=SQLITE_OK ){
      return rc;
    }
  }

  pInfo = walCkptInfo(pWal);
  if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){
    /* The WAL has been completely backfilled (or it is empty).
    ** and can be safely ignored.
    */
    rc = walLockShared(pWal, WAL_READ_LOCK(0));
    walShmBarrier(pWal);
    if( rc==SQLITE_OK ){
      if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
        /* It is not safe to allow the reader to continue here if frames
        ** may have been appended to the log before READ_LOCK(0) was obtained.
        ** When holding READ_LOCK(0), the reader ignores the entire log file,
        ** which implies that the database file contains a trustworthy
        ** snapshoT. Since holding READ_LOCK(0) prevents a checkpoint from
        ** happening, this is usually correct.
        **
        ** However, if frames have been appended to the log (or if the log 
        ** is wrapped and written for that matter) before the READ_LOCK(0)
        ** is obtained, that is not necessarily true. A checkpointer may
        ** have started to backfill the appended frames but crashed before
        ** it finished. Leaving a corrupt image in the database file.
        */
        walUnlockShared(pWal, WAL_READ_LOCK(0));
        return WAL_RETRY;
      }
      pWal->readLock = 0;
      return SQLITE_OK;
    }else if( rc!=SQLITE_BUSY ){
      return rc;
    }
  }

  /* If we get this far, it means that the reader will want to use
  ** the WAL to get at content from recent commits.  The job now is
  ** to select one of the aReadMark[] entries that is closest to
  ** but not exceeding pWal->hdr.mxFrame and lock that entry.
  */
  mxReadMark = 0;
  mxI = 0;
  for(i=1; i<WAL_NREADER; i++){
    u32 thisMark = pInfo->aReadMark[i];
    if( mxReadMark<=thisMark && thisMark<=pWal->hdr.mxFrame ){
      assert( thisMark!=READMARK_NOT_USED );
      mxReadMark = thisMark;
      mxI = i;
    }
  }
  /* There was once an "if" here. The extra "{" is to preserve indentation. */
  {
    if( (pWal->readOnly & WAL_SHM_RDONLY)==0
     && (mxReadMark<pWal->hdr.mxFrame || mxI==0)
    ){
      for(i=1; i<WAL_NREADER; i++){
        rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
        if( rc==SQLITE_OK ){
          mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame;
          mxI = i;
          walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
          break;
        }else if( rc!=SQLITE_BUSY ){
          return rc;
        }
      }
    }
    if( mxI==0 ){
      assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
      return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
    }

    rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
    if( rc ){
      return rc==SQLITE_BUSY ? WAL_RETRY : rc;
    }
    /* Now that the read-lock has been obtained, check that neither the
    ** value in the aReadMark[] array or the contents of the wal-index
    ** header have changed.
    **
    ** It is necessary to check that the wal-index header did not change
    ** between the time it was read and when the shared-lock was obtained
    ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
    ** that the log file may have been wrapped by a writer, or that frames
    ** that occur later in the log than pWal->hdr.mxFrame may have been
    ** copied into the database by a checkpointer. If either of these things
    ** happened, then reading the database with the current value of
    ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
    ** instead.
    **
    ** This does not guarantee that the copy of the wal-index header is up to
    ** date before proceeding. That would not be possible without somehow
    ** blocking writers. It only guarantees that a dangerous checkpoint or 
    ** log-wrap (either of which would require an exclusive lock on
    ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
    */
    walShmBarrier(pWal);
    if( pInfo->aReadMark[mxI]!=mxReadMark
     || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
    ){
      walUnlockShared(pWal, WAL_READ_LOCK(mxI));
      return WAL_RETRY;
    }else{
      assert( mxReadMark<=pWal->hdr.mxFrame );
      pWal->readLock = (i16)mxI;
    }
  }
  return rc;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl %edx, %r15d
movq %rsi, %r12
movq %rdi, %rbx
cmpl $0x6, %ecx
jl 0x1bc88
movl $0xf, %edx
cmpl $0x64, %ecx
jg 0x1bf3e
imull $0xee, %ecx, %eax
addl $0xfffff7a2, %eax       # imm = 0xFFFFF7A2
cmpl $0xa, %ecx
movl $0x1, %esi
cmovgel %eax, %esi
movq (%rbx), %rdi
callq *0x70(%rdi)
testl %r15d, %r15d
je 0x1bdc7
xorl %r14d, %r14d
movq 0x30(%rbx), %rax
movq (%rax), %r12
movl $0x0, %edx
testl %r15d, %r15d
jne 0x1bd3a
movl 0x60(%r12), %eax
cmpl 0x58(%rbx), %eax
jne 0x1bd3a
xorl %edx, %edx
cmpb $0x0, 0x3f(%rbx)
jne 0x1bcda
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl $0x3, %esi
movl $0x1, %edx
movl $0x6, %ecx
callq *0x70(%rax)
movl %eax, %edx
cmpb $0x2, 0x3f(%rbx)
je 0x1bcf0
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl %edx, %r15d
callq *0x78(%rax)
movl %r15d, %edx
cmpl $0x5, %edx
je 0x1bd3a
testl %edx, %edx
jne 0x1bf3e
leaq 0x48(%rbx), %rsi
movq 0x30(%rbx), %rax
movq (%rax), %rdi
movl $0x30, %edx
callq 0x8410
testl %eax, %eax
je 0x1bf56
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
cmpb $0x0, 0x3f(%rbx)
jne 0x1bf3e
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl $0x3, %esi
jmp 0x1befe
xorl %eax, %eax
xorl %r15d, %r15d
movl 0x68(%r12,%rax,4), %ecx
cmpl %ecx, %r15d
ja 0x1bd57
cmpl 0x58(%rbx), %ecx
cmovbel %ecx, %r15d
leal 0x1(%rax), %ecx
cmovbel %ecx, %r14d
incq %rax
cmpq $0x4, %rax
jne 0x1bd3f
testb $0x2, 0x42(%rbx)
jne 0x1be61
cmpl 0x58(%rbx), %r15d
jb 0x1bd79
testl %r14d, %r14d
jne 0x1be61
xorl %r13d, %r13d
movq %rbx, -0x30(%rbp)
leaq 0x4(%r13), %rsi
cmpb $0x0, 0x3f(%rbx)
movl $0x0, %edx
jne 0x1bdaf
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movq %rsi, %rbx
movl $0x1, %edx
movl $0xa, %ecx
callq *0x70(%rax)
movq %rbx, %rsi
movq -0x30(%rbp), %rbx
movl %eax, %edx
cmpl $0x5, %edx
jne 0x1be2e
incq %r13
cmpl $0x4, %r13d
jne 0x1bd80
movl $0x5, %edx
jmp 0x1be61
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1bf60
movl %eax, %edx
cmpl $0x5, %eax
jne 0x1bf36
movq 0x30(%rbx), %rax
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
cmpq $0x0, (%rax)
je 0x1bf36
xorl %eax, %eax
cmpb $0x0, 0x3f(%rbx)
jne 0x1be16
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl $0x2, %esi
movl $0x1, %edx
movl $0x6, %ecx
callq *0x70(%rax)
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
testl %eax, %eax
je 0x1bf12
cmpl $0x5, %eax
movl $0x105, %edx            # imm = 0x105
cmovnel %eax, %edx
jmp 0x1bf36
testl %edx, %edx
jne 0x1bf3e
movl 0x58(%rbx), %r15d
movl %r15d, 0x68(%r12,%r13,4)
incq %r13
cmpb $0x0, 0x3f(%rbx)
jne 0x1be5c
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl $0x1, %edx
movl $0x9, %ecx
callq *0x70(%rax)
xorl %edx, %edx
movl %r13d, %r14d
testl %r14d, %r14d
je 0x1be9d
leal 0x3(%r14), %r13d
xorl %eax, %eax
cmpb $0x0, 0x3f(%rbx)
jne 0x1be89
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl %r13d, %esi
movl $0x1, %edx
movl $0x6, %ecx
callq *0x70(%rax)
testl %eax, %eax
je 0x1beb3
cmpl $0x5, %eax
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
cmovnel %eax, %edx
jmp 0x1bf3e
xorl %eax, %eax
cmpl $0x5, %edx
sete %al
negl %eax
orl $0x208, %eax            # imm = 0x208
movl %eax, %edx
jmp 0x1bf3e
cmpb $0x2, 0x3f(%rbx)
je 0x1bec3
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
callq *0x78(%rax)
movslq %r14d, %rax
movl 0x64(%r12,%rax,4), %eax
cmpl %r15d, %eax
jne 0x1bee9
movq 0x30(%rbx), %rax
movq (%rax), %rdi
leaq 0x48(%rbx), %rsi
movl $0x30, %edx
callq 0x8410
testl %eax, %eax
je 0x1bf4f
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
cmpb $0x0, 0x3f(%rbx)
jne 0x1bf3e
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl %r13d, %esi
movl $0x1, %edx
movl $0x5, %ecx
callq *0x70(%rax)
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
jmp 0x1bf3e
cmpb $0x0, 0x3f(%rbx)
jne 0x1bf36
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl $0x2, %esi
movl $0x1, %edx
movl $0x5, %ecx
callq *0x70(%rax)
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
testl %edx, %edx
je 0x1bc91
movl %edx, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movw %r14w, 0x3c(%rbx)
jmp 0x1bf5c
movw $0x0, 0x3c(%rbx)
xorl %edx, %edx
jmp 0x1bf3e