Speedup GDB data processing (#89)

This commit is contained in:
Maurice Heumann
2025-01-18 20:42:40 +01:00
committed by GitHub
4 changed files with 111 additions and 27 deletions

View File

@@ -27,6 +27,23 @@ namespace gdb_stub
: client_(client)
{
this->client_.set_blocking(false);
this->stop_ = false;
this->output_thread_ = std::thread([this] {
this->transmission_loop(); //
});
}
connection_handler::~connection_handler()
{
this->stop_ = true;
this->condition_variable_.notify_all();
if (this->output_thread_.joinable())
{
this->output_thread_.join();
}
}
std::optional<std::string> connection_handler::get_packet()
@@ -35,7 +52,7 @@ namespace gdb_stub
{
if (!read_from_socket(this->processor_, this->client_))
{
std::this_thread::sleep_for(100ms);
(void)this->client_.sleep(100ms, true);
}
}
@@ -47,19 +64,67 @@ namespace gdb_stub
return std::nullopt;
}
void connection_handler::send_reply(const std::string_view data) const
void connection_handler::send_reply(const std::string_view data)
{
const auto checksum = utils::string::to_hex_string(compute_checksum(data));
this->send_raw_data("$" + std::string(data) + "#" + checksum);
}
void connection_handler::send_raw_data(const std::string_view data) const
void connection_handler::send_raw_data(const std::string_view data)
{
(void)this->client_.send(data);
{
std::lock_guard _{this->mutex_};
this->output_stream_.append(data);
}
this->condition_variable_.notify_one();
}
bool connection_handler::should_stop() const
{
return this->stop_ || !this->client_.is_valid();
}
void connection_handler::close() const
{
this->client_.close();
}
void connection_handler::await_transmission(const std::function<void()>& handler)
{
std::unique_lock lock{this->mutex_};
const auto can_run = [this] {
return this->should_stop() //
|| !this->output_stream_.empty();
};
const auto run = this->condition_variable_.wait_for(lock, 100ms, can_run);
if (run && !this->should_stop())
{
handler();
}
}
std::string connection_handler::get_next_data_to_transmit()
{
std::string transmit_data{};
this->await_transmission([&] {
transmit_data = std::move(this->output_stream_);
this->output_stream_ = {};
});
return transmit_data;
}
void connection_handler::transmission_loop()
{
while (!this->should_stop())
{
const auto data = this->get_next_data_to_transmit();
(void)this->client_.send(data);
}
}
}

View File

@@ -1,23 +1,48 @@
#pragma once
#include "stream_processor.hpp"
#include <utils/concurrency.hpp>
#include <network/tcp_client_socket.hpp>
#include <thread>
#include <functional>
#include <condition_variable>
namespace gdb_stub
{
class connection_handler
{
public:
connection_handler(network::tcp_client_socket& client);
~connection_handler();
connection_handler(connection_handler&&) = delete;
connection_handler(const connection_handler&) = delete;
connection_handler& operator=(connection_handler&&) = delete;
connection_handler& operator=(const connection_handler&) = delete;
std::optional<std::string> get_packet();
void send_reply(std::string_view data) const;
void send_raw_data(std::string_view data) const;
void send_reply(std::string_view data);
void send_raw_data(std::string_view data);
void close() const;
bool should_stop() const;
private:
network::tcp_client_socket& client_;
stream_processor processor_{};
std::mutex mutex_{};
std::atomic_bool stop_{};
std::string output_stream_{};
std::thread output_thread_{};
std::condition_variable condition_variable_{};
void transmission_loop();
void await_transmission(const std::function<void()>& handler);
std::string get_next_data_to_transmit();
};
}

View File

@@ -49,8 +49,7 @@ namespace gdb_stub
return {name, args};
}
void process_xfer(const connection_handler& connection, debugging_handler& handler,
const std::string_view payload)
void process_xfer(connection_handler& connection, debugging_handler& handler, const std::string_view payload)
{
auto [name, args] = split_string(payload, ':');
@@ -66,8 +65,7 @@ namespace gdb_stub
}
}
void process_query(const connection_handler& connection, debugging_handler& handler,
const std::string_view payload)
void process_query(connection_handler& connection, debugging_handler& handler, const std::string_view payload)
{
const auto [name, args] = split_string(payload, ':');
@@ -93,7 +91,7 @@ namespace gdb_stub
}
}
void process_action(const connection_handler& connection, const action a)
void process_action(connection_handler& connection, const action a)
{
if (a == action::shutdown)
{
@@ -122,8 +120,8 @@ namespace gdb_stub
return handler.delete_breakpoint(type, address, size);
}
void handle_breakpoint(const connection_handler& connection, debugging_handler& handler,
const std::string& data, const bool set)
void handle_breakpoint(connection_handler& connection, debugging_handler& handler, const std::string& data,
const bool set)
{
uint32_t type{};
uint64_t addr{};
@@ -134,7 +132,7 @@ namespace gdb_stub
connection.send_reply(res ? "OK" : "E01");
}
void handle_v_packet(const connection_handler& connection, const std::string_view data)
void handle_v_packet(connection_handler& connection, const std::string_view data)
{
const auto [name, args] = split_string(data, ':');
@@ -151,7 +149,7 @@ namespace gdb_stub
}
}
void read_registers(const connection_handler& connection, debugging_handler& handler)
void read_registers(connection_handler& connection, debugging_handler& handler)
{
std::string response{};
std::vector<std::byte> data{};
@@ -176,8 +174,7 @@ namespace gdb_stub
connection.send_reply(response);
}
void write_registers(const connection_handler& connection, debugging_handler& handler,
const std::string_view payload)
void write_registers(connection_handler& connection, debugging_handler& handler, const std::string_view payload)
{
const auto data = utils::string::from_hex_string(payload);
@@ -207,7 +204,7 @@ namespace gdb_stub
connection.send_reply("OK");
}
void read_single_register(const connection_handler& connection, debugging_handler& handler,
void read_single_register(connection_handler& connection, debugging_handler& handler,
const std::string& payload)
{
size_t reg{};
@@ -228,7 +225,7 @@ namespace gdb_stub
}
}
void write_single_register(const connection_handler& connection, debugging_handler& handler,
void write_single_register(connection_handler& connection, debugging_handler& handler,
const std::string_view payload)
{
const auto [reg, hex_data] = split_string(payload, '=');
@@ -245,7 +242,7 @@ namespace gdb_stub
connection.send_reply(res ? "OK" : "E01");
}
void read_memory(const connection_handler& connection, debugging_handler& handler, const std::string& payload)
void read_memory(connection_handler& connection, debugging_handler& handler, const std::string& payload)
{
uint64_t address{};
size_t size{};
@@ -270,8 +267,7 @@ namespace gdb_stub
connection.send_reply(utils::string::to_hex_string(data));
}
void write_memory(const connection_handler& connection, debugging_handler& handler,
const std::string_view payload)
void write_memory(connection_handler& connection, debugging_handler& handler, const std::string_view payload)
{
const auto [info, hex_data] = split_string(payload, ':');
@@ -318,8 +314,7 @@ namespace gdb_stub
return result;
}
void write_x_memory(const connection_handler& connection, debugging_handler& handler,
const std::string_view payload)
void write_x_memory(connection_handler& connection, debugging_handler& handler, const std::string_view payload)
{
const auto [info, encoded_data] = split_string(payload, ':');
@@ -346,7 +341,7 @@ namespace gdb_stub
connection.send_reply("OK");
}
void handle_command(const connection_handler& connection, async_handler& async, debugging_handler& handler,
void handle_command(connection_handler& connection, async_handler& async, debugging_handler& handler,
const uint8_t command, const std::string_view data)
{
// printf("GDB command: %c -> %.*s\n", command, static_cast<int>(data.size()), data.data());
@@ -420,7 +415,7 @@ namespace gdb_stub
}
}
void process_packet(const connection_handler& connection, async_handler& async, debugging_handler& handler,
void process_packet(connection_handler& connection, async_handler& async, debugging_handler& handler,
const std::string_view packet)
{
connection.send_raw_data("+");

View File

@@ -1,7 +1,6 @@
#pragma once
#include <queue>
#include <string>
#include <optional>
namespace gdb_stub
{