in src/brpc/rdma/rdma_helper.cpp [442:569]
static void GlobalRdmaInitializeOrDieImpl() {
if (BAIDU_UNLIKELY(g_skip_rdma_init)) {
// Just for UT
return;
}
if (ReadRdmaDynamicLib() < 0) {
LOG(ERROR) << "Fail to load rdma dynamic lib";
ExitWithError();
}
// ibv_fork_init is very important. If we don't call this API,
// we may get some very, very strange problems if the program
// calls fork().
if (IbvForkInit()) {
PLOG(ERROR) << "Fail to ibv_fork_init";
ExitWithError();
}
int num = 0;
g_devices = IbvGetDeviceList(&num);
if (num == 0) {
LOG(ERROR) << "Fail to find rdma device";
ExitWithError();
}
// Find the first active port
g_port_num = FLAGS_rdma_port;
int available_devices;
g_context = OpenDevice(num, &available_devices);
if (!g_context) {
LOG(ERROR) << "Fail to find available RDMA device " << FLAGS_rdma_device;
ExitWithError();
}
if (available_devices > 1 && FLAGS_rdma_device.size() == 0) {
LOG(INFO) << "This server has more than one available RDMA device. Only "
<< "the first one (" << g_context->device->name
<< ") will be used. If you want to use other device, please "
<< "specify it with --rdma_device.";
} else {
LOG(INFO) << "RDMA device: " << g_context->device->name;
}
LOG(INFO) << "RDMA LID: " << g_lid;
if (!FindRdmaGid(g_context)) {
LOG(ERROR) << "Fail to find available RDMA GID";
ExitWithError();
} else {
LOG(INFO) << "RDMA GID Index: " << (int)g_gid_index;
}
IbvCreateCompChannel(g_context);
// Create protection domain
g_pd = IbvAllocPd(g_context);
if (!g_pd) {
PLOG(ERROR) << "Fail to allocate protection domain";
ExitWithError();
}
g_user_mrs_lock = new (std::nothrow) butil::Mutex;
if (!g_user_mrs_lock) {
PLOG(WARNING) << "Fail to construct g_user_mrs_lock";
ExitWithError();
}
g_user_mrs = new (std::nothrow) butil::FlatMap<void*, ibv_mr*>();
if (!g_user_mrs) {
PLOG(WARNING) << "Fail to construct g_user_mrs";
ExitWithError();
}
if (g_user_mrs->init(65536) < 0) {
PLOG(WARNING) << "Fail to initialize g_user_mrs";
ExitWithError();
}
g_mrs = new (std::nothrow) std::vector<ibv_mr*>;
if (!g_mrs) {
PLOG(ERROR) << "Fail to allocate a RDMA MR list";
ExitWithError();
}
ibv_device_attr attr;
if (IbvQueryDevice(g_context, &attr) < 0) {
PLOG(ERROR) << "Fail to get the device information";
ExitWithError();
}
// Too large sge consumes too much memory for QP
if (FLAGS_rdma_max_sge > 0) {
g_max_sge = attr.max_sge < FLAGS_rdma_max_sge ?
attr.max_sge : FLAGS_rdma_max_sge;
} else {
g_max_sge = attr.max_sge;
}
// Initialize RDMA memory pool (block_pool)
if (!InitBlockPool(RdmaRegisterMemory)) {
PLOG(ERROR) << "Fail to initialize RDMA memory pool";
ExitWithError();
}
if (RdmaEndpoint::GlobalInitialize() < 0) {
LOG(ERROR) << "rdma_recv_block_type incorrect "
<< "(valid value: default/large/huge)";
ExitWithError();
}
atexit(GlobalRelease);
SocketOptions opt;
opt.fd = g_context->async_fd;
butil::make_close_on_exec(opt.fd);
if (butil::make_non_blocking(opt.fd) < 0) {
PLOG(WARNING) << "Fail to set async_fd to nonblocking";
ExitWithError();
}
opt.on_edge_triggered_events = OnRdmaAsyncEvent;
if (Socket::Create(opt, &g_async_socket) < 0) {
LOG(WARNING) << "Fail to create socket to get async event of RDMA";
ExitWithError();
}
g_mem_alloc = butil::iobuf::blockmem_allocate;
g_mem_dealloc = butil::iobuf::blockmem_deallocate;
butil::iobuf::blockmem_allocate = BlockAllocate;
butil::iobuf::blockmem_deallocate = BlockDeallocate;
g_rdma_available.store(true, butil::memory_order_relaxed);
}