mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
float run/mem/reg generations out of demon, into core; fix issue of demon access synchronization w/ mem gens, causing failure-to-update-stale-parts-of-process-memory-cache
This commit is contained in:
+69
-10
@@ -1684,7 +1684,7 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32
|
||||
{
|
||||
id_exists = 1;
|
||||
id_stale = (n->mem_gen < mem_gen);
|
||||
id_working = (ins_atomic_u64_eval(&n->working_count) != 0);
|
||||
id_working = (n->working_count != 0);
|
||||
goto end_fast_lookup;
|
||||
}
|
||||
}
|
||||
@@ -1718,7 +1718,6 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32
|
||||
if(!id_exists || (id_exists && id_stale && !id_working))
|
||||
{
|
||||
B32 node_needs_stream = 0;
|
||||
U64 *node_working_count = 0;
|
||||
OS_MutexScopeW(process_stripe->rw_mutex)
|
||||
{
|
||||
for(CTRL_ProcessMemoryCacheNode *process_n = process_slot->first; process_n != 0; process_n = process_n->next)
|
||||
@@ -1751,9 +1750,8 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32
|
||||
}
|
||||
if(node_needs_stream)
|
||||
{
|
||||
ins_atomic_u64_inc_eval(&range_n->working_count);
|
||||
range_n->working_count += 1;
|
||||
}
|
||||
node_working_count = &range_n->working_count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1762,9 +1760,33 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32
|
||||
{
|
||||
if(ctrl_u2ms_enqueue_req(key, process, vaddr_range, zero_terminated, endt_us))
|
||||
{
|
||||
// NOTE(rjf): debugging
|
||||
#if 0
|
||||
raddbg_log("[0x%I64x, 0x%I64x) push: (gen: %I64u)\n", vaddr_range.min, vaddr_range.max, mem_gen);
|
||||
#endif
|
||||
async_push_work(ctrl_mem_stream_work);
|
||||
requested = 1;
|
||||
}
|
||||
else OS_MutexScopeW(process_stripe->rw_mutex)
|
||||
{
|
||||
for(CTRL_ProcessMemoryCacheNode *process_n = process_slot->first; process_n != 0; process_n = process_n->next)
|
||||
{
|
||||
if(ctrl_handle_match(process_n->handle, process))
|
||||
{
|
||||
U64 range_slot_idx = range_hash%process_n->range_hash_slots_count;
|
||||
CTRL_ProcessMemoryRangeHashSlot *range_slot = &process_n->range_hash_slots[range_slot_idx];
|
||||
CTRL_ProcessMemoryRangeHashNode *range_n = 0;
|
||||
for(CTRL_ProcessMemoryRangeHashNode *n = range_slot->first; n != 0; n = n->next)
|
||||
{
|
||||
if(hs_id_match(n->id, id))
|
||||
{
|
||||
n->working_count -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1960,6 +1982,12 @@ ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src)
|
||||
ProfBeginFunction();
|
||||
B32 result = dmn_process_write(process.dmn_handle, range, src);
|
||||
|
||||
//- rjf: success -> bump generation
|
||||
if(result)
|
||||
{
|
||||
ins_atomic_u64_inc_eval(&ctrl_state->mem_gen);
|
||||
}
|
||||
|
||||
//- rjf: success -> wait for cache updates, for small regions - prefer relatively seamless
|
||||
// writes within calling frame's "view" of the memory, at the expense of a small amount of
|
||||
// time.
|
||||
@@ -2066,7 +2094,7 @@ ctrl_reg_block_from_thread(Arena *arena, CTRL_EntityCtx *ctx, CTRL_Handle handle
|
||||
// rjf: copy from node
|
||||
if(node)
|
||||
{
|
||||
U64 current_reg_gen = dmn_reg_gen();
|
||||
U64 current_reg_gen = ctrl_reg_gen();
|
||||
B32 need_stale = 1;
|
||||
if(node->reg_gen != current_reg_gen && dmn_thread_read_reg_block(handle.dmn_handle, result))
|
||||
{
|
||||
@@ -2124,6 +2152,10 @@ ctrl_thread_write_reg_block(CTRL_Handle thread, void *block)
|
||||
{
|
||||
// TODO(rjf): @callstacks immediately reflect this in the call stack cache
|
||||
B32 good = dmn_thread_write_reg_block(thread.dmn_handle, block);
|
||||
if(good)
|
||||
{
|
||||
ins_atomic_u64_inc_eval(&ctrl_state->reg_gen);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
@@ -3492,26 +3524,26 @@ ctrl_halt(void)
|
||||
////////////////////////////////
|
||||
//~ rjf: Shared Accessor Functions
|
||||
|
||||
//- rjf: run generation counter
|
||||
//- rjf: generation counters
|
||||
|
||||
internal U64
|
||||
ctrl_run_gen(void)
|
||||
{
|
||||
U64 result = dmn_run_gen();
|
||||
U64 result = ins_atomic_u64_eval(&ctrl_state->run_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
ctrl_mem_gen(void)
|
||||
{
|
||||
U64 result = dmn_mem_gen();
|
||||
U64 result = ins_atomic_u64_eval(&ctrl_state->mem_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
ctrl_reg_gen(void)
|
||||
{
|
||||
U64 result = dmn_reg_gen();
|
||||
U64 result = ins_atomic_u64_eval(&ctrl_state->reg_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -3831,6 +3863,9 @@ ctrl_thread__entry_point(void *p)
|
||||
}
|
||||
ins_atomic_u64_eval_assign(&ctrl_state->ctrl_thread_run_state, 0);
|
||||
}
|
||||
ins_atomic_u64_inc_eval(&ctrl_state->run_gen);
|
||||
ins_atomic_u64_inc_eval(&ctrl_state->mem_gen);
|
||||
ins_atomic_u64_inc_eval(&ctrl_state->reg_gen);
|
||||
|
||||
//- rjf: gather & output logs
|
||||
LogScopeResult log = log_scope_end(scratch.arena);
|
||||
@@ -6777,6 +6812,7 @@ ctrl_u2ms_dequeue_req(HS_Key *out_key, CTRL_Handle *out_process, Rng1U64 *out_va
|
||||
|
||||
ASYNC_WORK_DEF(ctrl_mem_stream_work)
|
||||
{
|
||||
#define CTRL_MEM_STREAM_WORK_DEBUG 0
|
||||
ProfBeginFunction();
|
||||
CTRL_ProcessMemoryCache *cache = &ctrl_state->process_memory_cache;
|
||||
|
||||
@@ -6812,6 +6848,12 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work)
|
||||
void *range_base = 0;
|
||||
U64 zero_terminated_size = 0;
|
||||
U64 pre_read_mem_gen = ctrl_mem_gen();
|
||||
B32 pre_run_state = ins_atomic_u64_eval(&ctrl_state->ctrl_thread_run_state);
|
||||
#if CTRL_MEM_STREAM_WORK_DEBUG
|
||||
Log *log = log_alloc();
|
||||
log_select(log);
|
||||
log_scope_begin();
|
||||
#endif
|
||||
{
|
||||
range_size = dim_1u64(vaddr_range_clamped);
|
||||
U64 page_size = os_get_system_info()->page_size;
|
||||
@@ -6873,6 +6915,23 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work)
|
||||
}
|
||||
}
|
||||
U64 post_read_mem_gen = ctrl_mem_gen();
|
||||
B32 post_run_state = ins_atomic_u64_eval(&ctrl_state->ctrl_thread_run_state);
|
||||
// NOTE(rjf): debugging
|
||||
#if CTRL_MEM_STREAM_WORK_DEBUG
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8 sample_data_str = str8_lit("no data");
|
||||
if(range_base != 0)
|
||||
{
|
||||
String8 sample_data = str8((U8*)range_base + 0x100, 16);
|
||||
String8List sample_data_strs = numeric_str8_list_from_data(scratch.arena, 16, sample_data, 1);
|
||||
sample_data_str = str8_list_join(scratch.arena, &sample_data_strs, &(StringJoin){.sep = str8_lit(", ")});
|
||||
}
|
||||
LogScopeResult log = log_scope_end(scratch.arena);
|
||||
raddbg_log("[0x%I64x, 0x%I64x) { pre_gen: %I64u, post_gen: %I64u, pre_run: %i, post_run: %i, bytes: [%S], info:```%S``` }\n", vaddr_range.min, vaddr_range.max, pre_read_mem_gen, post_read_mem_gen, pre_run_state, post_run_state, sample_data_str, log.strings[LogMsgKind_Info]);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
#endif
|
||||
|
||||
//- rjf: read successful -> submit to hash store
|
||||
U128 hash = {0};
|
||||
@@ -6902,7 +6961,7 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work)
|
||||
{
|
||||
range_n->mem_gen = post_read_mem_gen;
|
||||
}
|
||||
ins_atomic_u64_dec_eval(&range_n->working_count);
|
||||
range_n->working_count -= 1;
|
||||
goto commit__break_all;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -792,6 +792,11 @@ struct CTRL_State
|
||||
CTRL_CallStackCache call_stack_cache;
|
||||
CTRL_ModuleImageInfoCache module_image_info_cache;
|
||||
|
||||
// rjf: generations
|
||||
U64 run_gen;
|
||||
U64 mem_gen;
|
||||
U64 reg_gen;
|
||||
|
||||
// rjf: user -> ctrl msg ring buffer
|
||||
U64 u2c_ring_size;
|
||||
U8 *u2c_ring_base;
|
||||
|
||||
@@ -221,11 +221,6 @@ internal void dmn_halt(U64 code, U64 user_data);
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS)
|
||||
|
||||
//- rjf: run/memory/register counters
|
||||
internal U64 dmn_run_gen(void);
|
||||
internal U64 dmn_mem_gen(void);
|
||||
internal U64 dmn_reg_gen(void);
|
||||
|
||||
//- rjf: non-blocking-control-thread access barriers
|
||||
internal B32 dmn_access_open(void);
|
||||
internal void dmn_access_close(void);
|
||||
|
||||
@@ -71,26 +71,6 @@ dmn_halt(U64 code, U64 user_data)
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS)
|
||||
|
||||
//- rjf: run/memory/register counters
|
||||
|
||||
internal U64
|
||||
dmn_run_gen(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
dmn_mem_gen(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
dmn_reg_gen(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//- rjf: non-blocking-control-thread access barriers
|
||||
|
||||
internal B32
|
||||
|
||||
@@ -320,7 +320,10 @@ dmn_w32_process_read(HANDLE process, Rng1U64 range, void *dst)
|
||||
SIZE_T actual_read = 0;
|
||||
if(!ReadProcessMemory(process, (LPCVOID)cursor, ptr, to_read, &actual_read))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
log_infof("'Win32 ReadProcessMemory failure': { [0x%I64x, 0x%I64x), code: %i }\n", range.min, range.max, error);
|
||||
bytes_read += actual_read;
|
||||
(void)error;
|
||||
break;
|
||||
}
|
||||
ptr += actual_read;
|
||||
@@ -349,7 +352,6 @@ dmn_w32_process_write(HANDLE process, Rng1U64 range, void *src)
|
||||
ptr += actual_write;
|
||||
cursor += actual_write;
|
||||
}
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->mem_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1112,7 +1114,6 @@ dmn_w32_thread_write_reg_block(Arch arch, HANDLE thread, void *reg_block)
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
}
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
|
||||
ProfEnd();
|
||||
return result;
|
||||
}
|
||||
@@ -1541,7 +1542,6 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
U64 new_rflags = rflags | 0x100;
|
||||
single_step_thread_ctx->EFlags = new_rflags;
|
||||
SetThreadContext(thread->handle, single_step_thread_ctx);
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
@@ -1891,9 +1891,6 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
(void)err;
|
||||
keep_going = 1;
|
||||
}
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->run_gen);
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->mem_gen);
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2327,7 +2324,6 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
U64 new_rip = instruction_pointer;
|
||||
ctx->Rip = new_rip;
|
||||
SetThreadContext(thread->handle, ctx);
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
@@ -2841,7 +2837,6 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
U64 new_rflags = rflags & ~0x100;
|
||||
single_step_thread_ctx->EFlags = new_rflags;
|
||||
SetThreadContext(thread->handle, single_step_thread_ctx);
|
||||
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
@@ -2938,29 +2933,6 @@ dmn_halt(U64 code, U64 user_data)
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS)
|
||||
|
||||
//- rjf: run/memory/register counters
|
||||
|
||||
internal U64
|
||||
dmn_run_gen(void)
|
||||
{
|
||||
U64 result = ins_atomic_u64_eval(&dmn_w32_shared->run_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
dmn_mem_gen(void)
|
||||
{
|
||||
U64 result = ins_atomic_u64_eval(&dmn_w32_shared->mem_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
dmn_reg_gen(void)
|
||||
{
|
||||
U64 result = ins_atomic_u64_eval(&dmn_w32_shared->reg_gen);
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: non-blocking-control-thread access barriers
|
||||
|
||||
internal B32
|
||||
|
||||
@@ -200,11 +200,6 @@ struct DMN_W32_Shared
|
||||
OS_Handle access_mutex;
|
||||
B32 access_run_state;
|
||||
|
||||
// rjf: run/mem/reg gens
|
||||
U64 run_gen;
|
||||
U64 mem_gen;
|
||||
U64 reg_gen;
|
||||
|
||||
// rjf: detaching info
|
||||
Arena *detach_arena;
|
||||
DMN_HandleList detach_processes;
|
||||
|
||||
@@ -17193,10 +17193,13 @@ rd_frame(void)
|
||||
os_append_data_to_file_path(rd_state->log_path, log.strings[LogMsgKind_Info]);
|
||||
if(log.strings[LogMsgKind_UserError].size != 0)
|
||||
{
|
||||
String8 error_log = log.strings[LogMsgKind_UserError];
|
||||
String8List error_log_lines = str8_split(scratch.arena, error_log, (U8 *)"\n", 1, 0);
|
||||
String8 error_log_string = str8_list_join(scratch.arena, &error_log_lines, &(StringJoin){.sep = str8_lit(" ")});
|
||||
for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next)
|
||||
{
|
||||
ws->error_string_size = Min(sizeof(ws->error_buffer), log.strings[LogMsgKind_UserError].size);
|
||||
MemoryCopy(ws->error_buffer, log.strings[LogMsgKind_UserError].str, ws->error_string_size);
|
||||
ws->error_string_size = Min(sizeof(ws->error_buffer), error_log_string.size);
|
||||
MemoryCopy(ws->error_buffer, error_log_string.str, ws->error_string_size);
|
||||
ws->error_t = 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
// [ ] hardware breakpoints regression
|
||||
// [ ] process memory waiting regression
|
||||
// [ ] "evict module image info from cache" crash, on module close sometimes
|
||||
// - reproduction steps:
|
||||
// - raddbg debugging raddbg
|
||||
// - [parent] breakpoint on memory read failure case
|
||||
// - [child] breakpoint on ctrl_bindings init in g0
|
||||
// - f5x3
|
||||
//
|
||||
//- memory view
|
||||
// [ ] have smaller visible range than entire memory
|
||||
|
||||
Reference in New Issue
Block a user