// File: /workspace/github_c_makefile_star2_O1/genometools[P]genometools/src/external/sqlite-3.33.0/sqlite3.c
// Function: unixShmLock
static int unixShmLock(
  sqlite3_file *fd,          /* Database file holding the shared memory */
  int ofst,                  /* First lock to acquire or release */
  int n,                     /* Number of locks to acquire or release */
  int flags                  /* What to do with the lock */
){
  unixFile *pDbFd = (unixFile*)fd;      /* Connection holding shared memory */
  unixShm *p = pDbFd->pShm;             /* The shared memory being locked */
  unixShm *pX;                          /* For looping over all siblings */
  unixShmNode *pShmNode = p->pShmNode;  /* The underlying file iNode */
  int rc = SQLITE_OK;                   /* Result code */
  u16 mask;                             /* Mask of locks to take or release */

  assert( pShmNode==pDbFd->pInode->pShmNode );
  assert( pShmNode->pInode==pDbFd->pInode );
  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
  assert( n>=1 );
  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
  assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
  assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );

  /* Check that, if this to be a blocking lock, no locks that occur later
  ** in the following list than the lock being obtained are already held:
  **
  **   1. Checkpointer lock (ofst==1).
  **   2. Write lock (ofst==0).
  **   3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
  **
  ** In other words, if this is a blocking lock, none of the locks that
  ** occur later in the above list than the lock being obtained may be
  ** held.
  **
  ** It is not permitted to block on the RECOVER lock.
  */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
  assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
         (ofst!=2)                                   /* not RECOVER */
      && (ofst!=1 || (p->exclMask|p->sharedMask)==0)
      && (ofst!=0 || (p->exclMask|p->sharedMask)<3)
      && (ofst<3  || (p->exclMask|p->sharedMask)<(1<<ofst))
  ));
#endif

  mask = (1<<(ofst+n)) - (1<<ofst);
  assert( n>1 || mask==(1<<ofst) );
  sqlite3_mutex_enter(pShmNode->pShmMutex);
  if( flags & SQLITE_SHM_UNLOCK ){
    u16 allMask = 0; /* Mask of locks held by siblings */

    /* See if any siblings hold this same lock */
    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
      if( pX==p ) continue;
      assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
      allMask |= pX->sharedMask;
    }

    /* Unlock the system-level locks */
    if( (mask & allMask)==0 ){
      rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
    }else{
      rc = SQLITE_OK;
    }

    /* Undo the local locks */
    if( rc==SQLITE_OK ){
      p->exclMask &= ~mask;
      p->sharedMask &= ~mask;
    }
  }else if( flags & SQLITE_SHM_SHARED ){
    u16 allShared = 0;  /* Union of locks held by connections other than "p" */

    /* Find out which shared locks are already held by sibling connections.
    ** If any sibling already holds an exclusive lock, go ahead and return
    ** SQLITE_BUSY.
    */
    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
      if( (pX->exclMask & mask)!=0 ){
        rc = SQLITE_BUSY;
        break;
      }
      allShared |= pX->sharedMask;
    }

    /* Get shared locks at the system level, if necessary */
    if( rc==SQLITE_OK ){
      if( (allShared & mask)==0 ){
        rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
      }else{
        rc = SQLITE_OK;
      }
    }

    /* Get the local shared locks */
    if( rc==SQLITE_OK ){
      p->sharedMask |= mask;
    }
  }else{
    /* Make sure no sibling connections hold locks that will block this
    ** lock.  If any do, return SQLITE_BUSY right away.
    */
    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
      if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
        rc = SQLITE_BUSY;
        break;
      }
    }

    /* Get the exclusive locks at the system level.  Then if successful
    ** also mark the local connection as being locked.
    */
    if( rc==SQLITE_OK ){
      rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
      if( rc==SQLITE_OK ){
        assert( (p->sharedMask & mask)==0 );
        p->exclMask |= mask;
      }
    }
  }
  sqlite3_mutex_leave(pShmNode->pShmMutex);
  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
           p->id, osGetpid(0), p->sharedMask, p->exclMask));
  return rc;
}

// Assembly:
pushq %r14
pushq %rbx
subq $0x28, %rsp
movl %ecx, %eax
leal (%rdx,%rsi), %ecx
movl $0x1, %r8d
shll %cl, %r8d
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movl %esi, %ecx
shll %cl, %ebx
movq 0x40(%rdi), %r14
movq (%r14), %rcx
addl %r8d, %ebx
testb $0x1, %al
jne 0x28d8a7
movq 0x38(%rcx), %r8
testq %r8, %r8
sete %cl
testb $0x4, %al
jne 0x28d92a
xorl %eax, %eax
testq %r8, %r8
je 0x28d979
movzwl 0x14(%r8), %r9d
testl %r9d, %ebx
jne 0x28d974
movzwl 0x12(%r8), %r9d
testl %r9d, %ebx
jne 0x28d974
movq 0x8(%r8), %r8
testq %r8, %r8
sete %cl
jne 0x28d87a
jmp 0x28d979
movq 0x38(%rcx), %rcx
xorl %eax, %eax
movl $0x0, %r8d
testq %rcx, %rcx
je 0x28d8d2
xorl %r8d, %r8d
cmpq %r14, %rcx
je 0x28d8c5
orw 0x12(%rcx), %r8w
movq 0x8(%rcx), %rcx
testq %rcx, %rcx
jne 0x28d8bb
movzwl %r8w, %r8d
testl %r8d, %ebx
jne 0x28da25
movq 0x10(%rdi), %rax
movq 0x38(%rax), %rax
movl 0x18(%rax), %edi
testl %edi, %edi
js 0x28da23
addl $0x78, %esi
leaq 0x8(%rsp), %rax
movl $0x2, (%rax)
movslq %esi, %rcx
movq %rcx, 0x8(%rax)
movslq %edx, %rcx
movq %rcx, 0x10(%rax)
movl $0x6, %esi
movq %rax, %rdx
xorl %eax, %eax
callq *0x239266(%rip)         # 0x4c6b80
xorl %ecx, %ecx
cmpl $-0x1, %eax
sete %cl
leal (%rcx,%rcx,4), %eax
jmp 0x28da25
xorl %r9d, %r9d
testq %r8, %r8
je 0x28d9ce
movzwl 0x14(%r8), %r10d
movl $0x5, %eax
testl %r10d, %ebx
jne 0x28d9d0
xorl %eax, %eax
xorl %r9d, %r9d
orw 0x12(%r8), %r9w
movq 0x8(%r8), %r8
testq %r8, %r8
sete %cl
je 0x28d96e
movzwl 0x14(%r8), %r10d
testl %r10d, %ebx
je 0x28d94e
movl $0x5, %eax
movzwl %r9w, %r9d
jmp 0x28d9d0
movl $0x5, %eax
testb $0x1, %cl
je 0x28da51
movq 0x10(%rdi), %rax
movq 0x38(%rax), %rax
movl 0x18(%rax), %edi
testl %edi, %edi
js 0x28da37
addl $0x78, %esi
leaq 0x8(%rsp), %rax
movl $0x1, (%rax)
movslq %esi, %rcx
movq %rcx, 0x8(%rax)
movslq %edx, %rcx
movq %rcx, 0x10(%rax)
movl $0x6, %esi
movq %rax, %rdx
xorl %eax, %eax
callq *0x2391bf(%rip)         # 0x4c6b80
xorl %ecx, %ecx
cmpl $-0x1, %eax
sete %cl
leal (%rcx,%rcx,4), %eax
jmp 0x28da39
xorl %eax, %eax
testb %cl, %cl
je 0x28da48
xorl %eax, %eax
testl %r9d, %ebx
jne 0x28da48
movq 0x10(%rdi), %rax
movq 0x38(%rax), %rax
movl 0x18(%rax), %edi
testl %edi, %edi
js 0x28da46
addl $0x78, %esi
leaq 0x8(%rsp), %rax
movl $0x0, (%rax)
movslq %esi, %rcx
movq %rcx, 0x8(%rax)
movslq %edx, %rcx
movq %rcx, 0x10(%rax)
movl $0x6, %esi
movq %rax, %rdx
xorl %eax, %eax
callq *0x23916a(%rip)         # 0x4c6b80
xorl %ecx, %ecx
cmpl $-0x1, %eax
sete %cl
leal (%rcx,%rcx,4), %eax
jmp 0x28da48
xorl %eax, %eax
testl %eax, %eax
jne 0x28da51
notl %ebx
andw %bx, 0x14(%r14)
andw %bx, 0x12(%r14)
jmp 0x28da51
xorl %eax, %eax
testl %eax, %eax
jne 0x28da51
orw %bx, 0x14(%r14)
xorl %eax, %eax
jmp 0x28da51
xorl %eax, %eax
testl %eax, %eax
jne 0x28da51
orw %bx, 0x12(%r14)
addq $0x28, %rsp
popq %rbx
popq %r14
retq