// Code generated by modernc.org/undup from the per-target sqlite_*.go files; DO NOT EDIT.

//go:build (freebsd && amd64) || (freebsd && arm64) || (netbsd && amd64) || (openbsd && amd64) || (openbsd && arm64)

package sqlite3

import (
	"unsafe"

	"modernc.org/libc"
)

type Tkey_t = int64

// C documentation
//
//	/*
//	** Change the lock state for a shared-memory segment.
//	**
//	** Note that the relationship between SHARED and EXCLUSIVE locks is a little
//	** different here than in posix.  In xShmLock(), one can go from unlocked
//	** to shared and back or from unlocked to exclusive and back.  But one may
//	** not go from shared to exclusive or from exclusive to shared.
//	*/
func _unixShmLock(tls *libc.TLS, fd uintptr, ofst int32, n int32, flags int32) (r int32) {
	var aLock, p, pDbFd, pShmNode, v1 uintptr
	var bUnlock, ii, rc int32
	var mask Tu16
	_, _, _, _, _, _, _, _, _ = aLock, bUnlock, ii, mask, p, pDbFd, pShmNode, rc, v1
	pDbFd = fd     /* The underlying file iNode */
	rc = SQLITE_OK /* Result code */
	mask = libc.Uint16FromInt32(int32(1)<<(ofst+n) - int32(1)<<ofst)
	p = (*TunixFile)(unsafe.Pointer(pDbFd)).FpShm
	if p == uintptr(0) {
		return libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(20)<<libc.Int32FromInt32(8)
	}
	pShmNode = (*TunixShm)(unsafe.Pointer(p)).FpShmNode
	if pShmNode == uintptr(0) {
		return libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(20)<<libc.Int32FromInt32(8)
	}
	aLock = pShmNode + 64
	/* 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. Recovery lock (ofst==2).
	 **   2. Checkpointer lock (ofst==1).
	 **   3. Write lock (ofst==0).
	 **   4. 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.
	 */
	/* Check if there is any work to do. There are three cases:
	 **
	 **    a) An unlock operation where there are locks to unlock,
	 **    b) An shared lock where the requested lock is not already held
	 **    c) An exclusive lock where the requested lock is not already held
	 **
	 ** The SQLite core never requests an exclusive lock that it already holds.
	 ** This is assert()ed below.
	 */
	if flags&int32(SQLITE_SHM_UNLOCK) != 0 && (libc.Int32FromUint16((*TunixShm)(unsafe.Pointer(p)).FexclMask)|libc.Int32FromUint16((*TunixShm)(unsafe.Pointer(p)).FsharedMask))&libc.Int32FromUint16(mask) != 0 || flags == libc.Int32FromInt32(SQLITE_SHM_SHARED)|libc.Int32FromInt32(SQLITE_SHM_LOCK) && 0 == libc.Int32FromUint16((*TunixShm)(unsafe.Pointer(p)).FsharedMask)&libc.Int32FromUint16(mask) || flags == libc.Int32FromInt32(SQLITE_SHM_EXCLUSIVE)|libc.Int32FromInt32(SQLITE_SHM_LOCK) {
		/* Take the required mutexes. In SETLK_TIMEOUT mode (blocking locks), if
		 ** this is an attempt on an exclusive lock use sqlite3_mutex_try(). If any
		 ** other thread is holding this mutex, then it is either holding or about
		 ** to hold a lock exclusive to the one being requested, and we may
		 ** therefore return SQLITE_BUSY to the caller.
		 **
		 ** Doing this prevents some deadlock scenarios. For example, thread 1 may
		 ** be a checkpointer blocked waiting on the WRITER lock. And thread 2
		 ** may be a normal SQL client upgrading to a write transaction. In this
		 ** case thread 2 does a non-blocking request for the WRITER lock. But -
		 ** if it were to use sqlite3_mutex_enter() then it would effectively
		 ** become a (doomed) blocking request, as thread 2 would block until thread
		 ** 1 obtained WRITER and released the mutex. Since thread 2 already holds
		 ** a lock on a read-locking slot at this point, this breaks the
		 ** anti-deadlock rules (see above).  */
		Xsqlite3_mutex_enter(tls, (*TunixShmNode)(unsafe.Pointer(pShmNode)).FpShmMutex)
		if rc == SQLITE_OK {
			if flags&int32(SQLITE_SHM_UNLOCK) != 0 {
				/* Case (a) - unlock.  */
				bUnlock = int32(1)
				/* If this is a SHARED lock being unlocked, it is possible that other
				 ** clients within this process are holding the same SHARED lock. In
				 ** this case, set bUnlock to 0 so that the posix lock is not removed
				 ** from the file-descriptor below.  */
				if flags&int32(SQLITE_SHM_SHARED) != 0 {
					if **(**int32)(__ccgo_up(aLock + uintptr(ofst)*4)) > int32(1) {
						bUnlock = 0
						**(**int32)(__ccgo_up(aLock + uintptr(ofst)*4)) = **(**int32)(__ccgo_up(aLock + uintptr(ofst)*4)) - 1
						v1 = p + 18
						*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromUint16(mask))
					}
				}
				if bUnlock != 0 {
					rc = _unixShmSystemLock(tls, pDbFd, int32(F_UNLCK), ofst+(libc.Int32FromInt32(22)+libc.Int32FromInt32(SQLITE_SHM_NLOCK))*libc.Int32FromInt32(4), n)
					if rc == SQLITE_OK {
						libc.Xmemset(tls, aLock+uintptr(ofst)*4, 0, uint64(4)*libc.Uint64FromInt32(n))
						v1 = p + 18
						*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromUint16(mask))
						v1 = p + 20
						*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) & ^libc.Int32FromUint16(mask))
					}
				}
			} else {
				if flags&int32(SQLITE_SHM_SHARED) != 0 {
					/* Case (b) - a shared lock.  */
					if **(**int32)(__ccgo_up(aLock + uintptr(ofst)*4)) < 0 {
						/* An exclusive lock is held by some other connection. BUSY. */
						rc = int32(SQLITE_BUSY)
					} else {
						if **(**int32)(__ccgo_up(aLock + uintptr(ofst)*4)) == 0 {
							rc = _unixShmSystemLock(tls, pDbFd, int32(F_RDLCK), ofst+(libc.Int32FromInt32(22)+libc.Int32FromInt32(SQLITE_SHM_NLOCK))*libc.Int32FromInt32(4), n)
						}
					}
					/* Get the local shared locks */
					if rc == SQLITE_OK {
						v1 = p + 18
						*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromUint16(mask))
						**(**int32)(__ccgo_up(aLock + uintptr(ofst)*4)) = **(**int32)(__ccgo_up(aLock + uintptr(ofst)*4)) + 1
					}
				} else {
					/* Make sure no sibling connections hold locks that will block this
					 ** lock.  If any do, return SQLITE_BUSY right away.  */
					ii = ofst
					for {
						if !(ii < ofst+n) {
							break
						}
						if **(**int32)(__ccgo_up(aLock + uintptr(ii)*4)) != 0 {
							rc = int32(SQLITE_BUSY)
							break
						}
						goto _5
					_5:
						;
						ii = ii + 1
					}
					/* Get the exclusive locks at the system level. Then if successful
					 ** also update the in-memory values. */
					if rc == SQLITE_OK {
						rc = _unixShmSystemLock(tls, pDbFd, int32(F_WRLCK), ofst+(libc.Int32FromInt32(22)+libc.Int32FromInt32(SQLITE_SHM_NLOCK))*libc.Int32FromInt32(4), n)
						if rc == SQLITE_OK {
							v1 = p + 20
							*(*Tu16)(unsafe.Pointer(v1)) = Tu16(int32(*(*Tu16)(unsafe.Pointer(v1))) | libc.Int32FromUint16(mask))
							ii = ofst
							for {
								if !(ii < ofst+n) {
									break
								}
								**(**int32)(__ccgo_up(aLock + uintptr(ii)*4)) = -int32(1)
								goto _7
							_7:
								;
								ii = ii + 1
							}
						}
					}
				}
			}
		}
		/* Drop the mutexes acquired above. */
		Xsqlite3_mutex_leave(tls, (*TunixShmNode)(unsafe.Pointer(pShmNode)).FpShmMutex)
	}
	return rc
}

func init() {
	p := unsafe.Pointer(&_aSyscall)
	*(*uintptr)(unsafe.Add(p, 8)) = __ccgo_fp(_posixOpen)
	*(*uintptr)(unsafe.Add(p, 32)) = __ccgo_fp(libc.Xclose)
	*(*uintptr)(unsafe.Add(p, 56)) = __ccgo_fp(libc.Xaccess)
	*(*uintptr)(unsafe.Add(p, 80)) = __ccgo_fp(libc.Xgetcwd)
	*(*uintptr)(unsafe.Add(p, 104)) = __ccgo_fp(libc.Xstat)
	*(*uintptr)(unsafe.Add(p, 128)) = __ccgo_fp(libc.Xfstat)
	*(*uintptr)(unsafe.Add(p, 152)) = __ccgo_fp(libc.Xftruncate)
	*(*uintptr)(unsafe.Add(p, 176)) = __ccgo_fp(libc.Xfcntl)
	*(*uintptr)(unsafe.Add(p, 200)) = __ccgo_fp(libc.Xread)
	*(*uintptr)(unsafe.Add(p, 272)) = __ccgo_fp(libc.Xwrite)
	*(*uintptr)(unsafe.Add(p, 344)) = __ccgo_fp(libc.Xfchmod)
	*(*uintptr)(unsafe.Add(p, 392)) = __ccgo_fp(libc.Xunlink)
	*(*uintptr)(unsafe.Add(p, 416)) = __ccgo_fp(_openDirectory)
	*(*uintptr)(unsafe.Add(p, 440)) = __ccgo_fp(libc.Xmkdir)
	*(*uintptr)(unsafe.Add(p, 464)) = __ccgo_fp(libc.Xrmdir)
	*(*uintptr)(unsafe.Add(p, 488)) = __ccgo_fp(libc.Xfchown)
	*(*uintptr)(unsafe.Add(p, 512)) = __ccgo_fp(libc.Xgeteuid)
	*(*uintptr)(unsafe.Add(p, 536)) = __ccgo_fp(libc.Xmmap)
	*(*uintptr)(unsafe.Add(p, 560)) = __ccgo_fp(libc.Xmunmap)
	*(*uintptr)(unsafe.Add(p, 608)) = __ccgo_fp(_unixGetpagesize)
	*(*uintptr)(unsafe.Add(p, 632)) = __ccgo_fp(libc.Xreadlink)
	*(*uintptr)(unsafe.Add(p, 656)) = __ccgo_fp(libc.Xlstat)
}

/* End of the overrideable system calls */

type t__intptr_t = int64

type t__register_t = int64

type t__uintptr_t = uint64
