in src/cdi/adapter.c [232:331]
static bool DataPoll(AdapterConnectionState* adapter_con_state_ptr)
{
bool all_idle = true;
// Set this thread to use the connection's log. Can now use CDI_LOG_THREAD() for logging within this thread.
CdiLoggerThreadLogSet(adapter_con_state_ptr->log_handle);
assert(kEndpointDirectionBidirectional != adapter_con_state_ptr->direction); // Not supported
EndpointManagerHandle mgr_handle = EndpointManagerConnectionToEndpointManager(
adapter_con_state_ptr->data_state.cdi_connection_handle);
if (kPollStart == adapter_con_state_ptr->poll_state) {
// Register this thread with the Endpoint Manager as being part of this connection. Since this is a polling
// thread, we use the non-blocking EndpointManagerPoll() function instead of the blocking
// EndpointManagerThreadWait() function.
EndpointManagerThreadRegister(mgr_handle,
CdiOsThreadGetName(adapter_con_state_ptr->poll_thread_state_ptr->thread_id));
adapter_con_state_ptr->poll_state = kPollRunning;
} else if (kPollStopping == adapter_con_state_ptr->poll_state) {
if (EndpointManagerPollThreadExit(mgr_handle)) {
adapter_con_state_ptr->poll_state = kPollStopped;
}
return all_idle;
}
// The Endpoint Manager is used here to control suspend, restart and shutdown sequences.
if (!CdiOsSignalReadState(adapter_con_state_ptr->shutdown_signal) &&
!EndpointManagerIsConnectionShuttingDown(mgr_handle)) {
// Walk through each endpoint that is part of this connection.
CdiEndpointHandle cdi_endpoint_handle = EndpointManagerGetFirstEndpoint(mgr_handle);
if (cdi_endpoint_handle) {
// Account for poll thread sleeping (idle time).
AdapterEndpointState* adapter_endpoint_ptr = EndpointManagerEndpointToAdapterEndpoint(cdi_endpoint_handle);
UpdateThreadUtilizationStats(adapter_endpoint_ptr->endpoint_stats_ptr, true,
&adapter_con_state_ptr->load_state);
}
while (cdi_endpoint_handle) {
adapter_con_state_ptr->load_state.top_time = CdiOsGetMicroseconds();
bool idle = true;
AdapterEndpointState* adapter_endpoint_ptr = EndpointManagerEndpointToAdapterEndpoint(cdi_endpoint_handle);
// Get Endpoint Manager notification signal.
if (EndpointManagerPoll(&cdi_endpoint_handle) && adapter_endpoint_ptr) {
if (adapter_con_state_ptr->can_transmit) {
Packet* packet_ptr = NULL;
bool last_packet = false;
EndpointTransmitQueueLevel queue_level = CdiAdapterGetTransmitQueueLevel(adapter_endpoint_ptr);
bool got_packet = (kEndpointTransmitQueueFull != queue_level) &&
(NULL != (packet_ptr = GetNextPacket(adapter_endpoint_ptr, 0, NULL, &last_packet)));
if (got_packet) {
idle = false;
// Use the adapter to send the packet.
adapter_con_state_ptr->adapter_state_ptr->functions_ptr->Send(adapter_endpoint_ptr, packet_ptr,
last_packet);
// NOTE: No need to generate any error or warnings here since, the Send() will normally fail if
// the receiver is not connected (ie. during probe).
}
if (kEndpointTransmitQueueEmpty != CdiAdapterGetTransmitQueueLevel(adapter_endpoint_ptr)) {
// Packets are in flight (have not received ACKs back), so don't want this poll thread to sleep.
all_idle = false;
}
} else {
if (RxPollProcess(adapter_endpoint_ptr)) {
idle = false;
all_idle = false;
}
}
// Perform adapter specific poll mode processing.
if (kCdiStatusOk == CdiAdapterPollEndpoint(adapter_endpoint_ptr)) {
idle = false;
}
// Check if busy/idle state is different this time compared to last.
UpdateThreadUtilizationStats(adapter_endpoint_ptr->endpoint_stats_ptr, idle,
&adapter_con_state_ptr->load_state);
}
}
// Set top time to account for poll thread idle time performed outside of this function (ie. mostly sleep time).
adapter_con_state_ptr->load_state.top_time = CdiOsGetMicroseconds();
} else {
// Connection is shutting down. If a receiver, ensure receiver poll processing is performed for all endpoints
// related to this connection to flush Rx queues.
if (!adapter_con_state_ptr->can_transmit) {
CdiEndpointHandle cdi_endpoint_handle = EndpointManagerGetFirstEndpoint(mgr_handle);
while (cdi_endpoint_handle) {
AdapterEndpointState* adapter_endpoint_ptr = EndpointManagerEndpointToAdapterEndpoint(cdi_endpoint_handle);
RxPollProcess(adapter_endpoint_ptr);
cdi_endpoint_handle = EndpointManagerGetNextEndpoint(cdi_endpoint_handle);
}
}
if (kPollRunning == adapter_con_state_ptr->poll_state) {
adapter_con_state_ptr->poll_state = kPollStopping;
}
}
return all_idle;
}