// File: /workspace/github_cpp_makefile_star2_O2/cybozu[P]yrmcds/cybozu/tcp.cpp
// Function: cybozu::tcp_server_socket::on_readable(int)
bool tcp_server_socket::on_readable(int fd) {
    while( true ) {
        union {
            struct sockaddr sa;
            struct sockaddr_storage ss;
        } addr;
        socklen_t addrlen = sizeof(addr);
#ifdef _GNU_SOURCE
        int s = ::accept4(fd, &(addr.sa), &addrlen,
                          SOCK_NONBLOCK|SOCK_CLOEXEC);
#else
        int s = ::accept(m_fd, &(addr.sa), &addrlen);
        if( s != -1 ) {
            int fl = fcntl(s, F_GETFL, 0);
            if( fl == -1 ) fl = 0;
            if( fcntl(s, F_SETFL, fl | O_NONBLOCK) == -1 ) {
                ::close(s);
                throw_unix_error(errno, "fcntl(F_SETFL)");
            }
            fl = fcntl(s, F_GETFD, 0);
            if( fl == -1 ) fl = 0;
            if( fcntl(s, F_SETFD, fl | FD_CLOEXEC) == -1 ) {
                ::close(s);
                throw_unix_error(errno, "fcntl(F_SETFD)");
            }
        }
#endif
        if( s == -1 ) {
            if( errno == EINTR || errno == ECONNABORTED )
                continue;
            if( errno == EMFILE || errno == ENFILE ) {
                logger::error() << "accept: Too many open files.";
                m_reactor->add_readable(*this);
                break;
            }
            if( errno == EAGAIN || errno == EWOULDBLOCK )
                break;
            throw_unix_error(errno, "accept");
        }

        try {
            std::unique_ptr<tcp_socket> t = m_wrapper(s, ip_address(&(addr.sa)));
            if( t.get() == nullptr ) {
                ::close(s);
            } else {
                m_reactor->add_resource( std::move(t),
                                         reactor::EVENT_IN|reactor::EVENT_OUT );
            }

        } catch( ... ) {
            ::close(s);
            throw;
        }
    }
    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movl %esi, %ebp
movq %rdi, 0x20(%rsp)
leaq 0x58(%rdi), %r14
leaq 0x48(%rsp), %r15
leaq 0x1c(%rsp), %r12
leaq 0x28(%rsp), %r13
movl $0x80, 0x1c(%rsp)
movl %ebp, %edi
movq %r15, %rsi
movq %r12, %rdx
movl $0x80800, %ecx          # imm = 0x80800
callq 0x7210
cmpl $-0x1, %eax
je 0x1cd40
movl %eax, %ebx
movq %r13, %rdi
movq %r15, %rsi
callq 0x109d2
leaq 0x10(%rsp), %rdi
movq %r14, %rsi
movl %ebx, %edx
movq %r13, %rcx
callq 0x1d116
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x1cd5b
movq 0x20(%rsp), %rcx
movq 0x8(%rcx), %rdi
andq $0x0, 0x10(%rsp)
movq %rax, 0x8(%rsp)
leaq 0x8(%rsp), %rsi
pushq $0x5
popq %rdx
callq 0x98ce
movq 0x8(%rsp), %rdi
testq %rdi, %rdi
je 0x1cd38
movq (%rdi), %rax
callq *0x8(%rax)
andq $0x0, 0x8(%rsp)
jmp 0x1cd62
callq 0x7030
movl (%rax), %edi
cmpl $0x4, %edi
je 0x1ccbf
cmpl $0x67, %edi
je 0x1ccbf
jmp 0x1cd7b
movl %ebx, %edi
callq 0x7a90
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x1ccbf
movq (%rdi), %rax
callq *0x8(%rax)
jmp 0x1ccbf
leal -0x17(%rdi), %eax
cmpl $0x2, %eax
jae 0x1cdc1
leaq 0x28(%rsp), %rbx
movq %rbx, %rdi
callq 0x865e
leaq 0xba4d(%rip), %rsi      # 0x287e4
movq %rbx, %rdi
callq 0x1321e
leaq 0x28(%rsp), %rdi
callq 0x86e4
movq 0x20(%rsp), %rsi
movq 0x8(%rsi), %rdi
addq $0x40, %rdi
addq $0x50, %rsi
callq 0x9f96
jmp 0x1cdc6
cmpl $0xb, %edi
jne 0x1cdda
movb $0x1, %al
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xba20(%rip), %rsi      # 0x28801
callq 0x8513
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x86e4
jmp 0x1ce44
movq %rax, %r14
jmp 0x1ce13
movq %rax, %r14
movq 0x8(%rsp), %rdi
testq %rdi, %rdi
je 0x1ce0d
movq (%rdi), %rax
callq *0x8(%rax)
andq $0x0, 0x8(%rsp)
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x1ce28
movq (%rdi), %rax
callq *0x8(%rax)
jmp 0x1ce28
movq %rax, %r14
movq %r14, %rdi
callq 0x71a0
movl %ebx, %edi
callq 0x7a90
callq 0x77c0
movq %rax, %rbx
callq 0x78e0
movq %rbx, %rdi
callq 0x7990
movq %rax, %rdi
callq 0x870a