// File: chhylp123[P]hifiasm/kthread.cpp
// Function: ktp_worker(void*)
static void *ktp_worker(void *data)
{
	ktp_worker_t *w = (ktp_worker_t*)data;
	ktp_t *p = w->pl;
	while (w->step < p->n_steps) {
		// test whether we can kick off the job with this worker
		pthread_mutex_lock(&p->mutex);
		for (;;) {
			int i;
			// test whether another worker is doing the same step
			for (i = 0; i < p->n_workers; ++i) {
				if (w == &p->workers[i]) continue; // ignore itself
				if (p->workers[i].step <= w->step && p->workers[i].index < w->index)
					break;
			}
			if (i == p->n_workers) break; // no workers with smaller indices are doing w->step or the previous steps
			pthread_cond_wait(&p->cv, &p->mutex);
		}
		pthread_mutex_unlock(&p->mutex);

		// working on w->step
		w->data = p->func(p->shared, w->step, w->step? w->data : 0); // for the first step, input is NULL

		// update step and let other workers know
		pthread_mutex_lock(&p->mutex);
		w->step = w->step == p->n_steps - 1 || w->data? (w->step + 1) % p->n_steps : p->n_steps;
		if (w->step == 0) w->index = p->index++;
		pthread_cond_broadcast(&p->cv);
		pthread_mutex_unlock(&p->mutex);
	}
	pthread_exit(0);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
movq -0x18(%rbp), %rcx
cmpl 0x1c(%rcx), %eax
jge 0x16dd5e
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
callq 0x22b0
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0x18(%rcx), %eax
jge 0x16dc30
movq -0x10(%rbp), %rax
movq -0x18(%rbp), %rcx
movq 0x20(%rcx), %rcx
movslq -0x1c(%rbp), %rdx
shlq $0x5, %rdx
addq %rdx, %rcx
cmpq %rcx, %rax
jne 0x16dbe1
jmp 0x16dc25
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
movslq -0x1c(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x10(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x10(%rcx), %eax
jg 0x16dc23
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
movslq -0x1c(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq -0x10(%rbp), %rcx
cmpq 0x8(%rcx), %rax
jge 0x16dc23
jmp 0x16dc30
jmp 0x16dc25
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x16dbb7
movl -0x1c(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0x18(%rcx), %eax
jne 0x16dc3e
jmp 0x16dc58
movq -0x18(%rbp), %rdi
addq $0x50, %rdi
movq -0x18(%rbp), %rsi
addq $0x28, %rsi
callq 0x22f0
jmp 0x16dbb0
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
callq 0x2150
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x20(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x10(%rax)
je 0x16dc9e
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0x16dca6
xorl %eax, %eax
movq %rax, -0x38(%rbp)
jmp 0x16dca6
movq -0x30(%rbp), %rax
movl -0x20(%rbp), %esi
movq -0x28(%rbp), %rdi
movq -0x38(%rbp), %rdx
callq *%rax
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
callq 0x22b0
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
movq -0x18(%rbp), %rcx
movl 0x1c(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
je 0x16dcef
movq -0x10(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x16dd06
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
addl $0x1, %eax
movq -0x18(%rbp), %rcx
cltd
idivl 0x1c(%rcx)
movl %edx, -0x3c(%rbp)
jmp 0x16dd10
movq -0x18(%rbp), %rax
movl 0x1c(%rax), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x10(%rax)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x10(%rax)
jne 0x16dd3f
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, 0x10(%rax)
movq -0x10(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rdi
addq $0x50, %rdi
callq 0x2070
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
callq 0x2150
jmp 0x16db8f
xorl %eax, %eax
movl %eax, %edi
callq 0x23a0
nopw (%rax,%rax)