Skip to content

Commit

Permalink
review
Browse files Browse the repository at this point in the history
  • Loading branch information
Sonicadvance1 committed Jan 28, 2025
1 parent 83ce2d8 commit d85101b
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 54 deletions.
79 changes: 43 additions & 36 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/GdbServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,12 @@ fextl::string GdbServer::ReadPacket() {
break;
case '}': // escape char
{
auto escaped = CommsStream.get();
Utils::NetStream::ReturnGet escaped;

do {
escaped = CommsStream.get();
} while (!escaped.HasData() && !escaped.HasHangup());

if (escaped.HasData()) {
packet.push_back(escaped.GetData() ^ 0x20);
} else {
Expand All @@ -214,7 +219,7 @@ fextl::string GdbServer::ReadPacket() {
case '#': // end of packet
{
char hexString[3] = {0, 0, 0};
CommsStream.read(hexString, 2);
CommsStream.read(hexString, 2, true);
int expected_checksum = std::strtoul(hexString, nullptr, 16);

if (calculateChecksum(packet) == expected_checksum) {
Expand Down Expand Up @@ -1395,45 +1400,47 @@ void GdbServer::GdbServerLoop() {

HandledPacketType response {};

// Outer server loop. Handles packet start, ACK/NAK and break
Utils::NetStream::ReturnGet c;
while (!CoreShuttingDown.load() && (c = CommsStream.get()).HasData()) {
switch (c.GetData()) {
case '$': {
auto packet = ReadPacket();
response = ProcessPacket(packet);
SendPacketPair(response);
if (response.TypeResponse == HandledPacketType::TYPE_UNKNOWN) {
LogMan::Msg::DFmt("Unknown packet {}", packet);
while (!CoreShuttingDown.load()) {
// Outer server loop. Handles packet start, ACK/NAK and break
Utils::NetStream::ReturnGet c;
while ((c = CommsStream.get()).HasData()) {
switch (c.GetData()) {
case '$': {
auto packet = ReadPacket();
response = ProcessPacket(packet);
SendPacketPair(response);
if (response.TypeResponse == HandledPacketType::TYPE_UNKNOWN) {
LogMan::Msg::DFmt("Unknown packet {}", packet);
}
break;
}
break;
}
case '+':
// ACK, do nothing.
break;
case '-':
// NAK, Resend requested
{
std::lock_guard lk(sendMutex);
SendPacket(response.Response);
case '+':
// ACK, do nothing.
break;
case '-':
// NAK, Resend requested
{
std::lock_guard lk(sendMutex);
SendPacket(response.Response);
}
break;
case '\x03': { // ASCII EOT
SyscallHandler->TM.Pause();
fextl::string str = fextl::fmt::format("T02thread:{:02x};", getpid());
if (LibraryMapChanged) {
// If libraries have changed then let gdb know
str += "library:1;";
}
SendPacketPair({std::move(str), HandledPacketType::TYPE_ACK});
break;
}
break;
case '\x03': { // ASCII EOT
SyscallHandler->TM.Pause();
fextl::string str = fextl::fmt::format("T02thread:{:02x};", getpid());
if (LibraryMapChanged) {
// If libraries have changed then let gdb know
str += "library:1;";
default: LogMan::Msg::DFmt("GdbServer: Unexpected byte {} ({:02x})", c.GetData(), c.GetData());
}
SendPacketPair({std::move(str), HandledPacketType::TYPE_ACK});
break;
}
default: LogMan::Msg::DFmt("GdbServer: Unexpected byte {} ({:02x})", c.GetData(), c.GetData());
}
}

if (c.HasHangup()) {
break;
if (c.HasHangup()) {
break;
}
}

{
Expand Down
61 changes: 46 additions & 15 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/NetStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@
#include <FEXCore/Utils/LogManager.h>

#include <cstring>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <poll.h>
#include <unistd.h>

namespace FEX::Utils {

NetStream::NetStream()
: receive_buffer(1500) {
eventfd = ::eventfd(0, EFD_CLOEXEC);
}

NetStream::ReturnGet NetStream::get() {
if (read_offset != receive_buffer.size() && read_offset != receive_offset) {
auto Result = receive_buffer.at(read_offset);
Expand All @@ -22,43 +29,67 @@ NetStream::ReturnGet NetStream::get() {
receive_offset = 0;
}

struct pollfd pfd {
.fd = socketfd, .events = POLLIN, .revents = 0,
struct pollfd pfds[2] = {
{
.fd = socketfd,
.events = POLLIN,
.revents = 0,
},

{
.fd = eventfd,
.events = POLLIN,
.revents = 0,
},
};

auto Result = ppoll(&pfd, 1, nullptr, nullptr);
auto Result = poll(pfds, sizeof(pfds), -1);
if (Result > 0) {
if (pfd.revents & POLLHUP) {
return NetStream::ReturnGet {true};
}
for (auto& pfd : pfds) {
if (pfd.fd == eventfd) {
// Interrupted by eventfd.
uint64_t data;
::read(pfd.fd, &data, sizeof(data));
break;
}

if (pfd.revents & POLLHUP) {
return NetStream::ReturnGet {true};
}

const auto remaining_size = receive_buffer.size() - receive_offset;
Result = ::recv(socketfd, &receive_buffer.at(receive_offset), remaining_size, 0);
if (Result > 0) {
receive_offset += Result;
auto Result = receive_buffer.at(read_offset);
++read_offset;
return NetStream::ReturnGet {Result};
const auto remaining_size = receive_buffer.size() - receive_offset;
Result = ::recv(socketfd, &receive_buffer.at(receive_offset), remaining_size, 0);
if (Result > 0) {
receive_offset += Result;
auto Result = receive_buffer.at(read_offset);
++read_offset;
return NetStream::ReturnGet {Result};
}
}
}

return NetStream::ReturnGet {false};
}

size_t NetStream::read(char* buf, size_t size) {
size_t NetStream::read(char* buf, size_t size, bool ContinueOnInterrupt) {
size_t Read {};
while (Read < size) {
auto Result = get();
if (Result.HasData()) {
buf[Read] = Result.GetData();
++Read;
} else {
} else if ((!Result.HasData() && !ContinueOnInterrupt) || Result.HasHangup()) {
return Read;
}
}
return Read;
}

void NetStream::InterruptReader() {
uint64_t data {1};
::write(eventfd, &data, sizeof(data));
}

bool NetStream::SendPacket(const fextl::string& packet) {
size_t Total {};
while (Total < packet.size()) {
Expand Down
9 changes: 6 additions & 3 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/NetStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
namespace FEX::Utils {
class NetStream final {
public:
NetStream()
: receive_buffer(1500) {}
NetStream();

void OpenSocket(int _socketfd) {
socketfd = _socketfd;
Expand All @@ -37,12 +36,16 @@ class NetStream final {
return std::get<char>(*this);
}
};

ReturnGet get();
size_t read(char* buf, size_t size);
size_t read(char* buf, size_t size, bool ContinueOnInterrupt);

void InterruptReader();

bool SendPacket(const fextl::string& packet);
private:
int socketfd {-1};
int eventfd {-1};
size_t read_offset {};
size_t receive_offset {};
fextl::vector<char> receive_buffer;
Expand Down

0 comments on commit d85101b

Please sign in to comment.