// File: jvanns[P]verbatim/sub/lmdb/libraries/liblmdb/mdb.c
// Function: mdb_env_close1
static void ESECT
mdb_env_close0(MDB_env *env, int excl)
{
	int i;

	if (!(env->me_flags & MDB_ENV_ACTIVE))
		return;

	/* Doing this here since me_dbxs may not exist during mdb_env_close */
	if (env->me_dbxs) {
		for (i = env->me_maxdbs; --i >= CORE_DBS; )
			free(env->me_dbxs[i].md_name.mv_data);
		free(env->me_dbxs);
	}

	free(env->me_pbuf);
	free(env->me_dbiseqs);
	free(env->me_dbflags);
	free(env->me_path);
	free(env->me_dirty_list);
	free(env->me_txn0);
	mdb_midl_free(env->me_free_pgs);

	if (env->me_flags & MDB_ENV_TXKEY) {
		pthread_key_delete(env->me_txkey);
#ifdef _WIN32
		/* Delete our key from the global list */
		for (i=0; i<mdb_tls_nkeys; i++)
			if (mdb_tls_keys[i] == env->me_txkey) {
				mdb_tls_keys[i] = mdb_tls_keys[mdb_tls_nkeys-1];
				mdb_tls_nkeys--;
				break;
			}
#endif
	}

	if (env->me_map) {
		munmap(env->me_map, env->me_mapsize);
	}
	if (env->me_mfd != env->me_fd && env->me_mfd != INVALID_HANDLE_VALUE)
		(void) close(env->me_mfd);
	if (env->me_fd != INVALID_HANDLE_VALUE)
		(void) close(env->me_fd);
	if (env->me_txns) {
		MDB_PID_T pid = env->me_pid;
		/* Clearing readers is done in this function because
		 * me_txkey with its destructor must be disabled first.
		 *
		 * We skip the the reader mutex, so we touch only
		 * data owned by this process (me_close_readers and
		 * our readers), and clear each reader atomically.
		 */
		for (i = env->me_close_readers; --i >= 0; )
			if (env->me_txns->mti_readers[i].mr_pid == pid)
				env->me_txns->mti_readers[i].mr_pid = 0;
#ifdef _WIN32
		if (env->me_rmutex) {
			CloseHandle(env->me_rmutex);
			if (env->me_wmutex) CloseHandle(env->me_wmutex);
		}
		/* Windows automatically destroys the mutexes when
		 * the last handle closes.
		 */
#elif defined(MDB_USE_POSIX_SEM)
		if (env->me_rmutex != SEM_FAILED) {
			sem_close(env->me_rmutex);
			if (env->me_wmutex != SEM_FAILED)
				sem_close(env->me_wmutex);
			/* If we have the filelock:  If we are the
			 * only remaining user, clean up semaphores.
			 */
			if (excl == 0)
				mdb_env_excl_lock(env, &excl);
			if (excl > 0) {
				sem_unlink(env->me_txns->mti_rmname);
				sem_unlink(env->me_txns->mti_wmname);
			}
		}
#elif defined(MDB_USE_SYSV_SEM)
		if (env->me_rmutex->semid != -1) {
			/* If we have the filelock:  If we are the
			 * only remaining user, clean up semaphores.
			 */
			if (excl == 0)
				mdb_env_excl_lock(env, &excl);
			if (excl > 0)
				semctl(env->me_rmutex->semid, 0, IPC_RMID);
		}
#endif
		munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo));
	}
	if (env->me_lfd != INVALID_HANDLE_VALUE) {
#ifdef _WIN32
		if (excl >= 0) {
			/* Unlock the lockfile.  Windows would have unlocked it
			 * after closing anyway, but not necessarily at once.
			 */
			UnlockFile(env->me_lfd, 0, 0, 1, 0);
		}
#endif
		(void) close(env->me_lfd);
	}

	env->me_flags &= ~(MDB_ENV_ACTIVE|MDB_ENV_TXKEY);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x10, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x20000000, %eax       # imm = 0x20000000
cmpl $0x0, %eax
jne 0x14542
jmp 0x14739
movq -0x8(%rbp), %rax
cmpq $0x0, 0x88(%rax)
je 0x14599
movq -0x8(%rbp), %rax
movl 0x24(%rax), %eax
movl %eax, -0xc(%rbp)
movl -0xc(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0xc(%rbp)
cmpl $0x2, %eax
jl 0x14589
movq -0x8(%rbp), %rax
movq 0x88(%rax), %rax
movslq -0xc(%rbp), %rcx
imulq $0x30, %rcx, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rdi
callq 0x2030
jmp 0x1455a
movq -0x8(%rbp), %rax
movq 0x88(%rax), %rdi
callq 0x2030
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x2030
movq -0x8(%rbp), %rax
movq 0x98(%rax), %rdi
callq 0x2030
movq -0x8(%rbp), %rax
movq 0x90(%rax), %rdi
callq 0x2030
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x2030
movq -0x8(%rbp), %rax
movq 0xd0(%rax), %rdi
callq 0x2030
movq -0x8(%rbp), %rax
movq 0x68(%rax), %rdi
callq 0x2030
movq -0x8(%rbp), %rax
movq 0xc8(%rax), %rdi
callq 0x12710
movq -0x8(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x10000000, %eax       # imm = 0x10000000
cmpl $0x0, %eax
je 0x14620
movq -0x8(%rbp), %rax
movl 0xa0(%rax), %edi
callq 0x21c0
movq -0x8(%rbp), %rax
cmpq $0x0, 0x38(%rax)
je 0x14640
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x70(%rax), %rsi
callq 0x2280
movq -0x8(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x8(%rbp), %rcx
cmpl (%rcx), %eax
je 0x14665
movq -0x8(%rbp), %rax
cmpl $-0x1, 0x8(%rax)
je 0x14665
movq -0x8(%rbp), %rax
movl 0x8(%rax), %edi
callq 0x2190
movq -0x8(%rbp), %rax
cmpl $-0x1, (%rax)
je 0x14679
movq -0x8(%rbp), %rax
movl (%rax), %edi
callq 0x2190
movq -0x8(%rbp), %rax
cmpq $0x0, 0x40(%rax)
je 0x14713
movq -0x8(%rbp), %rax
movl 0x28(%rax), %eax
movl %eax, -0x10(%rbp)
movq -0x8(%rbp), %rax
movl 0x1c(%rax), %eax
movl %eax, -0xc(%rbp)
movl -0xc(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0xc(%rbp)
cmpl $0x0, %eax
jl 0x146ed
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rax
addq $0x80, %rax
movslq -0xc(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
cmpl -0x10(%rbp), %eax
jne 0x146eb
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rax
addq $0x80, %rax
movslq -0xc(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movl $0x0, 0x8(%rax)
jmp 0x1469c
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdi
movq -0x8(%rbp), %rax
movl 0x18(%rax), %eax
subl $0x1, %eax
movl %eax, %eax
movl %eax, %esi
shlq $0x6, %rsi
addq $0xc0, %rsi
callq 0x2280
movq -0x8(%rbp), %rax
cmpl $-0x1, 0x4(%rax)
je 0x14729
movq -0x8(%rbp), %rax
movl 0x4(%rax), %edi
callq 0x2190
movq -0x8(%rbp), %rax
movl 0xc(%rax), %ecx
andl $0xcfffffff, %ecx       # imm = 0xCFFFFFFF
movl %ecx, 0xc(%rax)
addq $0x10, %rsp
popq %rbp
retq
nop