diff --git a/src/async/async.c b/src/async/async.c index 01a24100..2cf0f666 100644 --- a/src/async/async.c +++ b/src/async/async.c @@ -61,6 +61,7 @@ async_push_work_(ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params work.output = params->output; work.semaphore = params->semaphore; work.completion_counter = params->completion_counter; + work.working_counter = params->working_counter; // rjf: loop; try to write into user -> writer ring buffer. if we're on a // worker thread, determine if we need to execute this task locally on this @@ -227,6 +228,12 @@ async_execute_work(ASYNC_Work work) { ins_atomic_u64_inc_eval(work.completion_counter); } + + //- rjf: decrement working counter + if(work.working_counter != 0) + { + ins_atomic_u64_dec_eval(work.working_counter); + } } //////////////////////////////// diff --git a/src/async/async.h b/src/async/async.h index f793f3d1..6d9f2b00 100644 --- a/src/async/async.h +++ b/src/async/async.h @@ -29,6 +29,7 @@ struct ASYNC_WorkParams void **output; OS_Handle semaphore; U64 *completion_counter; + U64 *working_counter; U64 endt_us; ASYNC_Priority priority; }; @@ -41,6 +42,7 @@ struct ASYNC_Work void **output; OS_Handle semaphore; U64 *completion_counter; + U64 *working_counter; }; //////////////////////////////// diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 8e92c34e..a12d31a1 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -1577,8 +1577,188 @@ ctrl_set_wakeup_hook(CTRL_WakeupFunctionType *wakeup_hook) //////////////////////////////// //~ rjf: Process Memory Functions +//- rjf: process memory cache key reading + +internal HS_Key +ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us, B32 *out_is_stale) +{ + CTRL_ProcessMemoryCache *cache = &ctrl_state->process_memory_cache; + + //- rjf: unpack process key + U64 process_hash = ctrl_hash_from_handle(process); + U64 process_slot_idx = process_hash%cache->slots_count; + U64 process_stripe_idx = process_slot_idx%cache->stripes_count; + CTRL_ProcessMemoryCacheSlot *process_slot = &cache->slots[process_slot_idx]; + CTRL_ProcessMemoryCacheStripe *process_stripe = &cache->stripes[process_stripe_idx]; + + //- rjf: get the hash store root for this process; construct process node if it + // doesn't exist + HS_Root root = {0}; + { + B32 node_found = 0; + OS_MutexScopeR(process_stripe->rw_mutex) + { + for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next) + { + if(ctrl_handle_match(n->handle, process)) + { + node_found = 1; + root = n->root; + break; + } + } + } + if(!node_found) OS_MutexScopeW(process_stripe->rw_mutex) + { + for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next) + { + if(ctrl_handle_match(n->handle, process)) + { + node_found = 1; + root = n->root; + break; + } + } + if(!node_found) + { + Arena *node_arena = arena_alloc(); + CTRL_ProcessMemoryCacheNode *node = push_array(node_arena, CTRL_ProcessMemoryCacheNode, 1); + DLLPushBack(process_slot->first, process_slot->last, node); + node->arena = node_arena; + node->handle = process; + node->root = hs_root_alloc(); + node->range_hash_slots_count = 1024; + node->range_hash_slots = push_array(node_arena, CTRL_ProcessMemoryRangeHashSlot, node->range_hash_slots_count); + root = node->root; + } + } + } + + //- rjf: form ID for this process memory query + HS_ID id = {0}; + { + id.u128[0].u64[0] = vaddr_range.min & 0x00ffffffffffffffull; + id.u128[0].u64[1] = vaddr_range.max & 0x00ffffffffffffffull; + if(zero_terminated) + { + id.u128[0].u64[0] |= (1ull << 63); + } + } + U64 range_hash = hs_little_hash_from_data(str8_struct(&id)); + + //- rjf: form full key + HS_Key key = hs_key_make(root, id); + + //- rjf: loop: try to look for current results, request if not there, wait if we can, repeat until we can't + U64 mem_gen = ctrl_mem_gen(); + B32 key_is_stale = 0; + for(;;) + { + //- rjf: step 1: [read-only] try to look for current results for key's ID + B32 id_exists = 0; + B32 id_stale = 0; + OS_MutexScopeR(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]; + for(CTRL_ProcessMemoryRangeHashNode *n = range_slot->first; n != 0; n = n->next) + { + if(hs_id_match(n->id, id)) + { + id_exists = 1; + id_stale = (n->mem_gen < mem_gen); + goto end_fast_lookup; + } + } + } + } + end_fast_lookup:; + } + key_is_stale = id_stale; + + //- rjf: step 2: if the ID exists and is not stale, then we're done; + // the hash store contains the most up-to-date representation of the + // process memory for this key. + if(id_exists && !id_stale) + { + break; + } + + //- rjf: step 3: if the ID does not exist in the process' cache, then we + // need to build a node for it. if that, or if the ID is stale, then also + // request that that range is streamed. + if(!id_exists || (id_exists && id_stale)) + { + 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) + { + 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)) + { + range_n = n; + break; + } + } + if(range_n == 0) + { + range_n = push_array(process_n->arena, CTRL_ProcessMemoryRangeHashNode, 1); + SLLQueuePush(range_slot->first, range_slot->last, range_n); + range_n->vaddr_range = vaddr_range; + range_n->zero_terminated = zero_terminated; + range_n->id = id; + range_n->working_count += 1; + node_needs_stream = 1; + } + else + { + node_needs_stream = (range_n->mem_gen < mem_gen); + } + node_working_count = &range_n->working_count; + break; + } + } + } + if(node_needs_stream) + { + ctrl_u2ms_enqueue_req(key, process, vaddr_range, zero_terminated, max_U64); + async_push_work(ctrl_mem_stream_work, .working_counter = node_working_count); + } + } + + //- rjf: step 4: if we have no time to wait, then abort; otherwise, + // wait on this process' stripe + if(os_now_microseconds() >= endt_us) + { + break; + } + else OS_MutexScopeR(process_stripe->rw_mutex) + { + os_condition_variable_wait_rw_r(process_stripe->cv, process_stripe->rw_mutex, endt_us); + } + } + if(out_is_stale) + { + *out_is_stale = key_is_stale; + } + return key; +} + //- rjf: process memory cache interaction +#if 0 // TODO(rjf): @hs internal U128 ctrl_calc_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated) { @@ -1758,9 +1938,11 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B3 ProfEnd(); return result; } +#endif //- rjf: bundled key/stream helper +#if 0 // TODO(rjf): @hs internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated) { @@ -1768,6 +1950,7 @@ ctrl_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, ctrl_stored_hash_from_process_vaddr_range(process, range, zero_terminated, 0, 0); return key; } +#endif //- rjf: process memory cache reading helpers @@ -1798,9 +1981,9 @@ ctrl_process_memory_slice_from_vaddr_range(Arena *arena, CTRL_Handle process, Rn for(U64 page_idx = 0; page_idx < page_count; page_idx += 1) { U64 page_base_vaddr = page_range.min + page_idx*page_size; - U128 page_key = ctrl_calc_hash_store_key_from_process_vaddr_range(process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0); B32 page_is_stale = 0; - U128 page_hash = ctrl_stored_hash_from_process_vaddr_range(process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0, &page_is_stale, endt_us); + HS_Key page_key = ctrl_key_from_process_vaddr_range(process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0, endt_us, &page_is_stale); + U128 page_hash = hs_hash_from_key(page_key, 0); U128 page_last_hash = hs_hash_from_key(page_key, 1); result.stale = (result.stale || page_is_stale); page_hashes[page_idx] = page_hash; @@ -6542,16 +6725,17 @@ ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) //- rjf: user -> memory stream communication internal B32 -ctrl_u2ms_enqueue_req(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us) +ctrl_u2ms_enqueue_req(HS_Key key, CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us) { B32 good = 0; OS_MutexScope(ctrl_state->u2ms_ring_mutex) for(;;) { U64 unconsumed_size = ctrl_state->u2ms_ring_write_pos-ctrl_state->u2ms_ring_read_pos; U64 available_size = ctrl_state->u2ms_ring_size-unconsumed_size; - if(available_size >= sizeof(process)+sizeof(vaddr_range)+sizeof(zero_terminated)) + if(available_size >= sizeof(key)+sizeof(process)+sizeof(vaddr_range)+sizeof(zero_terminated)) { good = 1; + ctrl_state->u2ms_ring_write_pos += ring_write_struct(ctrl_state->u2ms_ring_base, ctrl_state->u2ms_ring_size, ctrl_state->u2ms_ring_write_pos, &key); ctrl_state->u2ms_ring_write_pos += ring_write_struct(ctrl_state->u2ms_ring_base, ctrl_state->u2ms_ring_size, ctrl_state->u2ms_ring_write_pos, &process); ctrl_state->u2ms_ring_write_pos += ring_write_struct(ctrl_state->u2ms_ring_base, ctrl_state->u2ms_ring_size, ctrl_state->u2ms_ring_write_pos, &vaddr_range); ctrl_state->u2ms_ring_write_pos += ring_write_struct(ctrl_state->u2ms_ring_base, ctrl_state->u2ms_ring_size, ctrl_state->u2ms_ring_write_pos, &zero_terminated); @@ -6565,13 +6749,14 @@ ctrl_u2ms_enqueue_req(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_termina } internal void -ctrl_u2ms_dequeue_req(CTRL_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated) +ctrl_u2ms_dequeue_req(HS_Key *out_key, CTRL_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated) { OS_MutexScope(ctrl_state->u2ms_ring_mutex) for(;;) { U64 unconsumed_size = ctrl_state->u2ms_ring_write_pos-ctrl_state->u2ms_ring_read_pos; - if(unconsumed_size >= sizeof(*out_process)+sizeof(*out_vaddr_range)+sizeof(*out_zero_terminated)) + if(unconsumed_size >= sizeof(*out_key)+sizeof(*out_process)+sizeof(*out_vaddr_range)+sizeof(*out_zero_terminated)) { + ctrl_state->u2ms_ring_read_pos += ring_read_struct(ctrl_state->u2ms_ring_base, ctrl_state->u2ms_ring_size, ctrl_state->u2ms_ring_read_pos, out_key); ctrl_state->u2ms_ring_read_pos += ring_read_struct(ctrl_state->u2ms_ring_base, ctrl_state->u2ms_ring_size, ctrl_state->u2ms_ring_read_pos, out_process); ctrl_state->u2ms_ring_read_pos += ring_read_struct(ctrl_state->u2ms_ring_base, ctrl_state->u2ms_ring_size, ctrl_state->u2ms_ring_read_pos, out_vaddr_range); ctrl_state->u2ms_ring_read_pos += ring_read_struct(ctrl_state->u2ms_ring_base, ctrl_state->u2ms_ring_size, ctrl_state->u2ms_ring_read_pos, out_zero_terminated); @@ -6590,50 +6775,29 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work) CTRL_ProcessMemoryCache *cache = &ctrl_state->process_memory_cache; //- rjf: unpack next request + HS_Key key = {0}; CTRL_Handle process = {0}; Rng1U64 vaddr_range = {0}; B32 zero_terminated = 0; - ctrl_u2ms_dequeue_req(&process, &vaddr_range, &zero_terminated); - U128 key = ctrl_calc_hash_store_key_from_process_vaddr_range(process, vaddr_range, zero_terminated); + ctrl_u2ms_dequeue_req(&key, &process, &vaddr_range, &zero_terminated); ProfBegin("memory stream request"); - //- rjf: unpack process memory cache key - U64 process_hash = ctrl_hash_from_string(str8_struct(&process)); + //- rjf: unpack process key + U64 process_hash = ctrl_hash_from_handle(process); U64 process_slot_idx = process_hash%cache->slots_count; U64 process_stripe_idx = process_slot_idx%cache->stripes_count; CTRL_ProcessMemoryCacheSlot *process_slot = &cache->slots[process_slot_idx]; CTRL_ProcessMemoryCacheStripe *process_stripe = &cache->stripes[process_stripe_idx]; //- rjf: unpack address range hash cache key - U64 range_hash = ctrl_hash_from_string(str8_struct(&vaddr_range)); + U64 range_hash = hs_little_hash_from_data(str8_struct(&key.id)); - //- rjf: take task - B32 got_task = 0; - U64 preexisting_mem_gen = 0; - U128 preexisting_hash = {0}; - Rng1U64 vaddr_range_clamped = {0}; - OS_MutexScopeW(process_stripe->rw_mutex) + //- rjf: clamp vaddr range + Rng1U64 vaddr_range_clamped = vaddr_range; { - for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next) - { - if(ctrl_handle_match(n->handle, process)) - { - U64 range_slot_idx = range_hash%n->range_hash_slots_count; - CTRL_ProcessMemoryRangeHashSlot *range_slot = &n->range_hash_slots[range_slot_idx]; - for(CTRL_ProcessMemoryRangeHashNode *range_n = range_slot->first; range_n != 0; range_n = range_n->next) - { - if(MemoryMatchStruct(&range_n->vaddr_range, &vaddr_range) && range_n->zero_terminated == zero_terminated) - { - got_task = !ins_atomic_u32_eval_cond_assign(&range_n->is_taken, 1, 0); - preexisting_mem_gen = range_n->mem_gen; - preexisting_hash = range_n->hash; - vaddr_range_clamped = range_n->vaddr_range_clamped; - goto take_task__break_all; - } - } - } - } - take_task__break_all:; + vaddr_range_clamped.max = Max(vaddr_range_clamped.max, vaddr_range_clamped.min); + U64 max_size_cap = Min(max_U64-vaddr_range_clamped.min, GB(1)); + vaddr_range_clamped.max = Min(vaddr_range_clamped.max, vaddr_range_clamped.min+max_size_cap); } //- rjf: task was taken -> read memory @@ -6641,9 +6805,8 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work) Arena *range_arena = 0; void *range_base = 0; U64 zero_terminated_size = 0; - U64 pre_read_mem_gen = dmn_mem_gen(); + U64 pre_read_mem_gen = ctrl_mem_gen(); U64 post_read_mem_gen = 0; - if(got_task && pre_read_mem_gen != preexisting_mem_gen) { range_size = dim_1u64(vaddr_range_clamped); U64 page_size = os_get_system_info()->page_size; @@ -6708,7 +6871,7 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work) //- rjf: read successful -> submit to hash store U128 hash = {0}; - if(got_task && range_base != 0 && pre_read_mem_gen == post_read_mem_gen) + if(range_base != 0 && pre_read_mem_gen == post_read_mem_gen) { hash = hs_submit_data(key, &range_arena, str8((U8*)range_base, zero_terminated_size)); } @@ -6717,8 +6880,8 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work) arena_release(range_arena); } - //- rjf: commit hash to cache - if(got_task) OS_MutexScopeW(process_stripe->rw_mutex) + //- rjf: commit new info to cache + OS_MutexScopeW(process_stripe->rw_mutex) { for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next) { @@ -6728,14 +6891,12 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work) CTRL_ProcessMemoryRangeHashSlot *range_slot = &n->range_hash_slots[range_slot_idx]; for(CTRL_ProcessMemoryRangeHashNode *range_n = range_slot->first; range_n != 0; range_n = range_n->next) { - if(MemoryMatchStruct(&range_n->vaddr_range, &vaddr_range) && range_n->zero_terminated == zero_terminated) + if(hs_id_match(range_n->id, key.id)) { if(!u128_match(u128_zero(), hash)) { - range_n->hash = hash; range_n->mem_gen = post_read_mem_gen; } - ins_atomic_u32_eval_assign(&range_n->is_taken, 0); goto commit__break_all; } } diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 3b2e1405..337555bd 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -505,13 +505,19 @@ typedef struct CTRL_ProcessMemoryRangeHashNode CTRL_ProcessMemoryRangeHashNode; struct CTRL_ProcessMemoryRangeHashNode { CTRL_ProcessMemoryRangeHashNode *next; + + // rjf: key Rng1U64 vaddr_range; B32 zero_terminated; - Rng1U64 vaddr_range_clamped; - U128 hash; + HS_ID id; + + // rjf: staleness info U64 mem_gen; + + // rjf: metadata + U64 working_count; U64 last_time_requested_us; - B32 is_taken; + U64 last_user_clock_idx_touched; }; typedef struct CTRL_ProcessMemoryRangeHashSlot CTRL_ProcessMemoryRangeHashSlot; @@ -528,6 +534,7 @@ struct CTRL_ProcessMemoryCacheNode CTRL_ProcessMemoryCacheNode *prev; Arena *arena; CTRL_Handle handle; + HS_Root root; U64 range_hash_slots_count; CTRL_ProcessMemoryRangeHashSlot *range_hash_slots; }; @@ -983,12 +990,19 @@ internal void ctrl_set_wakeup_hook(CTRL_WakeupFunctionType *wakeup_hook); //////////////////////////////// //~ rjf: Process Memory Functions +//- rjf: process memory cache key reading +internal HS_Key ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us, B32 *out_is_stale); + //- rjf: process memory cache interaction +#if 0 // TODO(rjf): @hs internal U128 ctrl_calc_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated); internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated, B32 *out_is_stale, U64 endt_us); +#endif //- rjf: bundled key/stream helper +#if 0 // TODO(rjf): @hs internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated); +#endif //- rjf: process memory cache reading helpers internal CTRL_ProcessMemorySlice ctrl_process_memory_slice_from_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, U64 endt_us); @@ -1114,8 +1128,8 @@ internal void ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); //~ rjf: Asynchronous Memory Streaming Functions //- rjf: user -> memory stream communication -internal B32 ctrl_u2ms_enqueue_req(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us); -internal void ctrl_u2ms_dequeue_req(CTRL_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated); +internal B32 ctrl_u2ms_enqueue_req(HS_Key key, CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us); +internal void ctrl_u2ms_dequeue_req(HS_Key *out_key, CTRL_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated); //- rjf: entry point ASYNC_WORK_DEF(ctrl_mem_stream_work); diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index 3c937b37..26d6df9f 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -345,10 +345,13 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params) DASM_Info info = {0}; if(!u128_match(hash, u128_zero())) { + //- rjf: unpack hash U64 slot_idx = hash.u64[1]%dasm_shared->slots_count; U64 stripe_idx = slot_idx%dasm_shared->stripes_count; DASM_Slot *slot = &dasm_shared->slots[slot_idx]; DASM_Stripe *stripe = &dasm_shared->stripes[stripe_idx]; + + //- rjf: try to get existing results B32 found = 0; OS_MutexScopeR(stripe->rw_mutex) { @@ -363,9 +366,13 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params) } } } - B32 node_is_new = 0; + + //- rjf: miss -> kick off work to fill cache if(!found) { + B32 node_is_new = 0; + U64 *node_working_count = 0; + HS_Root root = {0}; OS_MutexScopeW(stripe->rw_mutex) { DASM_Node *node = 0; @@ -379,16 +386,7 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params) } if(node == 0) { - LogInfoNamedBlockF("dasm_new_node") - { - log_infof("hash: [0x%I64x 0x%I64x]\n", hash.u64[0], hash.u64[1]); - log_infof("vaddr: 0x%I64x\n", params->vaddr); - log_infof("arch: %S\n", string_from_arch(params->arch)); - log_infof("style_flags: 0x%x\n", params->style_flags); - log_infof("syntax: %i\n", params->syntax); - log_infof("base_vaddr: 0x%I64x\n", params->base_vaddr); - log_infof("dbgi_key: [%S 0x%I64x]\n", params->dbgi_key.path, params->dbgi_key.min_timestamp); - } + // rjf: allocate node node = stripe->free_node; if(node) { @@ -399,26 +397,34 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params) node = push_array_no_zero(stripe->arena, DASM_Node, 1); } MemoryZeroStruct(node); + + // rjf: fill node DLLPushBack(slot->first, slot->last, node); node->hash = hash; MemoryCopyStruct(&node->params, params); + node->root = hs_root_alloc(); // TODO(rjf): need to make this releasable - currently all exe_paths just leak node->params.dbgi_key = di_key_copy(stripe->arena, &node->params.dbgi_key); + + // rjf: gather work kickoff params node_is_new = 1; + ins_atomic_u64_inc_eval(&node->working_count); + node_working_count = &node->working_count; + root = node->root; } } - } - if(node_is_new) - { - dasm_u2p_enqueue_req(hash, params, max_U64); - async_push_work(dasm_parse_work); + if(node_is_new) + { + dasm_u2p_enqueue_req(root, hash, params, max_U64); + async_push_work(dasm_parse_work, .working_counter = node_working_count); + } } } return info; } internal DASM_Info -dasm_info_from_key_params(DASM_Scope *scope, U128 key, DASM_Params *params, U128 *hash_out) +dasm_info_from_key_params(DASM_Scope *scope, HS_Key key, DASM_Params *params, U128 *hash_out) { DASM_Info result = {0}; for(U64 rewind_idx = 0; rewind_idx < HS_KEY_HASH_HISTORY_COUNT; rewind_idx += 1) @@ -441,16 +447,17 @@ dasm_info_from_key_params(DASM_Scope *scope, U128 key, DASM_Params *params, U128 //~ rjf: Parse Threads internal B32 -dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us) +dasm_u2p_enqueue_req(HS_Root root, U128 hash, DASM_Params *params, U64 endt_us) { B32 good = 0; OS_MutexScope(dasm_shared->u2p_ring_mutex) for(;;) { U64 unconsumed_size = dasm_shared->u2p_ring_write_pos - dasm_shared->u2p_ring_read_pos; U64 available_size = dasm_shared->u2p_ring_size - unconsumed_size; - if(available_size >= sizeof(hash)+sizeof(U64)+sizeof(Arch)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+params->dbgi_key.path.size+sizeof(U64)) + if(available_size >= sizeof(root)+sizeof(hash)+sizeof(U64)+sizeof(Arch)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+params->dbgi_key.path.size+sizeof(U64)) { good = 1; + dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &root); dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &hash); dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, ¶ms->vaddr); dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, ¶ms->arch); @@ -476,13 +483,14 @@ dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us) } internal void -dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out) +dasm_u2p_dequeue_req(Arena *arena, HS_Root *root_out, U128 *hash_out, DASM_Params *params_out) { OS_MutexScope(dasm_shared->u2p_ring_mutex) for(;;) { U64 unconsumed_size = dasm_shared->u2p_ring_write_pos - dasm_shared->u2p_ring_read_pos; if(unconsumed_size >= sizeof(*hash_out)+sizeof(U64)+sizeof(Arch)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+sizeof(U64)) { + dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, root_out); dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, hash_out); dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, ¶ms_out->vaddr); dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, ¶ms_out->arch); @@ -509,9 +517,10 @@ ASYNC_WORK_DEF(dasm_parse_work) TXT_Scope *txt_scope = txt_scope_open(); //- rjf: get next request + HS_Root root = {0}; U128 hash = {0}; DASM_Params params = {0}; - dasm_u2p_dequeue_req(scratch.arena, &hash, ¶ms); + dasm_u2p_dequeue_req(scratch.arena, &root, &hash, ¶ms); U64 change_gen = fs_change_gen(); //- rjf: unpack hash @@ -520,38 +529,19 @@ ASYNC_WORK_DEF(dasm_parse_work) DASM_Slot *slot = &dasm_shared->slots[slot_idx]; DASM_Stripe *stripe = &dasm_shared->stripes[stripe_idx]; - //- rjf: take task - B32 got_task = 0; - OS_MutexScopeR(stripe->rw_mutex) - { - for(DASM_Node *n = slot->first; n != 0; n = n->next) - { - if(u128_match(n->hash, hash) && dasm_params_match(&n->params, ¶ms)) - { - got_task = !ins_atomic_u32_eval_cond_assign(&n->is_working, 1, 0); - break; - } - } - } - //- rjf: get dbg info RDI_Parsed *rdi = &rdi_parsed_nil; - if(got_task && params.dbgi_key.path.size != 0) + if(params.dbgi_key.path.size != 0) { rdi = di_rdi_from_key(di_scope, ¶ms.dbgi_key, max_U64); } //- rjf: hash -> data - String8 data = {0}; - if(got_task) - { - data = hs_data_from_hash(hs_scope, hash); - } + String8 data = hs_data_from_hash(hs_scope, hash); //- rjf: data * arch * addr * dbg -> decode artifacts DASM_LineChunkList line_list = {0}; String8List inst_strings = {0}; - if(got_task) { switch(params.arch) { @@ -621,7 +611,7 @@ ASYNC_WORK_DEF(dasm_parse_work) { // TODO(rjf): need redirection path - this may map to a different path on the local machine, // need frontend to communicate path remapping info to this layer - U128 key = fs_key_from_path_range(file_normalized_full_path, r1u64(0, max_U64)); + HS_Key key = fs_key_from_path_range(file_normalized_full_path, r1u64(0, max_U64), 0); TXT_LangKind lang_kind = txt_lang_kind_from_extension(file_normalized_full_path); U64 endt_us = max_U64; U128 hash = {0}; @@ -712,7 +702,6 @@ ASYNC_WORK_DEF(dasm_parse_work) //- rjf: artifacts -> value bundle Arena *info_arena = 0; DASM_Info info = {0}; - if(got_task) { //- rjf: produce joined text Arena *text_arena = arena_alloc(); @@ -721,21 +710,7 @@ ASYNC_WORK_DEF(dasm_parse_work) String8 text = str8_list_join(text_arena, &inst_strings, &text_join); //- rjf: produce unique key for this disassembly's text - U128 text_key = {0}; - { - U64 hash_data[] = - { - hash.u64[0], - hash.u64[1], - params.vaddr, - (U64)params.arch, - (U64)params.style_flags, - (U64)params.syntax, - (U64)rdi, - 0x4d534144, - }; - text_key = hs_hash_from_data(str8((U8 *)hash_data, sizeof(hash_data))); - } + HS_Key text_key = hs_key_make(root, hs_id_make(0, 0)); //- rjf: submit text data to hash store U128 text_hash = hs_submit_data(text_key, &text_arena, text); @@ -747,7 +722,7 @@ ASYNC_WORK_DEF(dasm_parse_work) } //- rjf: commit results to cache - if(got_task) OS_MutexScopeW(stripe->rw_mutex) + OS_MutexScopeW(stripe->rw_mutex) { for(DASM_Node *n = slot->first; n != 0; n = n->next) { @@ -763,8 +738,6 @@ ASYNC_WORK_DEF(dasm_parse_work) { n->change_gen = 0; } - ins_atomic_u32_eval_assign(&n->is_working, 0); - ins_atomic_u64_inc_eval(&n->load_count); break; } } @@ -807,8 +780,7 @@ dasm_evictor_detector_thread__entry_point(void *p) if(n->scope_ref_count == 0 && n->last_time_touched_us+evict_threshold_us <= check_time_us && n->last_user_clock_idx_touched+evict_threshold_user_clocks <= check_time_user_clocks && - n->load_count != 0 && - n->is_working == 0) + ins_atomic_u64_eval(&n->working_count) == 0) { slot_has_work = 1; break; @@ -830,8 +802,7 @@ dasm_evictor_detector_thread__entry_point(void *p) if(n->scope_ref_count == 0 && n->last_time_touched_us+evict_threshold_us <= check_time_us && n->last_user_clock_idx_touched+evict_threshold_user_clocks <= check_time_user_clocks && - n->load_count != 0 && - n->is_working == 0) + ins_atomic_u64_eval(&n->working_count) == 0) { DLLRemove(slot->first, slot->last, n); if(n->info_arena != 0) @@ -844,7 +815,7 @@ dasm_evictor_detector_thread__entry_point(void *p) n->last_time_requested_us+retry_threshold_us <= check_time_us && n->last_user_clock_idx_requested+retry_threshold_user_clocks <= check_time_user_clocks) { - if(dasm_u2p_enqueue_req(n->hash, &n->params, max_U64)) + if(dasm_u2p_enqueue_req(n->root, n->hash, &n->params, max_U64)) { async_push_work(dasm_parse_work); n->last_time_requested_us = os_now_microseconds(); diff --git a/src/dasm_cache/dasm_cache.h b/src/dasm_cache/dasm_cache.h index 2d670111..25a222fe 100644 --- a/src/dasm_cache/dasm_cache.h +++ b/src/dasm_cache/dasm_cache.h @@ -159,7 +159,7 @@ struct DASM_Result typedef struct DASM_Info DASM_Info; struct DASM_Info { - U128 text_key; + HS_Key text_key; DASM_LineArray lines; }; @@ -177,6 +177,9 @@ struct DASM_Node U128 hash; DASM_Params params; + // rjf: root + HS_Root root; + // rjf: generations U64 change_gen; @@ -185,11 +188,10 @@ struct DASM_Node DASM_Info info; // rjf: metadata - B32 is_working; + U64 working_count; U64 scope_ref_count; U64 last_time_touched_us; U64 last_user_clock_idx_touched; - U64 load_count; U64 last_time_requested_us; U64 last_user_clock_idx_requested; }; @@ -309,13 +311,13 @@ internal void dasm_scope_touch_node__stripe_r_guarded(DASM_Scope *scope, DASM_No //~ rjf: Cache Lookups internal DASM_Info dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params); -internal DASM_Info dasm_info_from_key_params(DASM_Scope *scope, U128 key, DASM_Params *params, U128 *hash_out); +internal DASM_Info dasm_info_from_key_params(DASM_Scope *scope, HS_Key key, DASM_Params *params, U128 *hash_out); //////////////////////////////// //~ rjf: Parse Threads -internal B32 dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us); -internal void dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out); +internal B32 dasm_u2p_enqueue_req(HS_Root root, U128 hash, DASM_Params *params, U64 endt_us); +internal void dasm_u2p_dequeue_req(Arena *arena, HS_Root *root_out, U128 *hash_out, DASM_Params *params_out); ASYNC_WORK_DEF(dasm_parse_work); //////////////////////////////// diff --git a/src/dbg_engine/dbg_engine_core.c b/src/dbg_engine/dbg_engine_core.c index e9888f38..5c90af76 100644 --- a/src/dbg_engine/dbg_engine_core.c +++ b/src/dbg_engine/dbg_engine_core.c @@ -1443,7 +1443,7 @@ d_init(void) d_state = push_array(arena, D_State, 1); d_state->arena = arena; d_state->cmds_arena = arena_alloc(); - d_state->output_log_key = hs_hash_from_data(str8_lit("output_log_key")); + d_state->output_log_key = hs_key_make(hs_root_alloc(), hs_id_make(0, 0)); hs_submit_data(d_state->output_log_key, 0, str8_zero()); d_state->ctrl_entity_store = ctrl_entity_ctx_rw_store_alloc(); d_state->ctrl_stop_arena = arena_alloc(); diff --git a/src/dbg_engine/dbg_engine_core.h b/src/dbg_engine/dbg_engine_core.h index 3773329e..16d5101b 100644 --- a/src/dbg_engine/dbg_engine_core.h +++ b/src/dbg_engine/dbg_engine_core.h @@ -312,7 +312,7 @@ struct D_State D_CmdList cmds; // rjf: output log key - U128 output_log_key; + HS_Key output_log_key; // rjf: per-run caches D_UnwindCache unwind_cache; diff --git a/src/file_stream/file_stream.c b/src/file_stream/file_stream.c index 3229a321..feb6d815 100644 --- a/src/file_stream/file_stream.c +++ b/src/file_stream/file_stream.c @@ -71,125 +71,151 @@ fs_change_gen(void) //////////////////////////////// //~ rjf: Cache Interaction -internal U128 -fs_hash_from_path_range(String8 path, Rng1U64 range, U64 endt_us) +internal HS_Key +fs_key_from_path_range(String8 path, Rng1U64 range, U64 endt_us) { Temp scratch = scratch_begin(0, 0); //- rjf: unpack args path = path_normalized_from_string(scratch.arena, path); - U128 key = fs_big_hash_from_string_range(path, range); + U64 path_little_hash = fs_little_hash_from_string(path); + U64 path_slot_idx = path_little_hash%fs_shared->slots_count; + U64 path_stripe_idx = path_slot_idx%fs_shared->stripes_count; + FS_Slot *path_slot = &fs_shared->slots[path_slot_idx]; + FS_Stripe *path_stripe = &fs_shared->stripes[path_stripe_idx]; - //- rjf: loop through key -> hash history; obtain most recent hash for this key - U128 result = {0}; - for(U64 rewind_idx = 0; rewind_idx < HS_KEY_HASH_HISTORY_COUNT; rewind_idx += 1) + //- rjf: get root for this path + HS_Root root = {0}; + OS_MutexScopeR(path_stripe->rw_mutex) { - result = hs_hash_from_key(key, rewind_idx); - - //- rjf: nonzero hash -> got valid results, return - if(!u128_match(result, u128_zero())) + B32 node_found = 0; + for(FS_Node *n = path_slot->first; n != 0; n = n->next) { - break; - } - - //- rjf: zero hash, not rewound? -> send new stream request if needed - else if(u128_match(result, u128_zero()) && rewind_idx == 0) - { - // rjf: unpack path cache info - U64 path_little_hash = fs_little_hash_from_string(path); - U64 path_slot_idx = path_little_hash%fs_shared->slots_count; - U64 path_stripe_idx = path_slot_idx%fs_shared->stripes_count; - FS_Slot *path_slot = &fs_shared->slots[path_slot_idx]; - FS_Stripe *path_stripe = &fs_shared->stripes[path_stripe_idx]; - - // rjf: loop: request, check for results, return until we can't - OS_MutexScopeW(path_stripe->rw_mutex) for(;;) + if(str8_match(n->path, path, 0)) { - // rjf: path -> node - FS_Node *node = 0; - for(FS_Node *n = path_slot->first; n != 0; n = n->next) - { - if(str8_match(path, n->path, 0)) - { - node = n; - break; - } - } - - // rjf: node does not exist? -> create & store - if(node == 0) - { - node = push_array(path_stripe->arena, FS_Node, 1); - SLLQueuePush(path_slot->first, path_slot->last, node); - node->path = push_str8_copy(path_stripe->arena, path); - node->slots_count = 64; - node->slots = push_array(path_stripe->arena, FS_RangeSlot, node->slots_count); - } - - // rjf: range -> node - U64 range_hash = fs_little_hash_from_string(str8_struct(&range)); - U64 range_slot_idx = range_hash%node->slots_count; - FS_RangeSlot *range_slot = &node->slots[range_slot_idx]; - FS_RangeNode *range_node = 0; - for(FS_RangeNode *n = range_slot->first; n != 0; n = n->next) - { - if(MemoryMatchStruct(&n->range, &range)) - { - range_node = n; - break; - } - } - - // rjf: range node does not exist? create & store - if(range_node == 0) - { - range_node = push_array(path_stripe->arena, FS_RangeNode, 1); - SLLQueuePush(range_slot->first, range_slot->last, range_node); - range_node->range = range; - } - - // rjf: try to send stream request - if((ins_atomic_u64_eval(&range_node->request_count) == ins_atomic_u64_eval(&range_node->completion_count) || - ins_atomic_u64_eval(&range_node->last_time_requested_us)+100000 < os_now_microseconds()) && - fs_u2s_enqueue_req(range, path, endt_us)) - { - ins_atomic_u64_eval_assign(&range_node->last_time_requested_us, os_now_microseconds()); - ins_atomic_u64_inc_eval(&range_node->request_count); - DeferLoop(os_rw_mutex_drop_w(path_stripe->rw_mutex), os_rw_mutex_take_w(path_stripe->rw_mutex)) - { - async_push_work(fs_stream_work, .completion_counter = &range_node->completion_count); - } - } - - // rjf: try to reobtain results - result = hs_hash_from_key(key, 0); - - // rjf: have time to wait? -> wait on this stripe; otherwise exit - if(u128_match(result, u128_zero()) && os_now_microseconds() <= endt_us) - { - os_condition_variable_wait_rw_w(path_stripe->cv, path_stripe->rw_mutex, endt_us); - } - else + node_found = 1; + root = n->root; + break; + } + } + if(!node_found) OS_MutexScopeRWPromote(path_stripe->rw_mutex) + { + B32 node_found = 0; + for(FS_Node *n = path_slot->first; n != 0; n = n->next) + { + if(str8_match(n->path, path, 0)) { + node_found = 1; + root = n->root; break; } } + if(!node_found) + { + FS_Node *node = push_array(path_stripe->arena, FS_Node, 1); + SLLQueuePush(path_slot->first, path_slot->last, node); + node->path = push_str8_copy(path_stripe->arena, path); + node->root = hs_root_alloc(); + node->slots_count = 64; + node->slots = push_array(path_stripe->arena, FS_RangeSlot, node->slots_count); + root = node->root; + } + } + } + + //- rjf: build a key for this path/range combo + HS_Key key = hs_key_make(root, hs_id_make(range.min, range.max)); + + //- rjf: if the most recent hash for this key is zero, then try to submit a new + // request to pull it in. + if(u128_match(hs_hash_from_key(key, 0), u128_zero())) + { + // rjf: loop: request, check for results, return until we can't + OS_MutexScopeW(path_stripe->rw_mutex) for(;;) + { + // rjf: path -> node + FS_Node *node = 0; + for(FS_Node *n = path_slot->first; n != 0; n = n->next) + { + if(str8_match(path, n->path, 0)) + { + node = n; + break; + } + } + + // rjf: no node? -> weird case, node should've been made at this point. + if(node == 0) + { + break; + } + + // rjf: range -> node + U64 range_hash = fs_little_hash_from_string(str8_struct(&key.id)); + U64 range_slot_idx = range_hash%node->slots_count; + FS_RangeSlot *range_slot = &node->slots[range_slot_idx]; + FS_RangeNode *range_node = 0; + for(FS_RangeNode *n = range_slot->first; n != 0; n = n->next) + { + if(hs_id_match(n->id, key.id)) + { + range_node = n; + break; + } + } + + // rjf: range node does not exist? create & store + if(range_node == 0) + { + range_node = push_array(path_stripe->arena, FS_RangeNode, 1); + SLLQueuePush(range_slot->first, range_slot->last, range_node); + range_node->id = key.id; + } + + // rjf: try to send stream request + if(ins_atomic_u64_eval(&range_node->working_count) == 0 && + fs_u2s_enqueue_req(key, range, path, endt_us)) + { + ins_atomic_u64_inc_eval(&range_node->working_count); + DeferLoop(os_rw_mutex_drop_w(path_stripe->rw_mutex), os_rw_mutex_take_w(path_stripe->rw_mutex)) + { + async_push_work(fs_stream_work, .working_counter = &range_node->working_count); + } + } + + // rjf: have time to wait? -> wait on this stripe; otherwise exit + B32 have_results = !u128_match(hs_hash_from_key(key, 0), u128_zero()); + if(!have_results && os_now_microseconds() < endt_us) + { + os_condition_variable_wait_rw_w(path_stripe->cv, path_stripe->rw_mutex, endt_us); + } + else + { + break; + } } } scratch_end(scratch); - return result; + return key; } internal U128 -fs_key_from_path_range(String8 path, Rng1U64 range) +fs_hash_from_path_range(String8 path, Rng1U64 range, U64 endt_us) { - Temp scratch = scratch_begin(0, 0); - String8 path_normalized = path_normalized_from_string(scratch.arena, path); - U128 key = fs_big_hash_from_string_range(path_normalized, range); - fs_hash_from_path_range(path_normalized, range, 0); - scratch_end(scratch); - return key; + U128 hash = {0}; + { + HS_Key key = fs_key_from_path_range(path, range, endt_us); + for EachIndex(rewind_idx, HS_KEY_HASH_HISTORY_COUNT) + { + hash = hs_hash_from_key(key, rewind_idx); + if(!u128_match(hash, u128_zero())) + { + break; + } + } + } + return hash; } internal FileProperties @@ -222,7 +248,7 @@ fs_properties_from_path(String8 path) //~ rjf: Streamer Threads internal B32 -fs_u2s_enqueue_req(Rng1U64 range, String8 path, U64 endt_us) +fs_u2s_enqueue_req(HS_Key key, Rng1U64 range, String8 path, U64 endt_us) { B32 result = 0; path.size = Min(path.size, fs_shared->u2s_ring_size); @@ -230,10 +256,11 @@ fs_u2s_enqueue_req(Rng1U64 range, String8 path, U64 endt_us) { U64 unconsumed_size = fs_shared->u2s_ring_write_pos - fs_shared->u2s_ring_read_pos; U64 available_size = fs_shared->u2s_ring_size - unconsumed_size; - U64 needed_size = sizeof(range.min) + sizeof(range.max) + sizeof(path.size) + path.size; + U64 needed_size = sizeof(key) + sizeof(range.min) + sizeof(range.max) + sizeof(path.size) + path.size; if(available_size >= needed_size) { result = 1; + fs_shared->u2s_ring_write_pos += ring_write_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_write_pos, &key); fs_shared->u2s_ring_write_pos += ring_write_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_write_pos, &range.min); fs_shared->u2s_ring_write_pos += ring_write_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_write_pos, &range.max); fs_shared->u2s_ring_write_pos += ring_write_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_write_pos, &path.size); @@ -250,13 +277,14 @@ fs_u2s_enqueue_req(Rng1U64 range, String8 path, U64 endt_us) } internal void -fs_u2s_dequeue_req(Arena *arena, Rng1U64 *range_out, String8 *path_out) +fs_u2s_dequeue_req(Arena *arena, HS_Key *key_out, Rng1U64 *range_out, String8 *path_out) { OS_MutexScope(fs_shared->u2s_ring_mutex) for(;;) { U64 unconsumed_size = fs_shared->u2s_ring_write_pos - fs_shared->u2s_ring_read_pos; - if(unconsumed_size >= sizeof(U64)) + if(unconsumed_size >= sizeof(*key_out) + sizeof(U64)*2 + sizeof(U64)) { + fs_shared->u2s_ring_read_pos += ring_read_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, key_out); fs_shared->u2s_ring_read_pos += ring_read_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, &range_out->min); fs_shared->u2s_ring_read_pos += ring_read_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, &range_out->max); fs_shared->u2s_ring_read_pos += ring_read_struct(fs_shared->u2s_ring_base, fs_shared->u2s_ring_size, fs_shared->u2s_ring_read_pos, &path_out->size); @@ -275,12 +303,12 @@ ASYNC_WORK_DEF(fs_stream_work) Temp scratch = scratch_begin(0, 0); //- rjf: get next request + HS_Key key = {0}; Rng1U64 range = {0}; String8 path = {0}; - fs_u2s_dequeue_req(scratch.arena, &range, &path); + fs_u2s_dequeue_req(scratch.arena, &key, &range, &path); //- rjf: unpack request - U128 key = fs_big_hash_from_string_range(path, range); U64 path_hash = fs_little_hash_from_string(path); U64 path_slot_idx = path_hash%fs_shared->slots_count; U64 path_stripe_idx = path_slot_idx%fs_shared->stripes_count; @@ -387,12 +415,12 @@ fs_detector_thread__entry_point(void *p) range_n != 0; range_n = range_n->next) { - if(ins_atomic_u64_eval(&range_n->request_count) == ins_atomic_u64_eval(&range_n->completion_count) && - fs_u2s_enqueue_req(range_n->range, n->path, os_now_microseconds()+100000)) + HS_Key key = hs_key_make(n->root, range_n->id); + if(ins_atomic_u64_eval(&range_n->working_count) == 0 && + fs_u2s_enqueue_req(key, r1u64(key.id.u128[0].u64[0], key.id.u128[0].u64[1]), n->path, os_now_microseconds()+100000)) { - ins_atomic_u64_eval_assign(&range_n->last_time_requested_us, os_now_microseconds()); - ins_atomic_u64_inc_eval(&range_n->request_count); - async_push_work(fs_stream_work, .completion_counter = &range_n->completion_count); + ins_atomic_u64_inc_eval(&range_n->working_count); + async_push_work(fs_stream_work, .working_counter = &range_n->working_count); } } } diff --git a/src/file_stream/file_stream.h b/src/file_stream/file_stream.h index d1ec870b..a0ede57c 100644 --- a/src/file_stream/file_stream.h +++ b/src/file_stream/file_stream.h @@ -11,10 +11,8 @@ typedef struct FS_RangeNode FS_RangeNode; struct FS_RangeNode { FS_RangeNode *next; - Rng1U64 range; - U64 request_count; - U64 completion_count; - U64 last_time_requested_us; + HS_ID id; + U64 working_count; }; typedef struct FS_RangeSlot FS_RangeSlot; @@ -33,6 +31,9 @@ struct FS_Node String8 path; FileProperties props; + // rjf: hash store root + HS_Root root; + // rjf: sub-table of per-requested-file-range info U64 slots_count; FS_RangeSlot *slots; @@ -104,16 +105,15 @@ internal U64 fs_change_gen(void); //////////////////////////////// //~ rjf: Cache Interaction +internal HS_Key fs_key_from_path_range(String8 path, Rng1U64 range, U64 endt_us); internal U128 fs_hash_from_path_range(String8 path, Rng1U64 range, U64 endt_us); -internal U128 fs_key_from_path_range(String8 path, Rng1U64 range); - internal FileProperties fs_properties_from_path(String8 path); //////////////////////////////// //~ rjf: Streaming Work -internal B32 fs_u2s_enqueue_req(Rng1U64 range, String8 path, U64 endt_us); -internal void fs_u2s_dequeue_req(Arena *arena, Rng1U64 *range_out, String8 *path_out); +internal B32 fs_u2s_enqueue_req(HS_Key key, Rng1U64 range, String8 path, U64 endt_us); +internal void fs_u2s_dequeue_req(Arena *arena, HS_Key *key_out, Rng1U64 *range_out, String8 *path_out); ASYNC_WORK_DEF(fs_stream_work); //////////////////////////////// diff --git a/src/geo_cache/geo_cache.c b/src/geo_cache/geo_cache.c index 1af64fec..dd7fa2e0 100644 --- a/src/geo_cache/geo_cache.c +++ b/src/geo_cache/geo_cache.c @@ -181,7 +181,7 @@ geo_buffer_from_hash(GEO_Scope *scope, U128 hash) } internal R_Handle -geo_buffer_from_key(GEO_Scope *scope, U128 key) +geo_buffer_from_key(GEO_Scope *scope, HS_Key key) { R_Handle handle = {0}; for(U64 rewind_idx = 0; rewind_idx < HS_KEY_HASH_HISTORY_COUNT; rewind_idx += 1) diff --git a/src/geo_cache/geo_cache.h b/src/geo_cache/geo_cache.h index 230d059e..d343be8e 100644 --- a/src/geo_cache/geo_cache.h +++ b/src/geo_cache/geo_cache.h @@ -118,7 +118,7 @@ internal void geo_scope_touch_node__stripe_r_guarded(GEO_Scope *scope, GEO_Node //~ rjf: Cache Lookups internal R_Handle geo_buffer_from_hash(GEO_Scope *scope, U128 hash); -internal R_Handle geo_buffer_from_key(GEO_Scope *scope, U128 key); +internal R_Handle geo_buffer_from_key(GEO_Scope *scope, HS_Key key); //////////////////////////////// //~ rjf: Transfer Threads diff --git a/src/hash_store/hash_store.c b/src/hash_store/hash_store.c index 20c26aee..297f532f 100644 --- a/src/hash_store/hash_store.c +++ b/src/hash_store/hash_store.c @@ -13,6 +13,13 @@ # include "third_party/xxHash/xxhash.h" #endif +internal U64 +hs_little_hash_from_data(String8 data) +{ + U64 result = XXH3_64bits(data.str, data.size); + return result; +} + internal U128 hs_hash_from_data(String8 data) { @@ -22,6 +29,35 @@ hs_hash_from_data(String8 data) return u128; } +internal HS_ID +hs_id_make(U64 u64_0, U64 u64_1) +{ + HS_ID id; + id.u128[0].u64[0] = u64_0; + id.u128[0].u64[1] = u64_1; + return id; +} + +internal B32 +hs_id_match(HS_ID a, HS_ID b) +{ + B32 result = MemoryMatchStruct(&a, &b); + return result; +} + +internal HS_Key +hs_key_make(HS_Root root, HS_ID id) +{ + HS_Key key = {root, 0, id}; + return key; +} + +internal B32 +hs_key_match(HS_Key a, HS_Key b) +{ + return (MemoryMatchStruct(&a.root, &b.root) && hs_id_match(a.id, b.id)); +} + //////////////////////////////// //~ rjf: Main Layer Initialization @@ -73,11 +109,11 @@ hs_init(void) //////////////////////////////// //~ rjf: Root Allocation/Deallocation -internal U128 +internal HS_Root hs_root_alloc(void) { - U128 root = {0}; - root.u64[1] = ins_atomic_u64_inc_eval(&hs_shared->root_id_gen); + HS_Root root = {0}; + root.u64[0] = ins_atomic_u64_inc_eval(&hs_shared->root_id_gen); U64 slot_idx = root.u64[1]%hs_shared->root_slots_count; U64 stripe_idx = slot_idx%hs_shared->root_stripes_count; HS_RootSlot *slot = &hs_shared->root_slots[slot_idx]; @@ -101,7 +137,7 @@ hs_root_alloc(void) } internal void -hs_root_release(U128 root) +hs_root_release(HS_Root root) { U64 slot_idx = root.u64[1]%hs_shared->root_slots_count; U64 stripe_idx = slot_idx%hs_shared->root_stripes_count; @@ -111,7 +147,7 @@ hs_root_release(U128 root) { for(HS_RootNode *n = slot->first; n != 0; n = n->next) { - if(u128_match(n->root, root)) + if(MemoryMatchStruct(&root, &n->root)) { DLLRemove(slot->first, slot->last, n); arena_release(n->arena); @@ -126,9 +162,10 @@ hs_root_release(U128 root) //~ rjf: Cache Submission internal U128 -hs_submit_data(U128 key, Arena **data_arena, String8 data) +hs_submit_data(HS_Key key, Arena **data_arena, String8 data) { - U64 key_slot_idx = key.u64[1]%hs_shared->key_slots_count; + U64 key_hash = hs_little_hash_from_data(str8_struct(&key)); + U64 key_slot_idx = key_hash%hs_shared->key_slots_count; U64 key_stripe_idx = key_slot_idx%hs_shared->key_stripes_count; HS_KeySlot *key_slot = &hs_shared->key_slots[key_slot_idx]; HS_Stripe *key_stripe = &hs_shared->key_stripes[key_stripe_idx]; @@ -192,7 +229,7 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data) HS_KeyNode *key_node = 0; for(HS_KeyNode *n = key_slot->first; n != 0; n = n->next) { - if(u128_match(n->key, key)) + if(hs_key_match(n->key, key)) { key_node = n; break; @@ -321,9 +358,10 @@ hs_scope_touch_node__stripe_r_guarded(HS_Scope *scope, HS_Node *node) //~ rjf: Key Closing internal void -hs_key_close(U128 key) +hs_key_close(HS_Key key) { - U64 key_slot_idx = key.u64[1]%hs_shared->key_slots_count; + U64 key_hash = hs_little_hash_from_data(str8_struct(&key)); + U64 key_slot_idx = key_hash%hs_shared->key_slots_count; U64 key_stripe_idx = key_slot_idx%hs_shared->key_stripes_count; HS_KeySlot *key_slot = &hs_shared->key_slots[key_slot_idx]; HS_Stripe *key_stripe = &hs_shared->key_stripes[key_stripe_idx]; @@ -331,7 +369,7 @@ hs_key_close(U128 key) { for(HS_KeyNode *n = key_slot->first; n != 0; n = n->next) { - if(u128_match(n->key, key)) + if(hs_key_match(n->key, key)) { for(U64 history_idx = 0; history_idx < HS_KEY_HASH_HISTORY_STRONG_REF_COUNT && history_idx < n->hash_history_gen; history_idx += 1) { @@ -407,10 +445,11 @@ hs_hash_downstream_dec(U128 hash) //~ rjf: Cache Lookup internal U128 -hs_hash_from_key(U128 key, U64 rewind_count) +hs_hash_from_key(HS_Key key, U64 rewind_count) { U128 result = {0}; - U64 key_slot_idx = key.u64[1]%hs_shared->key_slots_count; + U64 key_hash = hs_little_hash_from_data(str8_struct(&key)); + U64 key_slot_idx = key_hash%hs_shared->key_slots_count; U64 key_stripe_idx = key_slot_idx%hs_shared->key_stripes_count; HS_KeySlot *key_slot = &hs_shared->key_slots[key_slot_idx]; HS_Stripe *key_stripe = &hs_shared->key_stripes[key_stripe_idx]; @@ -418,7 +457,7 @@ hs_hash_from_key(U128 key, U64 rewind_count) { for(HS_KeyNode *n = key_slot->first; n != 0; n = n->next) { - if(u128_match(n->key, key) && n->hash_history_gen > 0 && n->hash_history_gen-1 >= rewind_count) + if(hs_key_match(n->key, key) && n->hash_history_gen > 0 && n->hash_history_gen-1 >= rewind_count) { result = n->hash_history[(n->hash_history_gen-1-rewind_count)%ArrayCount(n->hash_history)]; break; diff --git a/src/hash_store/hash_store.h b/src/hash_store/hash_store.h index b626a0ba..c5c3412e 100644 --- a/src/hash_store/hash_store.h +++ b/src/hash_store/hash_store.h @@ -40,23 +40,46 @@ // submit that data to the hash store, correllating with the root and key // combo. +//////////////////////////////// +//~ rjf: Key Types + +typedef struct HS_Root HS_Root; +struct HS_Root +{ + U64 u64[1]; +}; + +typedef struct HS_ID HS_ID; +struct HS_ID +{ + U128 u128[1]; +}; + +typedef struct HS_Key HS_Key; +struct HS_Key +{ + HS_Root root; + U64 _padding_; + HS_ID id; +}; + //////////////////////////////// //~ rjf: Cache Types -typedef struct HS_RootKeyChunkNode HS_RootKeyChunkNode; -struct HS_RootKeyChunkNode +typedef struct HS_RootIDChunkNode HS_RootIDChunkNode; +struct HS_RootIDChunkNode { - HS_RootKeyChunkNode *next; + HS_RootIDChunkNode *next; U128 *v; U64 count; U64 cap; }; -typedef struct HS_RootKeyChunkList HS_RootKeyChunkList; -struct HS_RootKeyChunkList +typedef struct HS_RootIDChunkList HS_RootIDChunkList; +struct HS_RootIDChunkList { - HS_RootKeyChunkNode *first; - HS_RootKeyChunkNode *last; + HS_RootIDChunkNode *first; + HS_RootIDChunkNode *last; U64 chunk_count; U64 total_count; }; @@ -67,8 +90,8 @@ struct HS_RootNode HS_RootNode *next; HS_RootNode *prev; Arena *arena; - U128 root; - HS_RootKeyChunkList keys; + HS_Root root; + HS_RootIDChunkList ids; }; typedef struct HS_RootSlot HS_RootSlot; @@ -86,7 +109,7 @@ struct HS_KeyNode { HS_KeyNode *next; HS_KeyNode *prev; - U128 key; + HS_Key key; U128 hash_history[HS_KEY_HASH_HISTORY_COUNT]; U64 hash_history_gen; }; @@ -197,7 +220,12 @@ global HS_Shared *hs_shared = 0; //////////////////////////////// //~ rjf: Basic Helpers +internal U64 hs_little_hash_from_data(String8 data); internal U128 hs_hash_from_data(String8 data); +internal HS_ID hs_id_make(U64 u64_0, U64 u64_1); +internal B32 hs_id_match(HS_ID a, HS_ID b); +internal HS_Key hs_key_make(HS_Root root, HS_ID id); +internal B32 hs_key_match(HS_Key a, HS_Key b); //////////////////////////////// //~ rjf: Main Layer Initialization @@ -207,13 +235,13 @@ internal void hs_init(void); //////////////////////////////// //~ rjf: Root Allocation/Deallocation -internal U128 hs_root_alloc(void); -internal void hs_root_release(U128 root); +internal HS_Root hs_root_alloc(void); +internal void hs_root_release(HS_Root root); //////////////////////////////// //~ rjf: Cache Submission -internal U128 hs_submit_data(U128 key, Arena **data_arena, String8 data); +internal U128 hs_submit_data(HS_Key key, Arena **data_arena, String8 data); //////////////////////////////// //~ rjf: Scoped Access @@ -225,7 +253,7 @@ internal void hs_scope_touch_node__stripe_r_guarded(HS_Scope *scope, HS_Node *no //////////////////////////////// //~ rjf: Key Closing -internal void hs_key_close(U128 key); +internal void hs_key_close(HS_Key key); //////////////////////////////// //~ rjf: Downstream Accesses @@ -236,7 +264,7 @@ internal void hs_hash_downstream_dec(U128 hash); //////////////////////////////// //~ rjf: Cache Lookups -internal U128 hs_hash_from_key(U128 key, U64 rewind_count); +internal U128 hs_hash_from_key(HS_Key key, U64 rewind_count); internal String8 hs_data_from_hash(HS_Scope *scope, U128 hash); //////////////////////////////// diff --git a/src/mutable_text/mutable_text.c b/src/mutable_text/mutable_text.c index 006ea601..94549be7 100644 --- a/src/mutable_text/mutable_text.c +++ b/src/mutable_text/mutable_text.c @@ -38,9 +38,10 @@ mtx_init(void) //~ rjf: Buffer Operations internal void -mtx_push_op(U128 buffer_key, MTX_Op op) +mtx_push_op(HS_Key buffer_key, MTX_Op op) { - MTX_MutThread *thread = &mtx_shared->mut_threads[buffer_key.u64[1]%mtx_shared->mut_threads_count]; + U64 hash = hs_little_hash_from_data(str8_struct(&buffer_key)); + MTX_MutThread *thread = &mtx_shared->mut_threads[hash%mtx_shared->mut_threads_count]; mtx_enqueue_op(thread, buffer_key, op); } @@ -48,7 +49,7 @@ mtx_push_op(U128 buffer_key, MTX_Op op) //~ rjf: Mutation Threads internal void -mtx_enqueue_op(MTX_MutThread *thread, U128 buffer_key, MTX_Op op) +mtx_enqueue_op(MTX_MutThread *thread, HS_Key buffer_key, MTX_Op op) { // TODO(rjf): if op.replace is too big, need to split into multiple edits OS_MutexScope(thread->mutex) for(;;) @@ -70,7 +71,7 @@ mtx_enqueue_op(MTX_MutThread *thread, U128 buffer_key, MTX_Op op) } internal void -mtx_dequeue_op(Arena *arena, MTX_MutThread *thread, U128 *buffer_key_out, MTX_Op *op_out) +mtx_dequeue_op(Arena *arena, MTX_MutThread *thread, HS_Key *buffer_key_out, MTX_Op *op_out) { OS_MutexScope(thread->mutex) for(;;) { @@ -100,7 +101,7 @@ mtx_mut_thread__entry_point(void *p) HS_Scope *hs_scope = hs_scope_open(); //- rjf: get next op - U128 buffer_key = {0}; + HS_Key buffer_key = {0}; MTX_Op op = {0}; mtx_dequeue_op(scratch.arena, mut_thread, &buffer_key, &op); diff --git a/src/mutable_text/mutable_text.h b/src/mutable_text/mutable_text.h index 505caac6..1614ae48 100644 --- a/src/mutable_text/mutable_text.h +++ b/src/mutable_text/mutable_text.h @@ -84,13 +84,13 @@ internal void mtx_init(void); //////////////////////////////// //~ rjf: Buffer Operations -internal void mtx_push_op(U128 buffer_key, MTX_Op op); +internal void mtx_push_op(HS_Key buffer_key, MTX_Op op); //////////////////////////////// //~ rjf: Mutation Threads -internal void mtx_enqueue_op(MTX_MutThread *thread, U128 buffer_key, MTX_Op op); -internal void mtx_dequeue_op(Arena *arena, MTX_MutThread *thread, U128 *buffer_key_out, MTX_Op *op_out); +internal void mtx_enqueue_op(MTX_MutThread *thread, HS_Key buffer_key, MTX_Op op); +internal void mtx_dequeue_op(Arena *arena, MTX_MutThread *thread, HS_Key *buffer_key_out, MTX_Op *op_out); internal void mtx_mut_thread__entry_point(void *p); #endif // MUTABLE_TEXT_H diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 0d652895..7c2e92df 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -456,7 +456,7 @@ Rng1U64 rd_reg_slot_range_table[44] = {OffsetOf(RD_Regs, file_path), OffsetOf(RD_Regs, file_path) + sizeof(String8)}, {OffsetOf(RD_Regs, cursor), OffsetOf(RD_Regs, cursor) + sizeof(TxtPt)}, {OffsetOf(RD_Regs, mark), OffsetOf(RD_Regs, mark) + sizeof(TxtPt)}, -{OffsetOf(RD_Regs, text_key), OffsetOf(RD_Regs, text_key) + sizeof(U128)}, +{OffsetOf(RD_Regs, text_key), OffsetOf(RD_Regs, text_key) + sizeof(HS_Key)}, {OffsetOf(RD_Regs, lang_kind), OffsetOf(RD_Regs, lang_kind) + sizeof(TXT_LangKind)}, {OffsetOf(RD_Regs, lines), OffsetOf(RD_Regs, lines) + sizeof(D_LineList)}, {OffsetOf(RD_Regs, dbgi_key), OffsetOf(RD_Regs, dbgi_key) + sizeof(DI_Key)}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 6473c8bd..8d48807c 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -450,7 +450,7 @@ U64 inline_depth; String8 file_path; TxtPt cursor; TxtPt mark; -U128 text_key; +HS_Key text_key; TXT_LangKind lang_kind; D_LineList lines; DI_Key dbgi_key; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index 86129cf8..aceda3d5 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -712,7 +712,7 @@ RD_RegTable: {String8 file_path FilePath } {TxtPt cursor Cursor } {TxtPt mark Mark } - {U128 text_key TextKey } + {HS_Key text_key TextKey } {TXT_LangKind lang_kind LangKind } {D_LineList lines Lines } {DI_Key dbgi_key DbgiKey } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 6dece756..458ee937 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -1747,7 +1747,9 @@ rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range) //- rjf: reads from hash store key case E_SpaceKind_HashStoreKey: { - U128 key = space.u128; + HS_Root root = {space.u64_0}; + HS_ID id = {space.u128}; + HS_Key key = hs_key_make(root, id); U128 hash = hs_hash_from_key(key, 0); HS_Scope *scope = hs_scope_open(); { @@ -1778,7 +1780,7 @@ rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range) containing_range.max -= containing_range.max%chunk_size; // rjf: map to hash - U128 key = fs_key_from_path_range(file_path, containing_range); + HS_Key key = fs_key_from_path_range(file_path, containing_range, 0); U128 hash = hs_hash_from_key(key, 0); // rjf: look up from hash store @@ -2136,28 +2138,30 @@ rd_eval_space_write(void *u, E_Space space, void *in, Rng1U64 range) //- rjf: asynchronous streamed reads -> hashes from spaces -internal U128 +internal HS_Key rd_key_from_eval_space_range(E_Space space, Rng1U64 range, B32 zero_terminated) { - U128 result = {0}; + HS_Key result = {0}; switch(space.kind) { case E_SpaceKind_HashStoreKey: { - result = space.u128; + HS_Root root = {space.u64_0}; + HS_ID id = {space.u128}; + result = hs_key_make(root, id); }break; case E_SpaceKind_File: { U64 file_path_string_id = space.u64_0; String8 file_path = e_string_from_id(file_path_string_id); - result = fs_key_from_path_range(file_path, range); + result = fs_key_from_path_range(file_path, range, 0); }break; case RD_EvalSpaceKind_CtrlEntity: { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); if(entity->kind == CTRL_EntityKind_Process) { - result = ctrl_hash_store_key_from_process_vaddr_range(entity->handle, range, zero_terminated); + result = ctrl_key_from_process_vaddr_range(entity->handle, range, zero_terminated, 0, 0); } }break; } @@ -2174,7 +2178,9 @@ rd_whole_range_from_eval_space(E_Space space) { case E_SpaceKind_HashStoreKey: { - U128 key = space.u128; + HS_Root root = {space.u64_0}; + HS_ID id = {space.u128}; + HS_Key key = hs_key_make(root, id); U128 hash = hs_hash_from_key(key, 0); HS_Scope *hs_scope = hs_scope_open(); { @@ -2867,7 +2873,7 @@ rd_view_ui(Rng2F32 rect) // rjf: unpack view's target expression & hash E_Eval eval = e_eval_from_string(expr_string); Rng1U64 range = r1u64(0, 1024); - U128 key = rd_key_from_eval_space_range(eval.space, range, 0); + HS_Key key = rd_key_from_eval_space_range(eval.space, range, 0); U128 hash = hs_hash_from_key(key, 0); // rjf: determine if hash's blob is ready, and which viewer to use @@ -6519,7 +6525,7 @@ rd_window_frame(void) if(ws->dev_menu_is_open) RD_Font(RD_FontSlot_Code) { ui_set_next_flags(UI_BoxFlag_ViewScrollY|UI_BoxFlag_AllowOverflowY|UI_BoxFlag_ViewClamp); - UI_PaneF(r2f32p(30, 30, 30+ui_top_font_size()*100, ui_top_font_size()*150), "###dev_ctx_menu") + UI_PaneF(r2f32p(30, 30, 30+ui_top_font_size()*100, ui_top_font_size()*60), "###dev_ctx_menu") { //- rjf: capture if(!ProfIsCapturing() && ui_clicked(ui_buttonf("Begin Profiler Capture###prof_cap"))) @@ -6580,7 +6586,7 @@ rd_window_frame(void) ui_labelf("mark: (L:%I64d, C:%I64d)", regs->mark.line, regs->mark.column); ui_labelf("unwind_count: %I64u", regs->unwind_count); ui_labelf("inline_depth: %I64u", regs->inline_depth); - ui_labelf("text_key: [0x%I64x, 0x%I64x]", regs->text_key.u64[0], regs->text_key.u64[1]); + ui_labelf("text_key: [0x%I64x / 0x%I64x:0x%I64x]", regs->text_key.root.u64[0], regs->text_key.id.u128[0].u64[0], regs->text_key.id.u128[0].u64[1]); ui_labelf("lang_kind: '%S'", txt_extension_from_lang_kind(regs->lang_kind)); ui_labelf("vaddr_range: [0x%I64x, 0x%I64x)", regs->vaddr_range.min, regs->vaddr_range.max); ui_labelf("voff_range: [0x%I64x, 0x%I64x)", regs->voff_range.min, regs->voff_range.max); @@ -12174,12 +12180,13 @@ rd_frame(void) //- rjf: add macro for output log { HS_Scope *hs_scope = hs_scope_open(); - U128 key = d_state->output_log_key; + HS_Key key = d_state->output_log_key; U128 hash = hs_hash_from_key(key, 0); String8 data = hs_data_from_hash(hs_scope, hash); E_Space space = e_space_make(E_SpaceKind_HashStoreKey); + space.u64_0 = key.root.u64[0]; + space.u128 = key.id.u128[0]; E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); - space.u128 = key; expr->space = space; expr->mode = E_Mode_Offset; expr->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), data.size, 0); @@ -15479,7 +15486,7 @@ rd_frame(void) HS_Scope *hs_scope = hs_scope_open(); TXT_Scope *txt_scope = txt_scope_open(); RD_Regs *regs = rd_regs(); - U128 text_key = regs->text_key; + HS_Key text_key = regs->text_key; TXT_LangKind lang_kind = regs->lang_kind; TxtRng range = txt_rng(regs->cursor, regs->mark); U128 hash = {0}; diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 3e4335c6..6468fbc6 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -890,7 +890,7 @@ internal B32 rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range internal B32 rd_eval_space_write(void *u, E_Space space, void *in, Rng1U64 range); //- rjf: asynchronous streamed reads -> hashes from spaces -internal U128 rd_key_from_eval_space_range(E_Space space, Rng1U64 range, B32 zero_terminated); +internal HS_Key rd_key_from_eval_space_range(E_Space space, Rng1U64 range, B32 zero_terminated); //- rjf: space -> entire range internal Rng1U64 rd_whole_range_from_eval_space(E_Space space); diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 177f9bd5..80fd780b 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -2381,7 +2381,7 @@ RD_VIEW_UI_FUNCTION_DEF(disasm) syntax = DASM_Syntax_ATT; } } - U128 dasm_key = rd_key_from_eval_space_range(space, range, 0); + HS_Key dasm_key = rd_key_from_eval_space_range(space, range, 0); U128 dasm_data_hash = {0}; DASM_Params dasm_params = {0}; { @@ -3572,7 +3572,7 @@ RD_VIEW_UI_FUNCTION_DEF(bitmap) ////////////////////////////// //- rjf: map expression artifacts -> texture // - U128 texture_key = rd_key_from_eval_space_range(eval.space, offset_range, 0); + HS_Key texture_key = rd_key_from_eval_space_range(eval.space, offset_range, 0); TEX_Topology topology = tex_topology_make(dim, fmt); U128 data_hash = {0}; R_Handle texture = tex_texture_from_key_topology(tex_scope, texture_key, topology, &data_hash); @@ -4058,8 +4058,8 @@ RD_VIEW_UI_FUNCTION_DEF(geo3d) U64 base_offset = e_base_offset_from_eval(eval); Rng1U64 idxs_range = r1u64(base_offset, base_offset+count*sizeof(U32)); Rng1U64 vtxs_range = r1u64(vtx_base_off, vtx_base_off+vtx_size); - U128 idxs_key = rd_key_from_eval_space_range(eval.space, idxs_range, 0); - U128 vtxs_key = rd_key_from_eval_space_range(eval.space, vtxs_range, 0); + HS_Key idxs_key = rd_key_from_eval_space_range(eval.space, idxs_range, 0); + HS_Key vtxs_key = rd_key_from_eval_space_range(eval.space, vtxs_range, 0); R_Handle idxs_buffer = geo_buffer_from_key(geo_scope, idxs_key); R_Handle vtxs_buffer = geo_buffer_from_key(geo_scope, vtxs_key); diff --git a/src/text_cache/text_cache.c b/src/text_cache/text_cache.c index e8c5da5c..e8706c1d 100644 --- a/src/text_cache/text_cache.c +++ b/src/text_cache/text_cache.c @@ -1771,7 +1771,7 @@ txt_text_info_from_hash_lang(TXT_Scope *scope, U128 hash, TXT_LangKind lang) } internal TXT_TextInfo -txt_text_info_from_key_lang(TXT_Scope *scope, U128 key, TXT_LangKind lang, U128 *hash_out) +txt_text_info_from_key_lang(TXT_Scope *scope, HS_Key key, TXT_LangKind lang, U128 *hash_out) { TXT_TextInfo result = {0}; for(U64 rewind_idx = 0; rewind_idx < HS_KEY_HASH_HISTORY_COUNT; rewind_idx += 1) diff --git a/src/text_cache/text_cache.h b/src/text_cache/text_cache.h index 2311139e..143a7b75 100644 --- a/src/text_cache/text_cache.h +++ b/src/text_cache/text_cache.h @@ -274,7 +274,7 @@ internal void txt_scope_touch_node__stripe_r_guarded(TXT_Scope *scope, TXT_Node //~ rjf: Cache Lookups internal TXT_TextInfo txt_text_info_from_hash_lang(TXT_Scope *scope, U128 hash, TXT_LangKind lang); -internal TXT_TextInfo txt_text_info_from_key_lang(TXT_Scope *scope, U128 key, TXT_LangKind lang, U128 *hash_out); +internal TXT_TextInfo txt_text_info_from_key_lang(TXT_Scope *scope, HS_Key key, TXT_LangKind lang, U128 *hash_out); //////////////////////////////// //~ rjf: Text Info Extractor Helpers diff --git a/src/texture_cache/texture_cache.c b/src/texture_cache/texture_cache.c index bca74e24..8bc7e657 100644 --- a/src/texture_cache/texture_cache.c +++ b/src/texture_cache/texture_cache.c @@ -196,7 +196,7 @@ tex_texture_from_hash_topology(TEX_Scope *scope, U128 hash, TEX_Topology topolog } internal R_Handle -tex_texture_from_key_topology(TEX_Scope *scope, U128 key, TEX_Topology topology, U128 *hash_out) +tex_texture_from_key_topology(TEX_Scope *scope, HS_Key key, TEX_Topology topology, U128 *hash_out) { R_Handle handle = {0}; for(U64 rewind_idx = 0; rewind_idx < HS_KEY_HASH_HISTORY_COUNT; rewind_idx += 1) diff --git a/src/texture_cache/texture_cache.h b/src/texture_cache/texture_cache.h index 617618dd..25a00be1 100644 --- a/src/texture_cache/texture_cache.h +++ b/src/texture_cache/texture_cache.h @@ -135,7 +135,7 @@ internal void tex_scope_touch_node__stripe_r_guarded(TEX_Scope *scope, TEX_Node //~ rjf: Cache Lookups internal R_Handle tex_texture_from_hash_topology(TEX_Scope *scope, U128 hash, TEX_Topology topology); -internal R_Handle tex_texture_from_key_topology(TEX_Scope *scope, U128 key, TEX_Topology topology, U128 *hash_out); +internal R_Handle tex_texture_from_key_topology(TEX_Scope *scope, HS_Key key, TEX_Topology topology, U128 *hash_out); //////////////////////////////// //~ rjf: Transfer Threads