Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BBA/HLE: Increase polling efficiency #12560

Merged
merged 4 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 63 additions & 20 deletions Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ void CEXIETHERNET::BuiltInBBAInterface::WriteToQueue(const std::vector<u8>& data
const u8 next_write_index = (m_queue_write + 1) & 15;
if (next_write_index != m_queue_read)
m_queue_write = next_write_index;
else
WARN_LOG_FMT(SP1, "BBA queue overrun, data might be lost");
}

bool CEXIETHERNET::BuiltInBBAInterface::WillQueueOverrun() const
{
return ((m_queue_write + 1) & 15) == m_queue_read;
}

void CEXIETHERNET::BuiltInBBAInterface::PollData(std::size_t* datasize)
Expand All @@ -140,24 +147,39 @@ void CEXIETHERNET::BuiltInBBAInterface::PollData(std::size_t* datasize)
{
for (auto& tcp_buf : net_ref.tcp_buffers)
{
if (WillQueueOverrun())
break;
if (!tcp_buf.used || (GetTickCountStd() - tcp_buf.tick) <= 1000)
continue;

tcp_buf.tick = GetTickCountStd();
// Timed out packet, resend
if (((m_queue_write + 1) & 15) != m_queue_read)
WriteToQueue(tcp_buf.data);
tcp_buf.tick = GetTickCountStd();
WriteToQueue(tcp_buf.data);
}
}

// Check for connection data
if (*datasize != 0)
continue;
const auto socket_data = TryGetDataFromSocket(&net_ref);
if (socket_data.has_value())
if (*datasize == 0)
{
*datasize = socket_data->size();
std::memcpy(m_eth_ref->mRecvBuffer.get(), socket_data->data(), *datasize);
// Send it to the network buffer if empty
const auto socket_data = TryGetDataFromSocket(&net_ref);
if (socket_data.has_value())
{
*datasize = socket_data->size();
std::memcpy(m_eth_ref->mRecvBuffer.get(), socket_data->data(), *datasize);
}
}
else if (!WillQueueOverrun())
{
// Otherwise, enqueue it
const auto socket_data = TryGetDataFromSocket(&net_ref);
if (socket_data.has_value())
WriteToQueue(*socket_data);
}
else
{
WARN_LOG_FMT(SP1, "BBA queue might overrun, can't poll more data");
return;
}
}
}
Expand Down Expand Up @@ -224,7 +246,7 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleDHCP(const Common::UDPPacket& pack
std::optional<std::vector<u8>>
CEXIETHERNET::BuiltInBBAInterface::TryGetDataFromSocket(StackRef* ref)
{
size_t datasize = 0; // Set by socket.receive using a non-const reference
std::size_t datasize = 0; // Set by socket.receive using a non-const reference
unsigned short remote_port;

switch (ref->type)
Expand All @@ -247,8 +269,24 @@ CEXIETHERNET::BuiltInBBAInterface::TryGetDataFromSocket(StackRef* ref)
}

case IPPROTO_TCP:
if (!ref->tcp_socket.Connected(ref))
switch (ref->tcp_socket.Connected(ref))
{
case BbaTcpSocket::ConnectingState::Error:
{
// Create the resulting RST ACK packet
const Common::TCPPacket result(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num,
ref->ack_num, TCP_FLAG_RST | TCP_FLAG_ACK);
WriteToQueue(result.Build());
ref->ip = 0;
ref->tcp_socket.disconnect();
[[fallthrough]];
}
case BbaTcpSocket::ConnectingState::None:
case BbaTcpSocket::ConnectingState::Connecting:
return std::nullopt;
case BbaTcpSocket::ConnectingState::Connected:
break;
}

sf::Socket::Status st = sf::Socket::Status::Done;
TcpBuffer* tcp_buffer = nullptr;
Expand Down Expand Up @@ -372,7 +410,7 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket&
{
// only if contain data
if (static_cast<int>(this_seq - ref->ack_num) >= 0 &&
data.size() >= static_cast<size_t>(size))
data.size() >= static_cast<std::size_t>(size))
{
ref->tcp_socket.send(data.data(), size);
ref->ack_num += size;
Expand Down Expand Up @@ -656,14 +694,17 @@ bool CEXIETHERNET::BuiltInBBAInterface::SendFrame(const u8* frame, u32 size)

void CEXIETHERNET::BuiltInBBAInterface::ReadThreadHandler(CEXIETHERNET::BuiltInBBAInterface* self)
{
std::size_t datasize = 0;
while (!self->m_read_thread_shutdown.IsSet())
{
// make thread less cpu hungry
std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (datasize == 0)
{
// Make thread less CPU hungry
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}

if (!self->m_read_enabled.IsSet())
continue;
size_t datasize = 0;

u8 wp = self->m_eth_ref->page_ptr(BBA_RWP);
const u8 rp = self->m_eth_ref->page_ptr(BBA_RRP);
Expand All @@ -689,6 +730,10 @@ void CEXIETHERNET::BuiltInBBAInterface::ReadThreadHandler(CEXIETHERNET::BuiltInB
self->m_queue_read++;
self->m_queue_read &= 15;
}
else
{
datasize = 0;
}

// Check network stack references
self->PollData(&datasize);
Expand Down Expand Up @@ -775,14 +820,11 @@ sf::Socket::Status BbaTcpSocket::GetSockName(sockaddr_in* addr) const
return sf::Socket::Status::Done;
}

bool BbaTcpSocket::Connected(StackRef* ref)
BbaTcpSocket::ConnectingState BbaTcpSocket::Connected(StackRef* ref)
{
// Called by ReadThreadHandler's TryGetDataFromSocket
// TODO: properly handle error state
switch (m_connecting_state)
{
case ConnectingState::Connected:
return true;
case ConnectingState::Connecting:
{
const int fd = getHandle();
Expand Down Expand Up @@ -812,6 +854,7 @@ bool BbaTcpSocket::Connected(StackRef* ref)
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&error), &len) != 0)
{
ERROR_LOG_FMT(SP1, "Failed to get BBA socket error state: {}", Common::StrNetworkError());
m_connecting_state = ConnectingState::Error;
break;
}

Expand Down Expand Up @@ -856,7 +899,7 @@ bool BbaTcpSocket::Connected(StackRef* ref)
default:
break;
}
return false;
return m_connecting_state;
}

BbaUdpSocket::BbaUdpSocket() = default;
Expand Down
6 changes: 3 additions & 3 deletions Source/Core/Core/HW/EXI/BBA/BuiltIn.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ class BbaTcpSocket : public sf::TcpSocket
sf::Socket::Status GetPeerName(sockaddr_in* addr) const;
sf::Socket::Status GetSockName(sockaddr_in* addr) const;

bool Connected(StackRef* ref);

private:
enum class ConnectingState
{
None,
Expand All @@ -59,6 +56,9 @@ class BbaTcpSocket : public sf::TcpSocket
Error
};

ConnectingState Connected(StackRef* ref);

private:
ConnectingState m_connecting_state = ConnectingState::None;
};

Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/HW/EXI/EXI_DeviceEthernet.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ class CEXIETHERNET : public IEXIDevice
static void ReadThreadHandler(BuiltInBBAInterface* self);
#endif
void WriteToQueue(const std::vector<u8>& data);
bool WillQueueOverrun() const;
void PollData(std::size_t* datasize);
std::optional<std::vector<u8>> TryGetDataFromSocket(StackRef* ref);

Expand Down