Fixing debugger startup race.

This commit is contained in:
Ben Vanik
2015-07-29 19:52:53 -07:00
parent 19901c4759
commit 122114d1d1
10 changed files with 78 additions and 11 deletions

View File

@@ -10,6 +10,8 @@
#ifndef XENIA_DEBUG_DEBUG_SERVER_H_
#define XENIA_DEBUG_DEBUG_SERVER_H_
#include <functional>
#include "xenia/cpu/function.h"
#include "xenia/cpu/processor.h"
#include "xenia/debug/breakpoint.h"
@@ -27,6 +29,8 @@ class DebugServer {
virtual bool Initialize() = 0;
virtual void PostSynchronous(std::function<void()> fn) = 0;
// TODO(benvanik): better thread type (XThread?)
// virtual void OnThreadCreated(ThreadState* thread_state) = 0;
// virtual void OnThreadDestroyed(ThreadState* thread_state) = 0;

View File

@@ -123,7 +123,7 @@ void Debugger::PreLaunch() {
// Start paused.
execution_state_ = ExecutionState::kRunning;
Interrupt();
server_->PostSynchronous([this]() { Interrupt(); });
} else {
// Start running.
execution_state_ = ExecutionState::kRunning;

View File

@@ -44,6 +44,8 @@ bool GdbServer::Initialize() {
return true;
}
void GdbServer::PostSynchronous(std::function<void()> fn) { assert_always(); }
void GdbServer::AcceptClient(std::unique_ptr<Socket> client) {
// If we have an existing client, kill it and join its thread.
if (client_) {

View File

@@ -32,6 +32,8 @@ class GdbServer : public DebugServer {
bool Initialize() override;
void PostSynchronous(std::function<void()> fn) override;
private:
void AcceptClient(std::unique_ptr<Socket> client);
bool HandleClientEvent();

View File

@@ -44,6 +44,8 @@ bool MIServer::Initialize() {
return true;
}
void MIServer::PostSynchronous(std::function<void()> fn) { assert_always(); }
void MIServer::AcceptClient(std::unique_ptr<Socket> client) {
// If we have an existing client, kill it and join its thread.
if (client_) {

View File

@@ -32,6 +32,8 @@ class MIServer : public DebugServer {
bool Initialize() override;
void PostSynchronous(std::function<void()> fn) override;
private:
void AcceptClient(std::unique_ptr<Socket> client);
bool HandleClientEvent();

View File

@@ -42,6 +42,8 @@ XdpServer::XdpServer(Debugger* debugger)
XdpServer::~XdpServer() = default;
bool XdpServer::Initialize() {
post_event_ = xe::threading::Event::CreateAutoResetEvent(false);
socket_server_ = SocketServer::Create(uint16_t(FLAGS_xdp_server_port),
[this](std::unique_ptr<Socket> client) {
AcceptClient(std::move(client));
@@ -54,6 +56,19 @@ bool XdpServer::Initialize() {
return true;
}
void XdpServer::PostSynchronous(std::function<void()> fn) {
xe::threading::Fence fence;
{
std::lock_guard<std::mutex> lock(post_mutex_);
post_queue_.push_back([&fence, fn]() {
fn();
fence.Signal();
});
}
post_event_->Set();
fence.Wait();
}
void XdpServer::AcceptClient(std::unique_ptr<Socket> client) {
// If we have an existing client, kill it and join its thread.
if (client_) {
@@ -85,11 +100,35 @@ void XdpServer::AcceptClient(std::unique_ptr<Socket> client) {
// Main loop.
bool running = true;
while (running) {
auto wait_result = xe::threading::Wait(client_->wait_handle(), true);
switch (wait_result) {
xe::threading::WaitHandle* wait_handles[] = {
client_->wait_handle(), post_event_.get(),
};
auto wait_result = xe::threading::WaitMultiple(
wait_handles, xe::countof(wait_handles), false, true);
switch (wait_result.first) {
case xe::threading::WaitResult::kSuccess:
// Event (read or close).
running = HandleClientEvent();
switch (wait_result.second) {
case 0: {
running = HandleClientEvent();
} break;
case 1: {
bool has_remaining = true;
while (has_remaining) {
std::function<void()> fn;
{
std::lock_guard<std::mutex> lock(post_mutex_);
fn = std::move(post_queue_.front());
post_queue_.pop_front();
has_remaining = !post_queue_.empty();
if (!has_remaining) {
post_event_->Reset();
}
}
fn();
}
} break;
}
continue;
case xe::threading::WaitResult::kAbandoned:
case xe::threading::WaitResult::kFailed:

View File

@@ -10,7 +10,9 @@
#ifndef XENIA_DEBUG_SERVER_XDP_XDP_SERVER_H_
#define XENIA_DEBUG_SERVER_XDP_XDP_SERVER_H_
#include <list>
#include <memory>
#include <mutex>
#include "xenia/base/socket.h"
#include "xenia/base/threading.h"
@@ -33,6 +35,8 @@ class XdpServer : public DebugServer {
bool Initialize() override;
void PostSynchronous(std::function<void()> fn) override;
void OnExecutionContinued() override;
void OnExecutionInterrupted() override;
@@ -54,6 +58,11 @@ class XdpServer : public DebugServer {
std::unique_ptr<Socket> client_;
std::unique_ptr<xe::threading::Thread> client_thread_;
std::mutex post_mutex_;
std::unique_ptr<xe::threading::Event> post_event_;
std::list<std::function<void()>> post_queue_;
std::vector<uint8_t> receive_buffer_;
proto::PacketReader packet_reader_;
proto::PacketWriter packet_writer_;