mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-05 05:18:40 +00:00
implement 'priority thread' in demon, to prefer debug events from selected thread - greatly improves multithreaded stepping
This commit is contained in:
@@ -5870,6 +5870,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
|||||||
//- rjf: setup run controls
|
//- rjf: setup run controls
|
||||||
//
|
//
|
||||||
DMN_RunCtrls run_ctrls = {0};
|
DMN_RunCtrls run_ctrls = {0};
|
||||||
|
run_ctrls.priority_thread = target_thread.dmn_handle;
|
||||||
run_ctrls.ignore_previous_exception = 1;
|
run_ctrls.ignore_previous_exception = 1;
|
||||||
run_ctrls.run_entity_count = frozen_threads.count;
|
run_ctrls.run_entity_count = frozen_threads.count;
|
||||||
run_ctrls.run_entities = push_array(scratch.arena, DMN_Handle, run_ctrls.run_entity_count);
|
run_ctrls.run_entities = push_array(scratch.arena, DMN_Handle, run_ctrls.run_entity_count);
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ struct DMN_TrapChunkList
|
|||||||
typedef struct DMN_RunCtrls DMN_RunCtrls;
|
typedef struct DMN_RunCtrls DMN_RunCtrls;
|
||||||
struct DMN_RunCtrls
|
struct DMN_RunCtrls
|
||||||
{
|
{
|
||||||
|
DMN_Handle priority_thread;
|
||||||
DMN_Handle single_step_thread;
|
DMN_Handle single_step_thread;
|
||||||
B8 ignore_previous_exception;
|
B8 ignore_previous_exception;
|
||||||
B8 run_entities_are_unfrozen;
|
B8 run_entities_are_unfrozen;
|
||||||
|
|||||||
@@ -1801,40 +1801,14 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////
|
|
||||||
//- rjf: resume threads which will run
|
|
||||||
//
|
|
||||||
ProfScope("resume threads which will run")
|
|
||||||
{
|
|
||||||
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
|
|
||||||
{
|
|
||||||
DMN_W32_Entity *thread = n->v;
|
|
||||||
DWORD resume_result = ResumeThread(thread->handle);
|
|
||||||
switch(resume_result)
|
|
||||||
{
|
|
||||||
case 0xffffffffu:
|
|
||||||
{
|
|
||||||
// TODO(rjf): error - unknown cause. need to do GetLastError, FormatMessage
|
|
||||||
}break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
DWORD desired_counter = 0;
|
|
||||||
DWORD current_counter = resume_result - 1;
|
|
||||||
if(current_counter != desired_counter)
|
|
||||||
{
|
|
||||||
// NOTE(rjf): Warning. The user has manually suspended this thread,
|
|
||||||
// so even though from Demon's perspective it thinks this thread
|
|
||||||
// should run, it will not, because the user has manually called
|
|
||||||
// SuspendThread or used CREATE_SUSPENDED or whatever.
|
|
||||||
}
|
|
||||||
}break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
//- rjf: loop, consume win32 debug events until we produce the relevant demon events
|
//- rjf: loop, consume win32 debug events until we produce the relevant demon events
|
||||||
//
|
//
|
||||||
|
B32 priority_mode = !dmn_handle_match(dmn_handle_zero(), ctrls->priority_thread);
|
||||||
|
B32 did_priority_mode = priority_mode;
|
||||||
|
B32 do_threads_resume = 1;
|
||||||
|
DMN_W32_EntityNode *first_ran_thread = 0;
|
||||||
|
DMN_W32_EntityNode *last_ran_thread = 0;
|
||||||
U64 begin_time = os_now_microseconds();
|
U64 begin_time = os_now_microseconds();
|
||||||
String8List debug_strings = {0};
|
String8List debug_strings = {0};
|
||||||
DMN_Event *debug_strings_event = 0;
|
DMN_Event *debug_strings_event = 0;
|
||||||
@@ -1842,6 +1816,54 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
{
|
{
|
||||||
keep_going = 0;
|
keep_going = 0;
|
||||||
|
|
||||||
|
////////////////////////
|
||||||
|
//- rjf: resume threads that we want to run
|
||||||
|
//
|
||||||
|
// if priority mode? => first, just resume priority thread
|
||||||
|
// if not? => resume all non-priority threads
|
||||||
|
//
|
||||||
|
if(do_threads_resume)
|
||||||
|
{
|
||||||
|
do_threads_resume = 0;
|
||||||
|
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
DMN_W32_Entity *thread = n->v;
|
||||||
|
B32 thread_is_priority = dmn_handle_match(dmn_w32_handle_from_entity(thread), ctrls->priority_thread);
|
||||||
|
if((priority_mode && !thread_is_priority) ||
|
||||||
|
(!priority_mode && did_priority_mode && thread_is_priority))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DWORD resume_result = ResumeThread(thread->handle);
|
||||||
|
DMN_W32_EntityNode *n = push_array(scratch.arena, DMN_W32_EntityNode, 1);
|
||||||
|
SLLQueuePush(first_ran_thread, last_ran_thread, n);
|
||||||
|
n->v = thread;
|
||||||
|
switch(resume_result)
|
||||||
|
{
|
||||||
|
case 0xffffffffu:
|
||||||
|
{
|
||||||
|
// TODO(rjf): error - unknown cause. need to do GetLastError, FormatMessage
|
||||||
|
}break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
DWORD desired_counter = 0;
|
||||||
|
DWORD current_counter = resume_result - 1;
|
||||||
|
if(current_counter != desired_counter)
|
||||||
|
{
|
||||||
|
// NOTE(rjf): Warning. The user has manually suspended this thread,
|
||||||
|
// so even though from Demon's perspective it thinks this thread
|
||||||
|
// should run, it will not, because the user has manually called
|
||||||
|
// SuspendThread or used CREATE_SUSPENDED or whatever.
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
if(priority_mode && thread_is_priority)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
//- rjf: choose win32 resume code
|
//- rjf: choose win32 resume code
|
||||||
//
|
//
|
||||||
@@ -1878,7 +1900,12 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}
|
}
|
||||||
if(resume_good)
|
if(resume_good)
|
||||||
{
|
{
|
||||||
evt_good = !!WaitForDebugEvent(&evt, 100);
|
DWORD wait_ms = 100;
|
||||||
|
if(priority_mode)
|
||||||
|
{
|
||||||
|
wait_ms = 30;
|
||||||
|
}
|
||||||
|
evt_good = !!WaitForDebugEvent(&evt, wait_ms);
|
||||||
if(evt_good)
|
if(evt_good)
|
||||||
{
|
{
|
||||||
dmn_w32_shared->resume_needed = 1;
|
dmn_w32_shared->resume_needed = 1;
|
||||||
@@ -1891,6 +1918,11 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
(void)err;
|
(void)err;
|
||||||
keep_going = 1;
|
keep_going = 1;
|
||||||
}
|
}
|
||||||
|
if(priority_mode)
|
||||||
|
{
|
||||||
|
priority_mode = 0;
|
||||||
|
do_threads_resume = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2664,7 +2696,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
//
|
//
|
||||||
ProfScope("suspend threads which ran")
|
ProfScope("suspend threads which ran")
|
||||||
{
|
{
|
||||||
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
|
for(DMN_W32_EntityNode *n = first_ran_thread; n != 0; n = n->next)
|
||||||
{
|
{
|
||||||
DMN_W32_Entity *thread = n->v;
|
DMN_W32_Entity *thread = n->v;
|
||||||
if(thread->kind != DMN_W32_EntityKind_Thread)
|
if(thread->kind != DMN_W32_EntityKind_Thread)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
//
|
//
|
||||||
//- urgent fixes
|
//- urgent fixes
|
||||||
// [ ] hardware breakpoints regression (global eval in ctrl)
|
// [ ] hardware breakpoints regression (global eval in ctrl)
|
||||||
// [ ] []string being sized by [0], due to `.` applying to first ^string
|
|
||||||
//
|
//
|
||||||
//- memory view
|
//- memory view
|
||||||
// [ ] have smaller visible range than entire memory
|
// [ ] have smaller visible range than entire memory
|
||||||
@@ -21,9 +20,6 @@
|
|||||||
// [ ] disassembly sometimes has a problem where source line annotations are
|
// [ ] disassembly sometimes has a problem where source line annotations are
|
||||||
// periodically removed/inserted... maybe updating on fs change when we
|
// periodically removed/inserted... maybe updating on fs change when we
|
||||||
// shouldn't, non-deterministic line annotation path?
|
// shouldn't, non-deterministic line annotation path?
|
||||||
// [ ] process memory cache sometimes is not correctly updating - best repro
|
|
||||||
// case so far is (for some reason?) only hover evaluation - only spotted
|
|
||||||
// on laptop in debug builds. g0 ctrl_bindings.bindings initialization.
|
|
||||||
//
|
//
|
||||||
//- watch improvements
|
//- watch improvements
|
||||||
// [ ] *ALL* expressions in watch windows need to be editable.
|
// [ ] *ALL* expressions in watch windows need to be editable.
|
||||||
@@ -115,7 +111,6 @@
|
|||||||
//- eval improvements
|
//- eval improvements
|
||||||
// [ ] maybe add extra caching layer to process memory querying? we pay a pretty
|
// [ ] maybe add extra caching layer to process memory querying? we pay a pretty
|
||||||
// heavy cost even to just read 8 bytes...
|
// heavy cost even to just read 8 bytes...
|
||||||
// [ ] evaluate `foo.bar` symbol names without escape hatch?
|
|
||||||
// [ ] serializing eval view maps (?)
|
// [ ] serializing eval view maps (?)
|
||||||
// [ ] EVAL LOOKUP RULES -> currently going 0 -> rdis_count, but we need
|
// [ ] EVAL LOOKUP RULES -> currently going 0 -> rdis_count, but we need
|
||||||
// to prioritize the primary rdi
|
// to prioritize the primary rdi
|
||||||
@@ -149,7 +144,6 @@
|
|||||||
// [ ] investigate wide-conversion performance
|
// [ ] investigate wide-conversion performance
|
||||||
// [ ] oversubscribing cores?
|
// [ ] oversubscribing cores?
|
||||||
// [ ] conversion crashes?
|
// [ ] conversion crashes?
|
||||||
// [ ] fastpath lookup to determine debug info relevance?
|
|
||||||
// [ ] live++ investigations - ctrl+alt+f11 in UE?
|
// [ ] live++ investigations - ctrl+alt+f11 in UE?
|
||||||
//
|
//
|
||||||
//- memory usage improvements
|
//- memory usage improvements
|
||||||
@@ -189,6 +183,12 @@
|
|||||||
// is not correctly incremented.
|
// is not correctly incremented.
|
||||||
// [x] output: add option for scroll-to-bottom - ensure this shows up in universal ctx menu
|
// [x] output: add option for scroll-to-bottom - ensure this shows up in universal ctx menu
|
||||||
// [x] auto-annotations for non-locals
|
// [x] auto-annotations for non-locals
|
||||||
|
// [x] []string being sized by [0], due to `.` applying to first ^string
|
||||||
|
// [x] process memory cache sometimes is not correctly updating - best repro
|
||||||
|
// case so far is (for some reason?) only hover evaluation - only spotted
|
||||||
|
// on laptop in debug builds. g0 ctrl_bindings.bindings initialization.
|
||||||
|
// [x] evaluate `foo.bar` symbol names without escape hatch?
|
||||||
|
// [x] fastpath lookup to determine debug info relevance?
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Build Options
|
//~ rjf: Build Options
|
||||||
|
|||||||
Reference in New Issue
Block a user