// File: /workspace/github_c_makefile_star2_O0/coyove[P]chann/./lib/unqlite/unqlite.c
// Function: unixLock
static int unixLock(unqlite_file *id, int eFileLock){
  /* The following describes the implementation of the various locks and
  ** lock transitions in terms of the POSIX advisory shared and exclusive
  ** lock primitives (called read-locks and write-locks below, to avoid
  ** confusion with SQLite lock names). The algorithms are complicated
  ** slightly in order to be compatible with unixdows systems simultaneously
  ** accessing the same database file, in case that is ever required.
  **
  ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
  ** byte', each single bytes at well known offsets, and the 'shared byte
  ** range', a range of 510 bytes at a well known offset.
  **
  ** To obtain a SHARED lock, a read-lock is obtained on the 'pending
  ** byte'.  If this is successful, a random byte from the 'shared byte
  ** range' is read-locked and the lock on the 'pending byte' released.
  **
  ** A process may only obtain a RESERVED lock after it has a SHARED lock.
  ** A RESERVED lock is implemented by grabbing a write-lock on the
  ** 'reserved byte'. 
  **
  ** A process may only obtain a PENDING lock after it has obtained a
  ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
  ** on the 'pending byte'. This ensures that no new SHARED locks can be
  ** obtained, but existing SHARED locks are allowed to persist. A process
  ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
  ** This property is used by the algorithm for rolling back a journal file
  ** after a crash.
  **
  ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
  ** implemented by obtaining a write-lock on the entire 'shared byte
  ** range'. Since all other locks require a read-lock on one of the bytes
  ** within this range, this ensures that no other locks are held on the
  ** database. 
  **
  ** The reason a single byte cannot be used instead of the 'shared byte
  ** range' is that some versions of unixdows do not support read-locks. By
  ** locking a random byte from a range, concurrent SHARED locks may exist
  ** even if the locking primitive used is always a write-lock.
  */
  int rc = UNQLITE_OK;
  unixFile *pFile = (unixFile*)id;
  unixInodeInfo *pInode = pFile->pInode;
  struct flock lock;
  int s = 0;
  int tErrno = 0;

  /* If there is already a lock of this type or more restrictive on the
  ** unixFile, do nothing. Don't use the end_lock: exit path, as
  ** unixEnterMutex() hasn't been called yet.
  */
  if( pFile->eFileLock>=eFileLock ){
    return UNQLITE_OK;
  }
  /* This mutex is needed because pFile->pInode is shared across threads
  */
  unixEnterMutex();
  pInode = pFile->pInode;

  /* If some thread using this PID has a lock via a different unixFile*
  ** handle that precludes the requested lock, return BUSY.
  */
  if( (pFile->eFileLock!=pInode->eFileLock && 
          (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
  ){
    rc = UNQLITE_BUSY;
    goto end_lock;
  }

  /* If a SHARED lock is requested, and some thread using this PID already
  ** has a SHARED or RESERVED lock, then increment reference counts and
  ** return UNQLITE_OK.
  */
  if( eFileLock==SHARED_LOCK && 
      (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
    pFile->eFileLock = SHARED_LOCK;
    pInode->nShared++;
    pInode->nLock++;
    goto end_lock;
  }
  /* A PENDING lock is needed before acquiring a SHARED lock and before
  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
  ** be released.
  */
  lock.l_len = 1L;
  lock.l_whence = SEEK_SET;
  if( eFileLock==SHARED_LOCK 
      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
  ){
    lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
    lock.l_start = PENDING_BYTE;
    s = fcntl(pFile->h, F_SETLK, &lock);
    if( s==(-1) ){
      tErrno = errno;
      rc = unqliteErrorFromPosixError(tErrno, UNQLITE_LOCKERR);
      if( IS_LOCK_ERROR(rc) ){
        pFile->lastErrno = tErrno;
      }
      goto end_lock;
    }
  }
  /* If control gets to this point, then actually go ahead and make
  ** operating system calls for the specified lock.
  */
  if( eFileLock==SHARED_LOCK ){
    /* Now get the read-lock */
    lock.l_start = SHARED_FIRST;
    lock.l_len = SHARED_SIZE;
    if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){
      tErrno = errno;
    }
    /* Drop the temporary PENDING lock */
    lock.l_start = PENDING_BYTE;
    lock.l_len = 1L;
    lock.l_type = F_UNLCK;
    if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
      if( s != -1 ){
        /* This could happen with a network mount */
        tErrno = errno; 
        rc = unqliteErrorFromPosixError(tErrno, UNQLITE_LOCKERR); 
        if( IS_LOCK_ERROR(rc) ){
          pFile->lastErrno = tErrno;
        }
        goto end_lock;
      }
    }
    if( s==(-1) ){
		rc = unqliteErrorFromPosixError(tErrno, UNQLITE_LOCKERR);
      if( IS_LOCK_ERROR(rc) ){
        pFile->lastErrno = tErrno;
      }
    }else{
      pFile->eFileLock = SHARED_LOCK;
      pInode->nLock++;
      pInode->nShared = 1;
    }
  }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
    /* We are trying for an exclusive lock but another thread in this
    ** same process is still holding a shared lock. */
    rc = UNQLITE_BUSY;
  }else{
    /* The request was for a RESERVED or EXCLUSIVE lock.  It is
    ** assumed that there is a SHARED or greater lock on the file
    ** already.
    */
    lock.l_type = F_WRLCK;
    switch( eFileLock ){
      case RESERVED_LOCK:
        lock.l_start = RESERVED_BYTE;
        break;
      case EXCLUSIVE_LOCK:
        lock.l_start = SHARED_FIRST;
        lock.l_len = SHARED_SIZE;
        break;
      default:
		  /* Can't happen */
        break;
    }
    s = fcntl(pFile->h, F_SETLK, &lock);
    if( s==(-1) ){
      tErrno = errno;
      rc = unqliteErrorFromPosixError(tErrno, UNQLITE_LOCKERR);
      if( IS_LOCK_ERROR(rc) ){
        pFile->lastErrno = tErrno;
      }
    }
  }
  if( rc==UNQLITE_OK ){
    pFile->eFileLock = eFileLock;
    pInode->eFileLock = eFileLock;
  }else if( eFileLock==EXCLUSIVE_LOCK ){
    pFile->eFileLock = PENDING_LOCK;
    pInode->eFileLock = PENDING_LOCK;
  }
end_lock:
  unixLeaveMutex();
  return rc;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movl $0x0, -0x4c(%rbp)
movl $0x0, -0x50(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x18(%rax), %eax
cmpl -0x14(%rbp), %eax
jl 0x5c741
movl $0x0, -0x4(%rbp)
jmp 0x5ca56
callq 0x5bec0
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x18(%rax), %eax
movq -0x28(%rbp), %rcx
cmpl 0x14(%rcx), %eax
je 0x5c77f
movq -0x28(%rbp), %rax
cmpl $0x3, 0x14(%rax)
jge 0x5c773
cmpl $0x1, -0x14(%rbp)
jle 0x5c77f
movl $0xfffffff2, -0x18(%rbp) # imm = 0xFFFFFFF2
jmp 0x5ca4b
cmpl $0x1, -0x14(%rbp)
jne 0x5c7c0
movq -0x28(%rbp), %rax
cmpl $0x1, 0x14(%rax)
je 0x5c799
movq -0x28(%rbp), %rax
cmpl $0x2, 0x14(%rax)
jne 0x5c7c0
movq -0x20(%rbp), %rax
movb $0x1, 0x18(%rax)
movq -0x28(%rbp), %rax
movl 0x10(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x10(%rax)
movq -0x28(%rbp), %rax
movl 0x1c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x1c(%rax)
jmp 0x5ca4b
movq $0x1, -0x38(%rbp)
movw $0x0, -0x46(%rbp)
cmpl $0x1, -0x14(%rbp)
je 0x5c7eb
cmpl $0x4, -0x14(%rbp)
jne 0x5c85e
movq -0x20(%rbp), %rax
movzbl 0x18(%rax), %eax
cmpl $0x3, %eax
jge 0x5c85e
movl -0x14(%rbp), %edx
movl $0x1, %eax
xorl %ecx, %ecx
cmpl $0x1, %edx
cmovel %ecx, %eax
movw %ax, -0x48(%rbp)
movq $0x40000000, -0x40(%rbp) # imm = 0x40000000
movq -0x20(%rbp), %rax
movl 0x10(%rax), %edi
movl $0x6, %esi
leaq -0x48(%rbp), %rdx
movb $0x0, %al
callq 0xd230
movl %eax, -0x4c(%rbp)
cmpl $-0x1, -0x4c(%rbp)
jne 0x5c85c
callq 0xdcc0
movl (%rax), %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %edi
movl $0xffffffb4, %esi       # imm = 0xFFFFFFB4
callq 0x5cf90
movl %eax, -0x18(%rbp)
cmpl $0x0, -0x18(%rbp)
je 0x5c857
cmpl $-0xe, -0x18(%rbp)
je 0x5c857
movl -0x50(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x1c(%rax)
jmp 0x5ca4b
jmp 0x5c85e
cmpl $0x1, -0x14(%rbp)
jne 0x5c963
movq $0x40000002, -0x40(%rbp) # imm = 0x40000002
movq $0x1fe, -0x38(%rbp)     # imm = 0x1FE
movq -0x20(%rbp), %rax
movl 0x10(%rax), %edi
movl $0x6, %esi
leaq -0x48(%rbp), %rdx
movb $0x0, %al
callq 0xd230
movl %eax, -0x4c(%rbp)
cmpl $-0x1, %eax
jne 0x5c8a1
callq 0xdcc0
movl (%rax), %eax
movl %eax, -0x50(%rbp)
movq $0x40000000, -0x40(%rbp) # imm = 0x40000000
movq $0x1, -0x38(%rbp)
movw $0x2, -0x48(%rbp)
movq -0x20(%rbp), %rax
movl 0x10(%rax), %edi
movl $0x6, %esi
leaq -0x48(%rbp), %rdx
movb $0x0, %al
callq 0xd230
cmpl $0x0, %eax
je 0x5c910
cmpl $-0x1, -0x4c(%rbp)
je 0x5c90e
callq 0xdcc0
movl (%rax), %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %edi
movl $0xffffffb4, %esi       # imm = 0xFFFFFFB4
callq 0x5cf90
movl %eax, -0x18(%rbp)
cmpl $0x0, -0x18(%rbp)
je 0x5c909
cmpl $-0xe, -0x18(%rbp)
je 0x5c909
movl -0x50(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x1c(%rax)
jmp 0x5ca4b
jmp 0x5c910
cmpl $-0x1, -0x4c(%rbp)
jne 0x5c93e
movl -0x50(%rbp), %edi
movl $0xffffffb4, %esi       # imm = 0xFFFFFFB4
callq 0x5cf90
movl %eax, -0x18(%rbp)
cmpl $0x0, -0x18(%rbp)
je 0x5c93c
cmpl $-0xe, -0x18(%rbp)
je 0x5c93c
movl -0x50(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x1c(%rax)
jmp 0x5c95e
movq -0x20(%rbp), %rax
movb $0x1, 0x18(%rax)
movq -0x28(%rbp), %rax
movl 0x1c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x1c(%rax)
movq -0x28(%rbp), %rax
movl $0x1, 0x10(%rax)
jmp 0x5ca10
cmpl $0x4, -0x14(%rbp)
jne 0x5c97f
movq -0x28(%rbp), %rax
cmpl $0x1, 0x10(%rax)
jle 0x5c97f
movl $0xfffffff2, -0x18(%rbp) # imm = 0xFFFFFFF2
jmp 0x5ca0e
movw $0x1, -0x48(%rbp)
movl -0x14(%rbp), %eax
movl %eax, -0x54(%rbp)
subl $0x2, %eax
je 0x5c99c
jmp 0x5c992
movl -0x54(%rbp), %eax
subl $0x4, %eax
je 0x5c9a6
jmp 0x5c9b8
movq $0x40000001, -0x40(%rbp) # imm = 0x40000001
jmp 0x5c9ba
movq $0x40000002, -0x40(%rbp) # imm = 0x40000002
movq $0x1fe, -0x38(%rbp)     # imm = 0x1FE
jmp 0x5c9ba
jmp 0x5c9ba
movq -0x20(%rbp), %rax
movl 0x10(%rax), %edi
movl $0x6, %esi
leaq -0x48(%rbp), %rdx
movb $0x0, %al
callq 0xd230
movl %eax, -0x4c(%rbp)
cmpl $-0x1, -0x4c(%rbp)
jne 0x5ca0c
callq 0xdcc0
movl (%rax), %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %edi
movl $0xffffffb4, %esi       # imm = 0xFFFFFFB4
callq 0x5cf90
movl %eax, -0x18(%rbp)
cmpl $0x0, -0x18(%rbp)
je 0x5ca0a
cmpl $-0xe, -0x18(%rbp)
je 0x5ca0a
movl -0x50(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x1c(%rax)
jmp 0x5ca0c
jmp 0x5ca0e
jmp 0x5ca10
cmpl $0x0, -0x18(%rbp)
jne 0x5ca2e
movl -0x14(%rbp), %eax
movb %al, %cl
movq -0x20(%rbp), %rax
movb %cl, 0x18(%rax)
movl -0x14(%rbp), %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x14(%rax)
jmp 0x5ca49
cmpl $0x4, -0x14(%rbp)
jne 0x5ca47
movq -0x20(%rbp), %rax
movb $0x3, 0x18(%rax)
movq -0x28(%rbp), %rax
movl $0x3, 0x14(%rax)
jmp 0x5ca49
jmp 0x5ca4b
callq 0x5bf10
movl -0x18(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nop