// File: /workspace/github_c_makefile_star2_O2/wahern[P]cqueues/src/thread.c
// Function: ct_enter
static void *ct_enter(void *arg) {
	struct cthread *ct = arg, **ud;
	lua_State *L = NULL;
	int error;

	/*
	 * Hold down deadman switch so ct_join can detect (on some systems)
	 * whether thread was killed or cancelled.
	 */
	hdl_hold(&ct->handle);

	/*
	 * Procedure for bootstrapping into a new Lua VM. Order is important
	 * because arg[0..N] are interned strings from the parent Lua VM.
	 *
	 *  1) Acquire lock.
	 *  -- BEGIN CRITICAL SECTION --
	 *  2) Grab struct cthread reference.
	 *  3) Open new main Lua thread.
	 *  4) Set Lua panic trap.
	 *  5) Load low-level components from memory as we might be
	 *     chroot'd and unable to load them from disk.
	 *  6) Load arg[0] as our Lua start routine.
	 *  7) Push reference to struct cthread.
	 *  8) Push reference to our socket.
	 *  9) Push strings arg[1..N].
	 *  -- END CRITICAL SECTION --
	 * 10) Release lock and signal parent.
	 * 11) Reset Lua panic trap.
	 * 12) Call Lua start routine.
	 *
	 * NOTE: Lua user code perceives this process differently. See
	 * thread.lua.
	 */
	pthread_mutex_lock(&ct->mutex);

	ct->refs++;

	if (!(L = luaL_newstate()))
		goto syerr;

	if ((error = pthread_once(&atpanic.once, &atpanic_once)))
		goto error;

	if ((error = pthread_setspecific(atpanic.key, ct)))
		goto error;

	lua_atpanic(L, &atpanic_trap);

	if ((error = _setjmp(ct->trap)))
		goto error;

	luaL_openlibs(L);
	cqs_openlibs(L);

	if (ct->tmp.arg[0].iscfunction) {
		lua_pushcfunction(L, EXTENSION (lua_CFunction)ct->tmp.arg[0].v.pointer);
	} else {
		luaL_loadbuffer(L, ct->tmp.arg[0].v.string.iov_base, ct->tmp.arg[0].v.string.iov_len, "[thread enter]");
	}

	ud = lua_newuserdata(L, sizeof *ud);
	*ud = NULL;

	luaL_getmetatable(L, CQS_THREAD);
	lua_setmetatable(L, -2);

	ct->refs++;
	*ud = ct;

	lua_pushvalue(L, -1);
	lua_rawsetp(L, LUA_REGISTRYINDEX, CQS_UNIQUE_LIGHTUSERDATA_MASK(&selfindex));

	if ((error = cqs_socket_fdopen(L, ct->tmp.fd[1], NULL)))
		goto error;

	ct->tmp.fd[1] = -1;

	for (struct cthread_arg *arg = &ct->tmp.arg[1]; arg < &ct->tmp.arg[ct->tmp.argc]; arg++) {
		switch (arg->type) {
		case LUA_TNUMBER:
			if (arg->isinteger) {
				lua_pushinteger(L, arg->v.integer);
			} else {
				lua_pushnumber(L, arg->v.number);
			}
			break;
		case LUA_TBOOLEAN:
			lua_pushboolean(L, arg->v.boolean);
			break;
		case LUA_TLIGHTUSERDATA:
			lua_pushlightuserdata(L, arg->v.pointer);
			break;
		case LUA_TSTRING:
			lua_pushlstring(L, arg->v.string.iov_base, arg->v.string.iov_len);
			break;
		case LUA_TFUNCTION:
			if (arg->iscfunction) {
				lua_pushcfunction(L, EXTENSION (lua_CFunction)arg->v.pointer);
			} else {
				luaL_loadbuffer(L, arg->v.string.iov_base, arg->v.string.iov_len, NULL);
			}
			break;
		default:
			lua_pushnil(L);
			break;
		}
	}

	free(ct->tmp.arg);
	ct->tmp.arg = NULL;
	ct->tmp.argc = 0;

	pthread_mutex_unlock(&ct->mutex);
	pthread_cond_signal(&ct->cond);

	if ((error = _setjmp(ct->trap))) {
		ct->error = error;
		goto close;
	}

	ct->status = lua_pcall(L, lua_gettop(L) - 1, 0, 0);

	if (ct->status != LUA_OK && lua_isstring(L, -1)) {
		if (!(ct->msg = strdup(lua_tostring(L, -1)))) {
			ct->error = errno;
		}
	}
close:
	if (L) {
		if (!(error = _setjmp(ct->trap))) {
			lua_close(L);
		} else if (!ct->error) {
			ct->error = error;
		}
	}

	cqs_closefd(&ct->pipe[1]);

	ct_release(ct);

	return 0;
syerr:
	error = errno;
error: /* NOTE: Only critical section errors reach here. */
	ct->error = error;

	pthread_mutex_unlock(&ct->mutex);
	pthread_cond_signal(&ct->cond);

	goto close;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
addq $0x180, %rdi            # imm = 0x180
callq 0x10450
testl %eax, %eax
jne 0x1be92
movl $0x1, 0x178(%rbx)
leaq 0x20(%rbx), %r12
movq %r12, %rdi
callq 0x10450
incl (%rbx)
callq 0x10440
movq %rax, %r15
movq %rax, %r14
testq %rax, %rax
je 0x1bfdf
leaq 0x2a79d(%rip), %rdi     # 0x46658
leaq 0x390(%rip), %rsi       # 0x1c252
callq 0xfcc0
testl %eax, %eax
jne 0x1bfe6
movl 0x2a787(%rip), %edi     # 0x4665c
movq %rbx, %rsi
callq 0xf280
testl %eax, %eax
jne 0x1bfe6
leaq 0x37d(%rip), %rsi       # 0x1c269
movq %r14, %rdi
callq 0x10a70
leaq 0xb0(%rbx), %r13
movq %r13, %rdi
callq 0x103c0
testl %eax, %eax
jne 0x1bfe6
movq %r14, %rdi
callq 0xf910
movq %r14, %rdi
callq 0xf970
movl %eax, %ebp
leaq 0x15107(%rip), %rsi     # 0x3102b
movq 0x29045(%rip), %rdx     # 0x44f70
movq %r14, %rdi
callq 0x1c28f
leaq 0x150fa(%rip), %rsi     # 0x31034
movq 0x29097(%rip), %rdx     # 0x44fd8
movq %r14, %rdi
callq 0x1c28f
leaq 0x14119(%rip), %rsi     # 0x30069
movq 0x29049(%rip), %rdx     # 0x44fa0
movq %r14, %rdi
callq 0x1c28f
leaq 0x150dd(%rip), %rsi     # 0x31043
movq 0x2902b(%rip), %rdx     # 0x44f98
movq %r14, %rdi
callq 0x1c28f
leaq 0x150d7(%rip), %rsi     # 0x31053
movq 0x2905d(%rip), %rdx     # 0x44fe0
movq %r14, %rdi
callq 0x1c28f
leaq 0x150d1(%rip), %rsi     # 0x31063
movq 0x2904f(%rip), %rdx     # 0x44fe8
movq %r14, %rdi
callq 0x1c28f
movq %r14, %rdi
movl %ebp, %esi
callq 0x106f0
movq 0x1b8(%rbx), %rax
testb $0x1, 0x4(%rax)
movq 0x8(%rax), %rsi
movq %r13, 0x10(%rsp)
jne 0x1c047
movq 0x10(%rax), %rdx
leaq 0x1504c(%rip), %rcx     # 0x3101c
xorl %eax, %eax
movl %eax, %r8d
movq %r14, %rdi
callq 0xfcf0
jmp 0x1c051
callq 0xf0a0
movl (%rax), %eax
movl %eax, 0x4(%rbx)
movq %r12, %rdi
callq 0xfa00
leaq 0x48(%rbx), %rdi
callq 0xf040
testq %r15, %r15
je 0x1c022
leaq 0xb0(%rbx), %rdi
callq 0x103c0
testl %eax, %eax
je 0x1c01a
cmpl $0x0, 0x4(%rbx)
jne 0x1c022
movl %eax, 0x4(%rbx)
jmp 0x1c022
movq %r14, %rdi
callq 0xfa20
leaq 0x1ac(%rbx), %rdi
callq 0x1b58a
movq %rbx, %rdi
callq 0x1b22b
xorl %eax, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
xorl %edx, %edx
callq 0x10ad0
pushq $0x8
popq %rsi
movq %r14, %rdi
callq 0xfb70
movq %rax, %rbp
andq $0x0, (%rax)
leaq 0x14f42(%rip), %rdx     # 0x30fac
movl $0xfff0b9d8, %r13d      # imm = 0xFFF0B9D8
movq %r14, %rdi
movl %r13d, %esi
callq 0xf1f0
pushq $-0x2
popq %rsi
movq %r14, %rdi
callq 0x109f0
incl (%rbx)
movq %rbx, (%rbp)
pushq $-0x1
popq %rsi
movq %r14, %rdi
callq 0xfa10
leaq 0x14f0a(%rip), %rdx     # 0x30fa8
movq %r14, %rdi
movl %r13d, %esi
callq 0xf170
movl 0x1c8(%rbx), %esi
xorl %eax, %eax
movl %eax, %edx
movq %r14, %rdi
callq 0x10200
testl %eax, %eax
jne 0x1bfe6
orl $-0x1, 0x1c8(%rbx)
movq 0x1b8(%rbx), %rdi
leaq 0x18(%rdi), %rbp
leaq 0x14eb4(%rip), %r13     # 0x30f90
xorl %eax, %eax
movq %rax, 0x8(%rsp)
movl 0x1c0(%rbx), %eax
imulq $0x18, %rax, %rax
addq %rdi, %rax
cmpq %rax, %rbp
jae 0x1c1a2
movl (%rbp), %eax
decl %eax
cmpl $0x5, %eax
ja 0x1c11b
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movzbl 0x8(%rbp), %esi
movq %r14, %rdi
callq 0x108d0
jmp 0x1c192
movq %r14, %rdi
callq 0xf9d0
jmp 0x1c192
testb $0x2, 0x4(%rbp)
jne 0x1c17a
movsd 0x8(%rbp), %xmm0
movq %r14, %rdi
callq 0xf2d0
jmp 0x1c192
movq 0x8(%rbp), %rsi
movq %r14, %rdi
callq 0x101e0
jmp 0x1c192
movq 0x8(%rbp), %rsi
movq 0x10(%rbp), %rdx
movq %r14, %rdi
callq 0xf4e0
jmp 0x1c192
testb $0x1, 0x4(%rbp)
movq 0x8(%rbp), %rsi
jne 0x1c188
movq 0x10(%rbp), %rdx
movq %r14, %rdi
movq 0x8(%rsp), %rcx
movq %rcx, %r8
callq 0xfcf0
jmp 0x1c192
movq 0x8(%rbp), %rsi
movq %r14, %rdi
callq 0xf960
jmp 0x1c192
movq %r14, %rdi
xorl %edx, %edx
callq 0x10ad0
movq 0x1b8(%rbx), %rdi
addq $0x18, %rbp
jmp 0x1c0e3
callq 0xffc0
andq $0x0, 0x1b8(%rbx)
andl $0x0, 0x1c0(%rbx)
movq %r12, %rdi
callq 0xfa00
leaq 0x48(%rbx), %rdi
callq 0xf040
movq 0x10(%rsp), %rdi
callq 0x103c0
testl %eax, %eax
je 0x1c1dd
movl %eax, 0x4(%rbx)
jmp 0x1bffa
movq %r14, %rdi
callq 0xf970
leal -0x1(%rax), %esi
xorl %ecx, %ecx
movl %ecx, %r8d
movq %r14, %rdi
movl %ecx, %edx
movq %r8, %r9
callq 0xf9e0
movl %eax, 0x8(%rbx)
testl %eax, %eax
je 0x1bffa
pushq $-0x1
popq %rsi
movq %r14, %rdi
callq 0x107b0
testl %eax, %eax
je 0x1bffa
xorl %eax, %eax
movl %eax, %edx
pushq $-0x1
popq %rsi
movq %r14, %rdi
callq 0xf120
movq %rax, %rdi
callq 0x10970
movq %rax, 0x10(%rbx)
testq %rax, %rax
jne 0x1bffa
callq 0xf0a0
movl (%rax), %eax
jmp 0x1c1d5