// 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) || (windows && (amd64 || arm64))

package sqlite3

import (
	"unsafe"

	"modernc.org/libc"
)

// C documentation
//
//	/*
//	** Initialize SQLite.
//	**
//	** This routine must be called to initialize the memory allocation,
//	** VFS, and mutex subsystems prior to doing any serious work with
//	** SQLite.  But as long as you do not compile with SQLITE_OMIT_AUTOINIT
//	** this routine will be called automatically by key routines such as
//	** sqlite3_open().
//	**
//	** This routine is a no-op except on its very first call for the process,
//	** or for the first call after a call to sqlite3_shutdown.
//	**
//	** The first thread to call this routine runs the initialization to
//	** completion.  If subsequent threads call this routine before the first
//	** thread has finished the initialization process, then the subsequent
//	** threads must block until the first thread finishes with the initialization.
//	**
//	** The first thread might call this routine recursively.  Recursive
//	** calls to this routine should not block, of course.  Otherwise the
//	** initialization process would never complete.
//	**
//	** Let X be the first thread to enter this routine.  Let Y be some other
//	** thread.  Then while the initial invocation of this routine by X is
//	** incomplete, it is required that:
//	**
//	**    *  Calls to this routine from Y must block until the outer-most
//	**       call by X completes.
//	**
//	**    *  Recursive calls to this routine from thread X return immediately
//	**       without blocking.
//	*/
func Xsqlite3_initialize(tls *libc.TLS) (r int32) {
	var pMainMtx uintptr
	var rc int32
	_, _ = pMainMtx, rc /* Result code */
	/* If the following assert() fails on some obscure processor/compiler
	 ** combination, the work-around is to set the correct pointer
	 ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */
	/* If SQLite is already completely initialized, then this call
	 ** to sqlite3_initialize() should be a no-op.  But the initialization
	 ** must be complete.  So isInit must not be set until the very end
	 ** of this routine.
	 */
	if libc.AtomicLoadPInt32(uintptr(unsafe.Pointer(&_sqlite3Config))+340) != 0 {
		return SQLITE_OK
	}
	/* Make sure the mutex subsystem is initialized.  If unable to
	 ** initialize the mutex subsystem, return early with the error.
	 ** If the system is so sick that we are unable to allocate a mutex,
	 ** there is not much SQLite is going to be able to do.
	 **
	 ** The mutex subsystem must take care of serializing its own
	 ** initialization.
	 */
	rc = _sqlite3MutexInit(tls)
	if rc != 0 {
		return rc
	}
	/* Initialize the malloc() system and the recursive pInitMutex mutex.
	 ** This operation is protected by the STATIC_MAIN mutex.  Note that
	 ** MutexAlloc() is called for a static mutex prior to initializing the
	 ** malloc subsystem - this implies that the allocation of a static
	 ** mutex must not require support from the malloc subsystem.
	 */
	pMainMtx = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_STATIC_MAIN))
	Xsqlite3_mutex_enter(tls, pMainMtx)
	_sqlite3Config.FisMutexInit = int32(1)
	if !(_sqlite3Config.FisMallocInit != 0) {
		rc = _sqlite3MallocInit(tls)
	}
	if rc == SQLITE_OK {
		_sqlite3Config.FisMallocInit = int32(1)
		if !(_sqlite3Config.FpInitMutex != 0) {
			_sqlite3Config.FpInitMutex = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_RECURSIVE))
			if _sqlite3Config.FbCoreMutex != 0 && !(_sqlite3Config.FpInitMutex != 0) {
				rc = int32(SQLITE_NOMEM)
			}
		}
	}
	if rc == SQLITE_OK {
		_sqlite3Config.FnRefInitMutex = _sqlite3Config.FnRefInitMutex + 1
	}
	Xsqlite3_mutex_leave(tls, pMainMtx)
	/* If rc is not SQLITE_OK at this point, then either the malloc
	 ** subsystem could not be initialized or the system failed to allocate
	 ** the pInitMutex mutex. Return an error in either case.  */
	if rc != SQLITE_OK {
		return rc
	}
	/* Do the rest of the initialization under the recursive mutex so
	 ** that we will be able to handle recursive calls into
	 ** sqlite3_initialize().  The recursive calls normally come through
	 ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
	 ** recursive calls might also be possible.
	 **
	 ** IMPLEMENTATION-OF: R-00140-37445 SQLite automatically serializes calls
	 ** to the xInit method, so the xInit method need not be threadsafe.
	 **
	 ** The following mutex is what serializes access to the appdef pcache xInit
	 ** methods.  The sqlite3_pcache_methods.xInit() all is embedded in the
	 ** call to sqlite3PcacheInitialize().
	 */
	Xsqlite3_mutex_enter(tls, _sqlite3Config.FpInitMutex)
	if libc.AtomicLoadPInt32(uintptr(unsafe.Pointer(&_sqlite3Config))+340) == 0 && _sqlite3Config.FinProgress == 0 {
		_sqlite3Config.FinProgress = int32(1)
		libc.Xmemset(tls, uintptr(unsafe.Pointer(&_sqlite3BuiltinFunctions)), 0, uint64(184))
		_sqlite3RegisterBuiltinFunctions(tls)
		if _sqlite3Config.FisPCacheInit == 0 {
			rc = _sqlite3PcacheInitialize(tls)
		}
		if rc == SQLITE_OK {
			_sqlite3Config.FisPCacheInit = int32(1)
			rc = _sqlite3OsInit(tls)
		}
		if rc == SQLITE_OK {
			rc = _sqlite3MemdbInit(tls)
		}
		if rc == SQLITE_OK {
			_sqlite3PCacheBufferSetup(tls, _sqlite3Config.FpPage, _sqlite3Config.FszPage, _sqlite3Config.FnPage)
		}
		if rc == SQLITE_OK {
			libc.AtomicStorePInt32(uintptr(unsafe.Pointer(&_sqlite3Config))+340, int32(1))
		}
		_sqlite3Config.FinProgress = 0
	}
	Xsqlite3_mutex_leave(tls, _sqlite3Config.FpInitMutex)
	/* Go back under the static mutex and clean up the recursive
	 ** mutex to prevent a resource leak.
	 */
	Xsqlite3_mutex_enter(tls, pMainMtx)
	_sqlite3Config.FnRefInitMutex = _sqlite3Config.FnRefInitMutex - 1
	if _sqlite3Config.FnRefInitMutex <= 0 {
		Xsqlite3_mutex_free(tls, _sqlite3Config.FpInitMutex)
		_sqlite3Config.FpInitMutex = uintptr(0)
	}
	Xsqlite3_mutex_leave(tls, pMainMtx)
	/* The following is just a sanity check to make sure SQLite has
	 ** been compiled correctly.  It is important to run this code, but
	 ** we don't want to run it too often and soak up CPU cycles for no
	 ** reason.  So we run it once during initialization.
	 */
	/* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
	 ** compile-time option.
	 */
	return rc
}
