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

//go:build (linux && amd64) || (linux && arm) || (linux && arm64) || (linux && ppc64le) || (linux && riscv64) || (linux && s390x)

package sqlite3

import (
	"unsafe"

	"modernc.org/libc"
)

// C documentation
//
//	/*
//	** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
//	** take it now. Return SQLITE_OK if successful, or an SQLite error
//	** code otherwise.
//	**
//	** If the DMS cannot be locked because this is a readonly_shm=1
//	** connection and no other process already holds a lock, return
//	** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
//	*/
func _unixLockSharedMemory(tls *libc.TLS, pDbFd uintptr, pShmNode uintptr) (r int32) {
	bp := tls.Alloc(48)
	defer tls.Free(48)
	var rc int32
	var _ /* lock at bp+0 */ Tflock
	_ = rc
	rc = SQLITE_OK
	/* Use F_GETLK to determine the locks other processes are holding
	 ** on the DMS byte. If it indicates that another process is holding
	 ** a SHARED lock, then this process may also take a SHARED lock
	 ** and proceed with opening the *-shm file.
	 **
	 ** Or, if no other process is holding any lock, then this process
	 ** is the first to open it. In this case take an EXCLUSIVE lock on the
	 ** DMS byte and truncate the *-shm file to zero bytes in size. Then
	 ** downgrade to a SHARED lock on the DMS byte.
	 **
	 ** If another process is holding an EXCLUSIVE lock on the DMS byte,
	 ** return SQLITE_BUSY to the caller (it will try again). An earlier
	 ** version of this code attempted the SHARED lock at this point. But
	 ** this introduced a subtle race condition: if the process holding
	 ** EXCLUSIVE failed just before truncating the *-shm file, then this
	 ** process might open and use the *-shm file without truncating it.
	 ** And if the *-shm file has been corrupted by a power failure or
	 ** system crash, the database itself may also become corrupt.  */
	(**(**Tflock)(__ccgo_up(bp))).Fl_whence = 0
	(**(**Tflock)(__ccgo_up(bp))).Fl_start = int64((libc.Int32FromInt32(22)+libc.Int32FromInt32(SQLITE_SHM_NLOCK))*libc.Int32FromInt32(4) + libc.Int32FromInt32(SQLITE_SHM_NLOCK))
	(**(**Tflock)(__ccgo_up(bp))).Fl_len = int64(1)
	(**(**Tflock)(__ccgo_up(bp))).Fl_type = int16(F_WRLCK)
	if (*(*func(*libc.TLS, int32, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(7)].FpCurrent})))(tls, (*TunixShmNode)(unsafe.Pointer(pShmNode)).FhShm, int32(F_GETLK), libc.VaList(bp+40, bp)) != 0 {
		rc = libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(15)<<libc.Int32FromInt32(8)
	} else {
		if int32((**(**Tflock)(__ccgo_up(bp))).Fl_type) == int32(F_UNLCK) {
			if (*TunixShmNode)(unsafe.Pointer(pShmNode)).FisReadonly != 0 {
				(*TunixShmNode)(unsafe.Pointer(pShmNode)).FisUnlocked = uint8(1)
				rc = libc.Int32FromInt32(SQLITE_READONLY) | libc.Int32FromInt32(5)<<libc.Int32FromInt32(8)
			} else {
				rc = _unixShmSystemLock(tls, pDbFd, int32(F_WRLCK), (libc.Int32FromInt32(22)+libc.Int32FromInt32(SQLITE_SHM_NLOCK))*libc.Int32FromInt32(4)+libc.Int32FromInt32(SQLITE_SHM_NLOCK), int32(1))
				/* The first connection to attach must truncate the -shm file.  We
				 ** truncate to 3 bytes (an arbitrary small number, less than the
				 ** -shm header size) rather than 0 as a system debugging aid, to
				 ** help detect if a -shm file truncation is legitimate or is the work
				 ** or a rogue process. */
				if rc == SQLITE_OK && _robust_ftruncate(tls, (*TunixShmNode)(unsafe.Pointer(pShmNode)).FhShm, int64(3)) != 0 {
					rc = _unixLogErrorAtLine(tls, libc.Int32FromInt32(SQLITE_IOERR)|libc.Int32FromInt32(18)<<libc.Int32FromInt32(8), __ccgo_ts+3578, (*TunixShmNode)(unsafe.Pointer(pShmNode)).FzFilename, int32(45100))
				}
			}
		} else {
			if int32((**(**Tflock)(__ccgo_up(bp))).Fl_type) == int32(F_WRLCK) {
				rc = int32(SQLITE_BUSY)
			}
		}
	}
	if rc == SQLITE_OK {
		rc = _unixShmSystemLock(tls, pDbFd, F_RDLCK, (libc.Int32FromInt32(22)+libc.Int32FromInt32(SQLITE_SHM_NLOCK))*libc.Int32FromInt32(4)+libc.Int32FromInt32(SQLITE_SHM_NLOCK), int32(1))
	}
	return rc
}
