// File: KinderRiven[P]rdma_demo/server.cc
// Function: create_qpair(rdma_context_t*)
static void create_qpair(rdma_context_t* context)
{
    printf("----------- Create QPair -----------\n");
    // create protection domain (pd)
    // protection domain可以看作是一个内存保护单位，在内存区域和队列直接建立一个关联关系，防止未授权的访问。
    context->pd = ibv_alloc_pd(context->ctx);
    if (context->pd == NULL) {
        printf("|--ibv_alloc_pd failed.\n");
        exit(1);
    }
    printf("|--ibv_alloc_pd ok.\n");

    // create completion queue (cq)
    context->cq = ibv_create_cq(context->ctx, 1, NULL, NULL, 0);
    if (context->cq == NULL) {
        printf("|--ibv_create_cq failed.\n");
        exit(1);
    }
    printf("|--ibv_create_cq ok.\n");

    // create shared received queue (srq)
    // struct ibv_srq_init_attr srq_init_attr;
    // srq_init_attr.attr.max_wr = context->dev_attr.max_srq_wr;
    // srq_init_attr.attr.max_sge = 1;
    // context->srq = ibv_create_srq(context->pd, &srq_init_attr);
    // if (context->srq == NULL) {
    //     printf("|--ibv_create_srq failed.\n");
    // }
    // printf("|--ibv_create_srq ok.\n");

    struct ibv_qp_init_attr qp_init_attr;
    memset(&qp_init_attr, 0, sizeof(qp_init_attr));
    qp_init_attr.qp_type = IBV_QPT_RC;
    qp_init_attr.sq_sig_all = 1;
    qp_init_attr.send_cq = context->cq;
    qp_init_attr.recv_cq = context->cq;
    qp_init_attr.cap.max_send_wr = 1;
    qp_init_attr.cap.max_recv_wr = 1;
    qp_init_attr.cap.max_send_sge = 1;
    qp_init_attr.cap.max_recv_sge = 1;

    for (int i = 0; i < context->num_qps; i++) {
        context->qp[i] = ibv_create_qp(context->pd, &qp_init_attr);
        if (context->qp[i] == NULL) {
            printf("|--ibv_create_qp failed.[%s]\n", strerror(errno));
            exit(1);
        }
        printf("|--ibv_create_qp ok.[%d/%d]\n", i, context->num_qps);
        printf("|--[qp_num:%d]\n", context->qp[i]->qp_num);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
leaq 0x14da(%rip), %rdi      # 0x321d
movb $0x0, %al
callq 0x1050
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x1070
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x8(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x1d85
leaq 0x14cf(%rip), %rdi      # 0x3243
movb $0x0, %al
callq 0x1050
movl $0x1, %edi
callq 0x1150
leaq 0x14d0(%rip), %rdi      # 0x325c
movb $0x0, %al
callq 0x1050
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movl $0x1, %esi
xorl %eax, %eax
movl %eax, %ecx
xorl %r8d, %r8d
movq %rcx, %rdx
callq 0x10e0
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x8(%rbp), %rax
cmpq $0x0, 0x20(%rax)
jne 0x1ddd
leaq 0x14a5(%rip), %rdi      # 0x3271
movb $0x0, %al
callq 0x1050
movl $0x1, %edi
callq 0x1150
leaq 0x14a7(%rip), %rdi      # 0x328b
movb $0x0, %al
callq 0x1050
leaq -0x48(%rbp), %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x10c0
movl $0x2, -0x14(%rbp)
movl $0x1, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x38(%rbp)
movl $0x1, -0x28(%rbp)
movl $0x1, -0x24(%rbp)
movl $0x1, -0x20(%rbp)
movl $0x1, -0x1c(%rbp)
movl $0x0, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x570(%rcx), %eax
jge 0x1ef6
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdi
leaq -0x48(%rbp), %rsi
callq 0x1190
movq %rax, %rdx
movq -0x8(%rbp), %rax
movslq -0x4c(%rbp), %rcx
movq %rdx, 0x28(%rax,%rcx,8)
movq -0x8(%rbp), %rax
movslq -0x4c(%rbp), %rcx
cmpq $0x0, 0x28(%rax,%rcx,8)
jne 0x1eaf
callq 0x1040
movl (%rax), %edi
callq 0x10a0
movq %rax, %rsi
leaq 0x1403(%rip), %rdi      # 0x32a1
movb $0x0, %al
callq 0x1050
movl $0x1, %edi
callq 0x1150
movl -0x4c(%rbp), %esi
movq -0x8(%rbp), %rax
movl 0x570(%rax), %edx
leaq 0x13fc(%rip), %rdi      # 0x32bf
movb $0x0, %al
callq 0x1050
movq -0x8(%rbp), %rax
movslq -0x4c(%rbp), %rcx
movq 0x28(%rax,%rcx,8), %rax
movl 0x34(%rax), %esi
leaq 0x13fb(%rip), %rdi      # 0x32dc
movb $0x0, %al
callq 0x1050
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x1e44
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax)