// File: /workspace/github_c_makefile_star2_O3/Tarsnap[P]spiped/liball/../lib/util/pthread_create_blocking_np.c
// Function: pthread_create_blocking_np
int
pthread_create_blocking_np(pthread_t * restrict thread,
    const pthread_attr_t * restrict attr,
    void * (*start_routine)(void *), void * restrict arg)
{
	struct wrapped_cookie * U;
	int rc;

	/*
	 * Allocate our cookie and store parameters.  The C standard does not
	 * require that variables with automatic storage duration are
	 * accessible by other threads; POSIX (and thus pthreads) does provide
	 * that guarantee, but out of an abundance of caution we take the
	 * option of using malloc in case this code ends up running on a
	 * non-POSIX system.
	 */
	if ((U = malloc(sizeof(struct wrapped_cookie))) == NULL) {
		rc = errno;
		goto err0;
	}
	U->start_routine = start_routine;
	U->arg = arg;

	/* Initialize synchronization-related variables. */
	if ((rc = pthread_mutex_init(&U->mutex, NULL)) != 0)
		goto err1;
	if ((rc = pthread_cond_init(&U->cond, NULL)) != 0)
		goto err2;
	U->running = 0;
	U->rc_sync = 0;

	/* Lock mutex. */
	if ((rc = pthread_mutex_lock(&U->mutex)) != 0)
		goto err3;

	/* Create the thread. */
	if ((rc = pthread_create(thread, attr, wrapped_thread, U)) != 0) {
		/*
		 * Don't record any pthread_mutex_unlock() error here; the
		 * error from pthread_create() is more important.
		 */
		pthread_mutex_unlock(&U->mutex);
		goto err3;
	}

	/* Wait for the thread to have started, then unlock the mutex. */
	while (!U->running) {
		/* Wait until signalled. */
		if ((rc = pthread_cond_wait(&U->cond, &U->mutex)) != 0)
			goto err5;

		/* Quit if there was an error in the synchronization. */
		if ((rc = U->rc_sync) != 0)
			goto err5;
	}
	if ((rc = pthread_mutex_unlock(&U->mutex)) != 0)
		goto err4;

	/* Clean up synchronization-related variables. */
	if ((rc = pthread_cond_destroy(&U->cond)) != 0)
		goto err2;
	if ((rc = pthread_mutex_destroy(&U->mutex)) != 0)
		goto err1;

	/* Clean up. */
	free(U);

	/* Success! */
	return (0);

err5:
	/*
	 * Don't record any errors in this clean-up; the existing value of rc
	 * is more important.
	 */
	pthread_mutex_unlock(&U->mutex);
err4:
	pthread_cancel(*thread);
	pthread_join(*thread, NULL);
err3:
	pthread_cond_destroy(&U->cond);
err2:
	pthread_mutex_destroy(&U->mutex);
err1:
	free(U);
err0:
	/* Failure! */
	return (rc);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rcx, %r14
movq %rdx, %r12
movq %rsi, %r13
movq %rdi, %r15
movl $0x70, %edi
callq 0x21e0
testq %rax, %rax
je 0x4195
movq %rax, %rbx
movq %r12, (%rax)
movq %r14, 0x8(%rax)
leaq 0x10(%rax), %r14
movq %r14, %rdi
xorl %esi, %esi
callq 0x22f0
testl %eax, %eax
je 0x41a1
movl %eax, %ebp
jmp 0x427a
callq 0x2080
movl (%rax), %ebp
jmp 0x4282
movq %rbx, %r12
addq $0x38, %r12
movq %r12, %rdi
xorl %esi, %esi
callq 0x21c0
testl %eax, %eax
je 0x41bd
movl %eax, %ebp
jmp 0x4272
movq $0x0, 0x68(%rbx)
movq %r14, %rdi
callq 0x2300
movl %eax, %ebp
testl %eax, %eax
jne 0x426a
leaq 0xb5(%rip), %rdx        # 0x4293
movq %r15, %rdi
movq %r13, %rsi
movq %rbx, %rcx
callq 0x2210
testl %eax, %eax
je 0x4212
movl %eax, %ebp
movq %r14, %rdi
callq 0x21d0
jmp 0x426a
movq %r12, %rdi
movq %r14, %rsi
callq 0x20c0
testl %eax, %eax
jne 0x424e
movl 0x6c(%rbx), %ebp
testl %ebp, %ebp
jne 0x4250
cmpl $0x0, 0x68(%rbx)
je 0x41fc
movq %r14, %rdi
callq 0x21d0
movl %eax, %ebp
testl %eax, %eax
jne 0x4258
movq %r12, %rdi
callq 0x2220
testl %eax, %eax
jne 0x41b6
movq %r14, %rdi
callq 0x20f0
testl %eax, %eax
jne 0x418e
movq %rbx, %rdi
callq 0x2030
xorl %ebp, %ebp
jmp 0x4282
movl %eax, %ebp
movq %r14, %rdi
callq 0x21d0
movq (%r15), %rdi
callq 0x22d0
movq (%r15), %rdi
xorl %esi, %esi
callq 0x2290
movq %r12, %rdi
callq 0x2220
movq %r14, %rdi
callq 0x20f0
movq %rbx, %rdi
callq 0x2030
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq