in src/cdi/internal.c [371:483]
CdiReturnStatus AdapterInitializeInternal(CdiAdapterData* adapter_data_ptr, CdiAdapterHandle* ret_handle_ptr)
{
CdiReturnStatus rs = kCdiStatusOk;
CdiListIterator list_iterator;
CdiOsCritSectionReserve(cdi_global_context.adapter_handle_list_lock);
CdiListIteratorInit(&cdi_global_context.adapter_handle_list, &list_iterator);
CdiListEntry* entry_ptr = NULL;
// If there are any adapters that have already been initialized, then walk through list until we reach the head or
// find an entry that matches the one we are currently trying to initialize. If we do find a match, then error out
// and exit.
while (NULL != (entry_ptr = CdiListIteratorGetNext(&list_iterator))) {
CdiAdapterHandle adapter_handle_entry = (CdiAdapterHandle)entry_ptr;
if ((adapter_handle_entry->adapter_data.adapter_type == adapter_data_ptr->adapter_type) &&
(0 == CdiOsStrCmp(adapter_handle_entry->adapter_ip_addr_str, adapter_data_ptr->adapter_ip_addr_str))) {
// If we find an adapter of the same type and with the same local IP addr as the new one we are attempting
// to initialize, then error out and exit.
CDI_LOG_THREAD(kLogError, "Unable to register an adapter with the IP address[%s] because an adapter "
"already exists for that IP address.", adapter_handle_entry->adapter_ip_addr_str);
// Set return code to "duplicate adapter" status.
rs = kCdiStatusAdapterDuplicateEntry;
// Exit the search loop.
break;
}
}
CdiAdapterState* state_ptr = NULL;
if (rs == kCdiStatusOk) {
state_ptr = (CdiAdapterState*)CdiOsMemAllocZero(sizeof *state_ptr);
if (state_ptr == NULL) {
rs = kCdiStatusNotEnoughMemory;
}
}
if (rs == kCdiStatusOk) {
state_ptr->magic = kMagicAdapter;
// Make a copy of the adapter's initialization data.
state_ptr->adapter_data = *adapter_data_ptr;
// Make a copy of the IP string and update the copy of the adapter data to point to it. This is done so the
// caller can free the memory used by the data.
CdiOsStrCpy(state_ptr->adapter_ip_addr_str, sizeof(state_ptr->adapter_ip_addr_str),
adapter_data_ptr->adapter_ip_addr_str);
state_ptr->adapter_data.adapter_ip_addr_str = state_ptr->adapter_ip_addr_str;
switch (adapter_data_ptr->adapter_type) {
case kCdiAdapterTypeEfa:
rs = EfaNetworkAdapterInitialize(state_ptr, /*not socket-based*/ false);
break;
case kCdiAdapterTypeSocketLibfabric:
rs = EfaNetworkAdapterInitialize(state_ptr, /*socket-based*/ true);
break;
case kCdiAdapterTypeSocket:
rs = SocketNetworkAdapterInitialize(state_ptr);
break;
}
if (rs == kCdiStatusOk) {
if (state_ptr->adapter_data.tx_buffer_size_bytes) {
// Ensure returned Tx buffer pointer was set.
assert(state_ptr->adapter_data.ret_tx_buffer_ptr);
}
// Update returned Tx buffer pointer.
adapter_data_ptr->ret_tx_buffer_ptr = state_ptr->adapter_data.ret_tx_buffer_ptr;
// Ensure platform specific state got set correctly.
assert(state_ptr->functions_ptr != NULL);
}
if (rs == kCdiStatusOk) {
// Create a critical section used to protect access to connection_list.
if (!CdiOsCritSectionCreate(&state_ptr->connection_list_lock)) {
rs = kCdiStatusNotEnoughMemory;
}
}
if (rs == kCdiStatusOk) {
// Initialize the list of connections using this adapter.
CdiListInit(&state_ptr->connection_list);
// Add the structure to network adapter handle list.
CdiListAddTail(&cdi_global_context.adapter_handle_list, &state_ptr->list_entry);
}
if (rs == kCdiStatusOk) {
// Create a critical section used to protect access to adapter state data.
if (!CdiOsCritSectionCreate(&state_ptr->adapter_lock)) {
rs = kCdiStatusNotEnoughMemory;
}
}
if (rs == kCdiStatusOk) {
// Initialize the list of poll threads using this adapter.
CdiListInit(&state_ptr->poll_thread_list);
}
}
if (rs != kCdiStatusOk) {
if (state_ptr) {
CdiOsCritSectionDelete(state_ptr->adapter_lock);
CdiOsCritSectionDelete(state_ptr->connection_list_lock);
CdiOsMemFree(state_ptr);
state_ptr = NULL;
}
}
CdiOsCritSectionRelease(cdi_global_context.adapter_handle_list_lock);
*ret_handle_ptr = state_ptr;
return rs;
}