summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/HW/EXI/EXI_DeviceGecko.cpp65
-rw-r--r--Source/Core/Core/HW/EXI/EXI_DeviceGecko.h9
2 files changed, 54 insertions, 20 deletions
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceGecko.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceGecko.cpp
index 5d58f4a926..9d064582a7 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceGecko.cpp
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceGecko.cpp
@@ -99,7 +99,6 @@ bool GeckoSockServer::GetAvailableSock()
if (!waiting_socks.empty())
{
- client = std::move(waiting_socks.front());
if (clientThread.joinable())
{
client_running.Clear();
@@ -108,6 +107,9 @@ bool GeckoSockServer::GetAvailableSock()
recv_fifo = std::deque<u8>();
send_fifo = std::deque<u8>();
}
+ client = std::move(waiting_socks.front());
+ client_running.Set();
+ client_connected.Set();
clientThread = std::thread(&GeckoSockServer::ClientThread, this);
client_count++;
waiting_socks.pop();
@@ -119,8 +121,6 @@ bool GeckoSockServer::GetAvailableSock()
void GeckoSockServer::ClientThread()
{
- client_running.Set();
-
Common::SetCurrentThreadName("Gecko Client");
client->setBlocking(false);
@@ -130,7 +130,7 @@ void GeckoSockServer::ClientThread()
bool did_nothing = true;
{
- std::lock_guard lk(transfer_lock);
+ std::lock_guard lk(recv_lock);
// what's an ideal buffer size?
std::array<char, 128> buffer;
@@ -145,24 +145,35 @@ void GeckoSockServer::ClientThread()
recv_fifo.insert(recv_fifo.end(), buffer.data(), buffer.data() + got);
}
+ } // unlock recv
+
+ {
+ std::lock_guard lk(send_lock);
if (!send_fifo.empty())
{
- did_nothing = false;
+ std::size_t sent;
std::vector<char> packet(send_fifo.begin(), send_fifo.end());
- send_fifo.clear();
- if (client->send(&packet[0], packet.size()) == sf::Socket::Status::Disconnected)
+ if (client->send(packet.data(), packet.size(), sent) == sf::Socket::Status::Disconnected)
client_running.Clear();
+
+ if (sent)
+ {
+ did_nothing = false;
+
+ send_fifo.erase(send_fifo.begin(), send_fifo.begin() + sent);
+ }
}
- } // unlock transfer
+ } // unlock send
if (did_nothing)
Common::YieldCPU();
}
client->disconnect();
+ client_connected.Clear();
}
CEXIGecko::CEXIGecko(Core::System& system) : IEXIDevice(system)
@@ -174,7 +185,7 @@ void CEXIGecko::ImmReadWrite(u32& _uData, u32 _uSize)
// We don't really care about _uSize
(void)_uSize;
- if (!client || client->getLocalPort() == 0)
+ if (!client_connected.IsSet())
GetAvailableSock();
switch (_uData >> 28)
@@ -195,11 +206,15 @@ void CEXIGecko::ImmReadWrite(u32& _uData, u32 _uSize)
// |= 0x08000000 if successful
case CMD_RECV:
{
- std::lock_guard lk(transfer_lock);
- if (!recv_fifo.empty())
+ if (m_recv_buffer.empty())
+ {
+ std::lock_guard lk(recv_lock);
+ m_recv_buffer.swap(recv_fifo);
+ }
+ if (!m_recv_buffer.empty())
{
- _uData = 0x08000000 | (recv_fifo.front() << 16);
- recv_fifo.pop_front();
+ _uData = 0x08000000 | (m_recv_buffer.front() << 16);
+ m_recv_buffer.pop_front();
}
break;
}
@@ -208,24 +223,36 @@ void CEXIGecko::ImmReadWrite(u32& _uData, u32 _uSize)
// |= 0x04000000 if successful
case CMD_SEND:
{
- std::lock_guard lk(transfer_lock);
- send_fifo.push_back(_uData >> 20);
- _uData = 0x04000000;
+ std::lock_guard lk(send_lock);
+
+ if (send_fifo.size() < 1024)
+ {
+ send_fifo.push_back(_uData >> 20);
+ _uData = 0x04000000;
+ }
+ else
+ {
+ _uData = 0;
+ }
+
break;
}
// Check if ok for Gecko -> PC, or FIFO full
// |= 0x04000000 if FIFO is not full
case CMD_CHK_TX:
- _uData = 0x04000000;
+ {
+ std::lock_guard lk(send_lock);
+ _uData = send_fifo.size() < 1024 ? 0x04000000 : 0;
break;
+ }
// Check if data in FIFO for PC -> Gecko, or FIFO empty
// |= 0x04000000 if data in recv FIFO
case CMD_CHK_RX:
{
- std::lock_guard lk(transfer_lock);
- _uData = recv_fifo.empty() ? 0 : 0x04000000;
+ std::lock_guard lk(recv_lock);
+ _uData = m_recv_buffer.empty() && recv_fifo.empty() ? 0 : 0x04000000;
break;
}
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceGecko.h b/Source/Core/Core/HW/EXI/EXI_DeviceGecko.h
index 59a8041294..8765349e5a 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceGecko.h
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceGecko.h
@@ -25,9 +25,13 @@ public:
// Client for this server object
std::unique_ptr<sf::TcpSocket> client;
+ // Set before starting the client thread; cleared after it closes the socket.
+ Common::Flag client_connected{false};
void ClientThread();
std::thread clientThread;
- std::mutex transfer_lock;
+
+ std::mutex send_lock;
+ std::mutex recv_lock;
std::deque<u8> send_fifo;
std::deque<u8> recv_fifo;
@@ -65,5 +69,8 @@ private:
};
static const u32 ident = 0x04700000;
+
+ // Only accessed by the CPU thread. Refilled from recv_fifo under recv_lock
+ std::deque<u8> m_recv_buffer;
};
} // namespace ExpansionInterface