// File: /workspace/github_c_makefile_star2_O0/ukontainer[P]sqlite-bench/sqlite3.c
// Function: walCheckpoint
static int walCheckpoint(
  Wal *pWal,                      /* Wal connection */
  sqlite3 *db,                    /* Check for interrupts on this handle */
  int eMode,                      /* One of PASSIVE, FULL or RESTART */
  int (*xBusy)(void*),            /* Function to call when busy */
  void *pBusyArg,                 /* Context argument for xBusyHandler */
  int sync_flags,                 /* Flags for OsSync() (or 0) */
  u8 *zBuf                        /* Temporary buffer to use */
){
  int rc = SQLITE_OK;             /* Return code */
  int szPage;                     /* Database page-size */
  WalIterator *pIter = 0;         /* Wal iterator context */
  u32 iDbpage = 0;                /* Next database page to write */
  u32 iFrame = 0;                 /* Wal frame containing data for iDbpage */
  u32 mxSafeFrame;                /* Max frame that can be backfilled */
  u32 mxPage;                     /* Max database page to write */
  int i;                          /* Loop counter */
  volatile WalCkptInfo *pInfo;    /* The checkpoint status information */

  szPage = walPagesize(pWal);
  testcase( szPage<=32768 );
  testcase( szPage>=65536 );
  pInfo = walCkptInfo(pWal);
  if( pInfo->nBackfill<pWal->hdr.mxFrame ){

    /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
    ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
    assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );

    /* Compute in mxSafeFrame the index of the last frame of the WAL that is
    ** safe to write into the database.  Frames beyond mxSafeFrame might
    ** overwrite database pages that are in use by active readers and thus
    ** cannot be backfilled from the WAL.
    */
    mxSafeFrame = pWal->hdr.mxFrame;
    mxPage = pWal->hdr.nPage;
    for(i=1; i<WAL_NREADER; i++){
      /* Thread-sanitizer reports that the following is an unsafe read,
      ** as some other thread may be in the process of updating the value
      ** of the aReadMark[] slot. The assumption here is that if that is
      ** happening, the other client may only be increasing the value,
      ** not decreasing it. So assuming either that either the "old" or
      ** "new" version of the value is read, and not some arbitrary value
      ** that would never be written by a real client, things are still 
      ** safe.  */
      u32 y = pInfo->aReadMark[i];
      if( mxSafeFrame>y ){
        assert( y<=pWal->hdr.mxFrame );
        rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
        if( rc==SQLITE_OK ){
          pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
          walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
        }else if( rc==SQLITE_BUSY ){
          mxSafeFrame = y;
          xBusy = 0;
        }else{
          goto walcheckpoint_out;
        }
      }
    }

    /* Allocate the iterator */
    if( pInfo->nBackfill<mxSafeFrame ){
      rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
      assert( rc==SQLITE_OK || pIter==0 );
    }

    if( pIter
     && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
    ){
      u32 nBackfill = pInfo->nBackfill;

      pInfo->nBackfillAttempted = mxSafeFrame;

      /* Sync the WAL to disk */
      rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));

      /* If the database may grow as a result of this checkpoint, hint
      ** about the eventual size of the db file to the VFS layer.
      */
      if( rc==SQLITE_OK ){
        i64 nReq = ((i64)mxPage * szPage);
        i64 nSize;                    /* Current size of database file */
        rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
        if( rc==SQLITE_OK && nSize<nReq ){
          sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
        }
      }


      /* Iterate through the contents of the WAL, copying data to the db file */
      while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
        i64 iOffset;
        assert( walFramePgno(pWal, iFrame)==iDbpage );
        if( db->u1.isInterrupted ){
          rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
          break;
        }
        if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
          continue;
        }
        iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
        /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
        rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
        if( rc!=SQLITE_OK ) break;
        iOffset = (iDbpage-1)*(i64)szPage;
        testcase( IS_BIG_INT(iOffset) );
        rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
        if( rc!=SQLITE_OK ) break;
      }

      /* If work was actually accomplished... */
      if( rc==SQLITE_OK ){
        if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
          i64 szDb = pWal->hdr.nPage*(i64)szPage;
          testcase( IS_BIG_INT(szDb) );
          rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
          if( rc==SQLITE_OK ){
            rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
          }
        }
        if( rc==SQLITE_OK ){
          pInfo->nBackfill = mxSafeFrame;
        }
      }

      /* Release the reader lock held while backfilling */
      walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
    }

    if( rc==SQLITE_BUSY ){
      /* Reset the return code so as not to report a checkpoint failure
      ** just because there are active readers.  */
      rc = SQLITE_OK;
    }
  }

  /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the
  ** entire wal file has been copied into the database file, then block 
  ** until all readers have finished using the wal file. This ensures that 
  ** the next process to write to the database restarts the wal file.
  */
  if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
    assert( pWal->writeLock );
    if( pInfo->nBackfill<pWal->hdr.mxFrame ){
      rc = SQLITE_BUSY;
    }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
      u32 salt1;
      sqlite3_randomness(4, &salt1);
      assert( pInfo->nBackfill==pWal->hdr.mxFrame );
      rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
      if( rc==SQLITE_OK ){
        if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){
          /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as
          ** SQLITE_CHECKPOINT_RESTART with the addition that it also
          ** truncates the log file to zero bytes just prior to a
          ** successful return.
          **
          ** In theory, it might be safe to do this without updating the
          ** wal-index header in shared memory, as all subsequent reader or
          ** writer clients should see that the entire log file has been
          ** checkpointed and behave accordingly. This seems unsafe though,
          ** as it would leave the system in a state where the contents of
          ** the wal-index header do not match the contents of the 
          ** file-system. To avoid this, update the wal-index header to
          ** indicate that the log file contains zero valid frames.  */
          walRestartHdr(pWal, salt1);
          rc = sqlite3OsTruncate(pWal->pWalFd, 0);
        }
        walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
      }
    }
  }

 walcheckpoint_out:
  walIteratorFree(pIter);
  return rc;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movl %r9d, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
movq $0x0, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
movl $0x0, -0x48(%rbp)
movq -0x8(%rbp), %rdi
callq 0x42a850
movl %eax, -0x34(%rbp)
movq -0x8(%rbp), %rdi
callq 0x4237f0
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movl (%rax), %eax
movq -0x8(%rbp), %rcx
cmpl 0x58(%rcx), %eax
jae 0x42ac53
movq -0x8(%rbp), %rax
movl 0x58(%rax), %eax
movl %eax, -0x4c(%rbp)
movq -0x8(%rbp), %rax
movl 0x5c(%rax), %eax
movl %eax, -0x50(%rbp)
movl $0x1, -0x54(%rbp)
cmpl $0x5, -0x54(%rbp)
jge 0x42a9ca
movq -0x60(%rbp), %rax
movslq -0x54(%rbp), %rcx
movl 0x4(%rax,%rcx,4), %eax
movl %eax, -0x64(%rbp)
movl -0x4c(%rbp), %eax
cmpl -0x64(%rbp), %eax
jbe 0x42a9ba
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
movl -0x54(%rbp), %ecx
addl $0x3, %ecx
movl $0x1, %r8d
callq 0x42a7e0
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
jne 0x42a99b
cmpl $0x1, -0x54(%rbp)
jne 0x42a966
movl -0x4c(%rbp), %eax
movl %eax, -0x90(%rbp)
jmp 0x42a973
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, -0x90(%rbp)
jmp 0x42a973
movl -0x90(%rbp), %edx
movq -0x60(%rbp), %rax
movslq -0x54(%rbp), %rcx
movl %edx, 0x4(%rax,%rcx,4)
movq -0x8(%rbp), %rdi
movl -0x54(%rbp), %esi
addl $0x3, %esi
movl $0x1, %edx
callq 0x423930
jmp 0x42a9b8
cmpl $0x5, -0x30(%rbp)
jne 0x42a9b1
movl -0x64(%rbp), %eax
movl %eax, -0x4c(%rbp)
movq $0x0, -0x20(%rbp)
jmp 0x42a9b6
jmp 0x42acfa
jmp 0x42a9b8
jmp 0x42a9ba
jmp 0x42a9bc
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x42a90a
movq -0x60(%rbp), %rax
movl (%rax), %eax
cmpl -0x4c(%rbp), %eax
jae 0x42a9eb
movq -0x8(%rbp), %rdi
movq -0x60(%rbp), %rax
movl (%rax), %esi
leaq -0x40(%rbp), %rdx
callq 0x42ad10
movl %eax, -0x30(%rbp)
cmpq $0x0, -0x40(%rbp)
je 0x42ac44
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
movl $0x3, %ecx
movl $0x1, %r8d
callq 0x42a7e0
movl %eax, -0x30(%rbp)
cmpl $0x0, %eax
jne 0x42ac44
movq -0x60(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x68(%rbp)
movl -0x4c(%rbp), %ecx
movq -0x60(%rbp), %rax
movl %ecx, 0x20(%rax)
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdi
movl -0x2c(%rbp), %esi
sarl $0x2, %esi
andl $0x3, %esi
callq 0x423190
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
jne 0x42aa9b
movl -0x50(%rbp), %eax
movslq -0x34(%rbp), %rcx
imulq %rcx, %rax
movq %rax, -0x70(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
leaq -0x78(%rbp), %rsi
callq 0x424b90
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
jne 0x42aa99
movq -0x78(%rbp), %rax
cmpq -0x70(%rbp), %rax
jge 0x42aa99
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movl $0x5, %esi
leaq -0x70(%rbp), %rdx
callq 0x420d50
jmp 0x42aa9b
jmp 0x42aa9d
xorl %eax, %eax
cmpl $0x0, -0x30(%rbp)
movb %al, -0x91(%rbp)
jne 0x42aacb
movq -0x40(%rbp), %rdi
leaq -0x44(%rbp), %rsi
leaq -0x48(%rbp), %rdx
callq 0x42af80
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
sete %al
movb %al, -0x91(%rbp)
movb -0x91(%rbp), %al
testb $0x1, %al
jne 0x42aada
jmp 0x42aba6
movq -0x10(%rbp), %rax
movl 0x158(%rax), %eax
cmpl $0x0, %eax
je 0x42ab09
movq -0x10(%rbp), %rax
movzbl 0x61(%rax), %edx
movl $0x9, %eax
movl $0x7, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movl %eax, -0x30(%rbp)
jmp 0x42aba6
movl -0x48(%rbp), %eax
cmpl -0x68(%rbp), %eax
jbe 0x42ab21
movl -0x48(%rbp), %eax
cmpl -0x4c(%rbp), %eax
ja 0x42ab21
movl -0x44(%rbp), %eax
cmpl -0x50(%rbp), %eax
jbe 0x42ab26
jmp 0x42aa9d
movl -0x48(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
movl -0x34(%rbp), %ecx
addl $0x18, %ecx
movslq %ecx, %rcx
imulq %rcx, %rax
addq $0x20, %rax
addq $0x18, %rax
movq %rax, -0x80(%rbp)
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdi
movq 0x10(%rbp), %rsi
movl -0x34(%rbp), %edx
movq -0x80(%rbp), %rcx
callq 0x424bc0
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
je 0x42ab6a
jmp 0x42aba6
movl -0x44(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
movslq -0x34(%rbp), %rcx
imulq %rcx, %rax
movq %rax, -0x80(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq 0x10(%rbp), %rsi
movl -0x34(%rbp), %edx
movq -0x80(%rbp), %rcx
callq 0x40c1f0
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
je 0x42aba1
jmp 0x42aba6
jmp 0x42aa9d
cmpl $0x0, -0x30(%rbp)
jne 0x42ac31
movl -0x4c(%rbp), %eax
movl %eax, -0x98(%rbp)
movq -0x8(%rbp), %rdi
callq 0x422f10
movq %rax, %rcx
movl -0x98(%rbp), %eax
movl 0x10(%rcx), %ecx
cmpl %ecx, %eax
jne 0x42ac20
movq -0x8(%rbp), %rax
movl 0x5c(%rax), %eax
movslq -0x34(%rbp), %rcx
imulq %rcx, %rax
movq %rax, -0x88(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x88(%rbp), %rsi
callq 0x4251b0
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
jne 0x42ac1e
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movl -0x2c(%rbp), %esi
sarl $0x2, %esi
andl $0x3, %esi
callq 0x423190
movl %eax, -0x30(%rbp)
jmp 0x42ac20
cmpl $0x0, -0x30(%rbp)
jne 0x42ac2f
movl -0x4c(%rbp), %ecx
movq -0x60(%rbp), %rax
movl %ecx, (%rax)
jmp 0x42ac31
movq -0x8(%rbp), %rdi
movl $0x3, %esi
movl $0x1, %edx
callq 0x423930
cmpl $0x5, -0x30(%rbp)
jne 0x42ac51
movl $0x0, -0x30(%rbp)
jmp 0x42ac53
cmpl $0x0, -0x30(%rbp)
jne 0x42acf8
cmpl $0x0, -0x14(%rbp)
je 0x42acf8
movq -0x60(%rbp), %rax
movl (%rax), %eax
movq -0x8(%rbp), %rcx
cmpl 0x58(%rcx), %eax
jae 0x42ac7f
movl $0x5, -0x30(%rbp)
jmp 0x42acf6
cmpl $0x2, -0x14(%rbp)
jl 0x42acf4
movl $0x4, %edi
leaq -0x8c(%rbp), %rsi
callq 0x409470
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
movl $0x4, %r8d
movl %r8d, %ecx
callq 0x42a7e0
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
jne 0x42acf2
cmpl $0x3, -0x14(%rbp)
jne 0x42ace2
movq -0x8(%rbp), %rdi
movl -0x8c(%rbp), %esi
callq 0x423860
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4251b0
movl %eax, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movl $0x4, %edx
movl %edx, %esi
callq 0x423930
jmp 0x42acf4
jmp 0x42acf6
jmp 0x42acf8
jmp 0x42acfa
movq -0x40(%rbp), %rdi
callq 0x42b080
movl -0x30(%rbp), %eax
addq $0xa0, %rsp
popq %rbp
retq
nop