Suspend/resume working.

This commit is contained in:
Ben Vanik 2013-12-23 19:46:35 -08:00
parent dc48b0a85a
commit 98efc7ddfa
11 changed files with 95 additions and 28 deletions

View File

@ -247,7 +247,7 @@ module.controller('FunctionViewController', function(
instance, line, gutterClass, e) { instance, line, gutterClass, e) {
if (e.which == 1) { if (e.which == 1) {
if (gutterClass == 'debugger-fnview-gutter-icon' || if (gutterClass == 'debugger-fnview-gutter-icon' ||
gutterClsas == 'debugger-fnview-gutter-addr') { gutterClass == 'debugger-fnview-gutter-addr') {
var sourceLine = $scope.sourceLines[line]; var sourceLine = $scope.sourceLines[line];
if (!sourceLine || sourceLine[0] != 'i') { if (!sourceLine || sourceLine[0] != 'i') {
return; return;

View File

@ -145,9 +145,10 @@ module.service('DataSource', function($q) {
}); });
}; };
DataSource.prototype.stepNext = function() { DataSource.prototype.stepNext = function(threadId) {
return this.issue({ return this.issue({
command: 'cpu.step' command: 'cpu.step',
threadId: threadId
}); });
}; };

View File

@ -224,6 +224,10 @@ module.service('Session', function(
}; };
Session.prototype.onBreakpointHit = function(breakpointId, threadId) { Session.prototype.onBreakpointHit = function(breakpointId, threadId) {
// Now paused!
this.paused = true;
if (breakpointId) {
var breakpoint = this.breakpointsById[breakpointId]; var breakpoint = this.breakpointsById[breakpointId];
var thread = null; // TODO var thread = null; // TODO
if (!breakpoint) { if (!breakpoint) {
@ -231,8 +235,8 @@ module.service('Session', function(
return; return;
} }
// Now paused! log.info('Breakpoint hit at 0x' +
this.paused = true; breakpoint.address.toString(16).toUpperCase() + '.');
$state.go('session.code.function', { $state.go('session.code.function', {
'function': breakpoint.fnAddress.toString(16).toUpperCase(), 'function': breakpoint.fnAddress.toString(16).toUpperCase(),
@ -241,9 +245,10 @@ module.service('Session', function(
notify: false, notify: false,
reloadOnSearch: false reloadOnSearch: false
}); });
} else {
// // Just a general pause.
log.info('breakpoint!!'); log.info('Execution paused.');
}
}; };
Session.prototype.continueExecution = function() { Session.prototype.continueExecution = function() {
@ -252,6 +257,7 @@ module.service('Session', function(
} }
this.paused = false; this.paused = false;
this.dataSource.continueExecution().then(function() { this.dataSource.continueExecution().then(function() {
log.info('Execution resumed.');
}, function(e) { }, function(e) {
log.error('Unable to continue: ' + e); log.error('Unable to continue: ' + e);
}); });
@ -261,18 +267,20 @@ module.service('Session', function(
if (!this.dataSource) { if (!this.dataSource) {
return; return;
} }
this.paused = true;
this.dataSource.breakExecution().then(function() { this.dataSource.breakExecution().then(function() {
log.info('Execution paused.');
}, function(e) { }, function(e) {
log.error('Unable to break: ' + e); log.error('Unable to break: ' + e);
}); });
}; };
Session.prototype.stepNext = function() { Session.prototype.stepNext = function(threadId) {
if (!this.dataSource) { if (!this.dataSource) {
return; return;
} }
this.paused = false; this.paused = false;
this.dataSource.breakExecution().then(function() { this.dataSource.stepNext(threadId).then(function() {
}, function(e) { }, function(e) {
log.error('Unable to step: ' + e); log.error('Unable to step: ' + e);
}); });

View File

@ -119,11 +119,19 @@ int IVMFunction::CallImpl(ThreadState* thread_state, uint64_t return_address) {
ics.return_address = return_address; ics.return_address = return_address;
ics.call_return_address = 0; ics.call_return_address = 0;
volatile int* suspend_flag_address = thread_state->suspend_flag_address();
// TODO(benvanik): DID_CARRY -- need HIR to set a OPCODE_FLAG_SET_CARRY // TODO(benvanik): DID_CARRY -- need HIR to set a OPCODE_FLAG_SET_CARRY
// or something so the fns can set an ics flag. // or something so the fns can set an ics flag.
uint32_t ia = 0; uint32_t ia = 0;
while (true) { while (true) {
// Check suspend. We could do this only on certain instructions, if we
// wanted to speed things up.
if (*suspend_flag_address) {
thread_state->EnterSuspend();
}
IntCode* i = &intcodes_[ia]; IntCode* i = &intcodes_[ia];
if (i->debug_flags) { if (i->debug_flags) {

View File

@ -190,7 +190,7 @@ typedef struct XECACHEALIGN64 PPCContext_s {
uint8_t* membase; uint8_t* membase;
runtime::Runtime* runtime; runtime::Runtime* runtime;
runtime::ThreadState* thread_state; runtime::ThreadState* thread_state;
uint32_t suspend_flag; volatile int suspend_flag;
void SetRegFromString(const char* name, const char* value); void SetRegFromString(const char* name, const char* value);
bool CompareRegWithString(const char* name, const char* value, bool CompareRegWithString(const char* name, const char* value,

View File

@ -63,12 +63,12 @@ int Debugger::ResumeThread(uint32_t thread_id) {
return result; return result;
} }
int Debugger::ResumeAllThreads() { int Debugger::ResumeAllThreads(bool force) {
int result = 0; int result = 0;
LockMutex(threads_lock_); LockMutex(threads_lock_);
for (auto it = threads_.begin(); it != threads_.end(); ++it) { for (auto it = threads_.begin(); it != threads_.end(); ++it) {
ThreadState* thread_state = it->second; ThreadState* thread_state = it->second;
if (thread_state->Resume()) { if (thread_state->Resume(force)) {
result = 1; result = 1;
} }
} }

View File

@ -84,7 +84,7 @@ public:
int SuspendAllThreads(uint32_t timeout_ms = UINT_MAX); int SuspendAllThreads(uint32_t timeout_ms = UINT_MAX);
int ResumeThread(uint32_t thread_id); int ResumeThread(uint32_t thread_id);
int ResumeAllThreads(); int ResumeAllThreads(bool force = false);
int AddBreakpoint(Breakpoint* breakpoint); int AddBreakpoint(Breakpoint* breakpoint);
int RemoveBreakpoint(Breakpoint* breakpoint); int RemoveBreakpoint(Breakpoint* breakpoint);

View File

@ -32,8 +32,10 @@ public:
void* backend_data() const { return backend_data_; } void* backend_data() const { return backend_data_; }
void* raw_context() const { return raw_context_; } void* raw_context() const { return raw_context_; }
virtual volatile int* suspend_flag_address() const = 0;
virtual int Suspend(uint32_t timeout_ms = UINT_MAX) = 0; virtual int Suspend(uint32_t timeout_ms = UINT_MAX) = 0;
virtual int Resume() = 0; virtual int Resume(bool force = false) = 0;
virtual void EnterSuspend() = 0;
static void Bind(ThreadState* thread_state); static void Bind(ThreadState* thread_state);
static ThreadState* Get(); static ThreadState* Get();

View File

@ -218,6 +218,10 @@ void Processor::OnDebugClientDisconnected(uint32_t client_id) {
debug_client_states_.erase(client_id); debug_client_states_.erase(client_id);
xe_mutex_unlock(debug_client_states_lock_); xe_mutex_unlock(debug_client_states_lock_);
delete client_state; delete client_state;
// Whenever we support multiple clients we will need to respect pause
// settings. For now, resume until running.
runtime_->debugger()->ResumeAllThreads(true);
} }
json_t* Processor::OnDebugRequest( json_t* Processor::OnDebugRequest(
@ -417,6 +421,21 @@ json_t* Processor::OnDebugRequest(
return json_string("Unable to remove breakpoints"); return json_string("Unable to remove breakpoints");
} }
return json_null(); return json_null();
} else if (xestrcmpa(command, "continue") == 0) {
if (runtime_->debugger()->ResumeAllThreads()) {
succeeded = false;
return json_string("Unable to resume threads");
}
return json_null();
} else if (xestrcmpa(command, "break") == 0) {
if (runtime_->debugger()->SuspendAllThreads()) {
succeeded = false;
return json_string("Unable to suspend threads");
}
return json_null();
} else if (xestrcmpa(command, "step") == 0) {
// threadId
return json_null();
} else { } else {
succeeded = false; succeeded = false;
return json_string("Unknown command"); return json_string("Unknown command");

View File

@ -28,6 +28,8 @@ XenonThreadState::XenonThreadState(
stack_address_ = memory_->HeapAlloc( stack_address_ = memory_->HeapAlloc(
0, stack_size, MEMORY_FLAG_ZERO); 0, stack_size, MEMORY_FLAG_ZERO);
debug_break_ = CreateEvent(NULL, FALSE, FALSE, NULL);
// Allocate with 64b alignment. // Allocate with 64b alignment.
context_ = (PPCContext*)xe_malloc_aligned(sizeof(PPCContext)); context_ = (PPCContext*)xe_malloc_aligned(sizeof(PPCContext));
XEASSERT(((uint64_t)context_ & 0xF) == 0); XEASSERT(((uint64_t)context_ & 0xF) == 0);
@ -53,6 +55,8 @@ XenonThreadState::XenonThreadState(
XenonThreadState::~XenonThreadState() { XenonThreadState::~XenonThreadState() {
runtime_->debugger()->OnThreadDestroyed(this); runtime_->debugger()->OnThreadDestroyed(this);
CloseHandle(debug_break_);
alloy::tracing::WriteEvent(EventType::ThreadDeinit({ alloy::tracing::WriteEvent(EventType::ThreadDeinit({
})); }));
@ -60,10 +64,31 @@ XenonThreadState::~XenonThreadState() {
memory_->HeapFree(stack_address_, stack_size_); memory_->HeapFree(stack_address_, stack_size_);
} }
volatile int* XenonThreadState::suspend_flag_address() const {
return &context_->suspend_flag;
}
int XenonThreadState::Suspend(uint32_t timeout_ms) { int XenonThreadState::Suspend(uint32_t timeout_ms) {
// Set suspend flag.
// One of the checks should call in to OnSuspend() at some point.
xe_atomic_inc_32(&context_->suspend_flag);
return 0; return 0;
} }
int XenonThreadState::Resume() { int XenonThreadState::Resume(bool force) {
if (context_->suspend_flag) {
if (force) {
context_->suspend_flag = 0;
SetEvent(debug_break_);
} else {
if (!xe_atomic_dec_32(&context_->suspend_flag)) {
SetEvent(debug_break_);
}
}
}
return 0; return 0;
} }
void XenonThreadState::EnterSuspend() {
WaitForSingleObject(debug_break_, INFINITE);
}

View File

@ -31,8 +31,10 @@ public:
PPCContext* context() const { return context_; } PPCContext* context() const { return context_; }
virtual volatile int* suspend_flag_address() const;
virtual int Suspend(uint32_t timeout_ms = UINT_MAX); virtual int Suspend(uint32_t timeout_ms = UINT_MAX);
virtual int Resume(); virtual int Resume(bool force = false);
virtual void EnterSuspend();
private: private:
size_t stack_size_; size_t stack_size_;
@ -44,6 +46,8 @@ private:
// NOTE: must be 64b aligned for SSE ops. // NOTE: must be 64b aligned for SSE ops.
PPCContext* context_; PPCContext* context_;
HANDLE debug_break_;
}; };