// File: /workspace/github_c_makefile_star2_O2/unixlab[P]cloudflare-udp-ping/udpclient.c
// Function: thread_loop
void thread_loop(void *userdata)
{
	struct state *state = userdata;

	pthread_spin_init(&state->lock, PTHREAD_PROCESS_PRIVATE);

	char send_buf[PKT_SIZE], recv_buf[PKT_SIZE];
	struct msghdr *msg = calloc(2, sizeof(struct msghdr));
	struct iovec *iovec = calloc(2, sizeof(struct iovec));
	int i;
	for (i = 0; i < 2; i++) {
		msg[i].msg_iov = &iovec[i];
		msg[i].msg_iovlen = 1;
		iovec[i].iov_len = sizeof(send_buf);
	}

	iovec[0].iov_base = send_buf;
	iovec[1].iov_base = recv_buf;

	char pktinfo[4096];
	msg[1].msg_control = pktinfo;
	msg[1].msg_controllen = sizeof(pktinfo);

	uint64_t packet_no = 0;
	while (1) {
		int fd = net_connect_udp(state->target_addr, state->src_port,
					 state->busy_poll);

		struct timeval tv = {1, 0}; // 1 second
		int r = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv,
				   sizeof(tv));
		if (r < 0) {
			PFATAL("setsockopt(SO_RCVTIMEO)");
		}

		for (;; packet_no++) {
			memset(send_buf, 0, sizeof(send_buf));
			snprintf(send_buf, sizeof(send_buf), "%i-%li-%lu",
				 getpid(), gettid(), packet_no);

			uint64_t t0 = realtime_now(), t1 = 0, tp = 0;
			int r = sendmsg(fd, &msg[0], 0);
			if (r <= 0) {
				if (errno == EAGAIN || errno == EWOULDBLOCK ||
				    errno == ECONNREFUSED) {
					break;
				}
				if (errno == EINTR) {
					continue;
				}
				PFATAL("sendmmsg()");
			}

			msg[1].msg_controllen = sizeof(pktinfo);
			while (1) {
				int flags = state->polling ? MSG_DONTWAIT : 0;
				r = recvmsg(fd, &msg[1], flags);
				t1 = realtime_now();
				if (t1 - t0 >= 1000000000) {
					/* No msg for 1s */
					errno = ECONNREFUSED;
					break;
				}

				if (r <= 0 &&
				    (errno == EINTR || errno == EAGAIN ||
				     errno == EWOULDBLOCK)) {
					continue;
				}

				if (r == 0 && state->polling) {
					continue;
				}
				break;
			}

			if (r <= 0 && errno == ECONNREFUSED) {
				sleep(1);
				break;
			}

			if (r <= 0) {
				PFATAL("recvmmsg()");
			}

			if (memcmp(send_buf, recv_buf, sizeof(recv_buf)) != 0) {
				fprintf(stderr, "[!] bad message\n");
				sleep(1);
				break;
			}

			struct cmsghdr *cmsg;
			for (cmsg = CMSG_FIRSTHDR(&msg[1]); cmsg;
			     cmsg = CMSG_NXTHDR(&msg[1], cmsg)) {
				switch (cmsg->cmsg_level) {
				case SOL_SOCKET:
					switch (cmsg->cmsg_type) {
					case SO_TIMESTAMPNS: {
						struct timespec *ts =
							(struct timespec *)
							CMSG_DATA(cmsg);
						tp = TIMESPEC_NSEC(ts);
						break;
					}
					}
					break;
				}
			}

			pthread_spin_lock(&state->lock);
			stddev_add(&state->stddev, t1 - t0);
			if (tp != 0) {
				stddev_add(&state->stddev_packet, t1 - tp);
			}
			pthread_spin_unlock(&state->lock);
		}
		close(fd);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1088, %rsp           # imm = 0x1088
movq %rdi, %r14
addq $0x14, %rdi
movq %rdi, -0x48(%rbp)
xorl %esi, %esi
callq 0x420c60
pushq $0x2
popq %rbx
pushq $0x38
popq %rsi
movq %rbx, %rdi
callq 0x426af0
movq %rax, %r15
pushq $0x10
popq %rsi
movq %rbx, %rdi
callq 0x426af0
movq %rax, 0x10(%r15)
pushq $0x1
popq %rdx
movq %rdx, 0x18(%r15)
pushq $0x20
popq %rsi
movq %rsi, 0x8(%rax)
leaq 0x10(%rax), %rcx
leaq 0x38(%r15), %r13
movq %rcx, 0x48(%r15)
movq %rdx, 0x50(%r15)
movq %rsi, 0x18(%rax)
leaq -0x80(%rbp), %rcx
movq %rcx, (%rax)
leaq -0xb0(%rbp), %rcx
movq %rcx, 0x10(%rax)
leaq -0x10b0(%rbp), %rax
movq %rax, 0x58(%r15)
movq $0x1000, 0x60(%r15)     # imm = 0x1000
leaq 0x18(%r14), %rax
movq %rax, -0x60(%rbp)
movq %r14, -0x38(%rbp)
leaq 0x38(%r14), %rax
movq %rax, -0x58(%rbp)
movq %r15, %r14
xorl %r15d, %r15d
movq %r14, -0x40(%rbp)
movq -0x38(%rbp), %rax
movq (%rax), %rdi
movl 0x8(%rax), %esi
movl 0x10(%rax), %edx
callq 0x402830
movups 0xb27f4(%rip), %xmm0    # 0x4b4040
movaps %xmm0, -0x90(%rbp)
movl %eax, -0x2c(%rbp)
movl %eax, %edi
pushq $0x1
popq %rsi
pushq $0x14
popq %rdx
leaq -0x90(%rbp), %rcx
pushq $0x10
popq %r8
callq 0x45f780
testl %eax, %eax
js 0x401a81
xorps %xmm0, %xmm0
movaps %xmm0, -0x70(%rbp)
movaps %xmm0, -0x80(%rbp)
callq 0x45aac0
movl %eax, %ebx
callq 0x45f130
leaq -0x80(%rbp), %rdi
pushq $0x20
popq %rsi
leaq 0xb2824(%rip), %rdx     # 0x4b40bf
movl %ebx, %ecx
movl %eax, %r8d
movq %r15, %r9
xorl %eax, %eax
callq 0x40d420
xorl %eax, %eax
callq 0x402d88
movq %rax, %rbx
movl -0x2c(%rbp), %edi
movq %r14, %rsi
xorl %edx, %edx
callq 0x45f6e0
testl %eax, %eax
jle 0x401936
movq %r15, -0x50(%rbp)
movq $0x1000, 0x60(%r14)     # imm = 0x1000
xorl %edx, %edx
movq -0x38(%rbp), %rax
cmpl $0x0, 0xc(%rax)
setne %dl
shll $0x6, %edx
movl -0x2c(%rbp), %edi
movq %r13, %rsi
callq 0x45f630
movq %rax, %r14
xorl %eax, %eax
callq 0x402d88
movq %rax, %r12
movq %rax, %r15
subq %rbx, %r15
cmpq $0x3b9ac9ff, %r15       # imm = 0x3B9AC9FF
ja 0x40194b
testl %r14d, %r14d
jg 0x40195f
callq 0x405990
movl (%rax), %ecx
cmpl $0x4, %ecx
je 0x4018d1
cmpl $0xb, %ecx
je 0x4018d1
testl %r14d, %r14d
jne 0x4019f9
movq -0x38(%rbp), %rcx
cmpl $0x0, 0xc(%rcx)
jne 0x4018d1
jmp 0x4019f7
callq 0x405990
movl (%rax), %eax
cmpl $0x4, %eax
je 0x4019ef
jmp 0x401a1f
callq 0x405990
movl $0x6f, (%rax)
testl %r14d, %r14d
jle 0x401a02
leaq -0x80(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
pushq $0x20
popq %rdx
callq 0x401028
testl %eax, %eax
jne 0x401a2b
movq -0x40(%rbp), %r14
cmpq $0x10, 0x60(%r14)
jb 0x40198b
movq 0x58(%r14), %rax
jmp 0x40198d
xorl %eax, %eax
xorl %ebx, %ebx
testq %rax, %rax
je 0x4019b9
cmpl $0x1, 0x8(%rax)
jne 0x4019ac
cmpl $0x23, 0xc(%rax)
jne 0x4019ac
imulq $0x3b9aca00, 0x10(%rax), %rbx # imm = 0x3B9ACA00
addq 0x18(%rax), %rbx
movq %r13, %rdi
movq %rax, %rsi
callq 0x45f7f0
jmp 0x40198f
movq -0x48(%rbp), %rdi
callq 0x420c40
movq -0x60(%rbp), %rdi
movl %r15d, %esi
callq 0x401b17
testq %rbx, %rbx
je 0x4019e2
subl %ebx, %r12d
movq -0x58(%rbp), %rdi
movl %r12d, %esi
callq 0x401b17
movq -0x48(%rbp), %rdi
callq 0x420c60
movq -0x50(%rbp), %r15
incq %r15
jmp 0x401876
movl (%rax), %ecx
cmpl $0x6f, %ecx
jne 0x401ab9
pushq $0x1
popq %rdi
callq 0x45a9c0
movq -0x40(%rbp), %r14
movq -0x50(%rbp), %r15
movl -0x2c(%rbp), %edi
callq 0x45c8b0
jmp 0x401833
cmpl $0xb, %eax
je 0x401a12
cmpl $0x6f, %eax
je 0x401a12
jmp 0x401a49
movq $0x4e77a8, %rax         # imm = 0x4E77A8
movq (%rax), %rcx
leaq 0xb26ca(%rip), %rdi     # 0x4b4106
pushq $0x10
popq %rsi
pushq $0x1
popq %rdx
callq 0x4142f0
jmp 0x401a02
movq $0x4e77a8, %rbx         # imm = 0x4E77A8
movq (%rbx), %rcx
leaq 0xb2670(%rip), %rdi     # 0x4b40ca
pushq $0x1d
popq %rsi
pushq $0x1
popq %rdx
callq 0x4142f0
movq (%rbx), %rdi
leaq 0xb260c(%rip), %rsi     # 0x4b407b
leaq 0xb261f(%rip), %rdx     # 0x4b4095
leaq 0xb2624(%rip), %rcx     # 0x4b40a1
pushq $0x53
jmp 0x401aef
movq $0x4e77a8, %rbx         # imm = 0x4E77A8
movq (%rbx), %rcx
leaq 0xb25be(%rip), %rdi     # 0x4b4050
pushq $0x2a
popq %rsi
pushq $0x1
popq %rdx
callq 0x4142f0
movq (%rbx), %rdi
leaq 0xb25d4(%rip), %rsi     # 0x4b407b
leaq 0xb25e7(%rip), %rdx     # 0x4b4095
leaq 0xb25ec(%rip), %rcx     # 0x4b40a1
pushq $0x41
jmp 0x401aef
movq $0x4e77a8, %rbx         # imm = 0x4E77A8
movq (%rbx), %rcx
leaq 0xb261e(%rip), %rdi     # 0x4b40e8
pushq $0x1d
popq %rsi
pushq $0x1
popq %rdx
callq 0x4142f0
movq (%rbx), %rdi
leaq 0xb259c(%rip), %rsi     # 0x4b407b
leaq 0xb25af(%rip), %rdx     # 0x4b4095
leaq 0xb25b4(%rip), %rcx     # 0x4b40a1
pushq $0x73
popq %r8
xorl %eax, %eax
callq 0x40d290
leaq 0xb25ae(%rip), %rdi     # 0x4b40ad
callq 0x40d640
movq (%rbx), %rsi
pushq $0xa
popq %rdi
callq 0x416660
pushq $0x1
popq %rdi
callq 0x40c1f0