diff --git a/src/base/base_entry_point.c b/src/base/base_entry_point.c index d17dd15b..5037dbde 100644 --- a/src/base/base_entry_point.c +++ b/src/base/base_entry_point.c @@ -71,6 +71,9 @@ main_thread_base_entry_point(int arguments_count, char **arguments) #if defined(DBG_INFO_H) && !defined(DI_INIT_MANUAL) di_init(); #endif +#if defined(DBG_INFO2_H) && !defined(DI_INIT_MANUAL) + di2_init(); +#endif #if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL) dmn_init(); #endif @@ -205,6 +208,9 @@ async_thread_entry_point(void *params) #endif #if defined(FILE_STREAM_H) fs_async_tick(); +#endif +#if defined(DBG_INFO2_H) + di2_async_tick(); #endif } diff --git a/src/dbg_info/dbg_info.c b/src/dbg_info/dbg_info.c index aff0da46..07a10bd5 100644 --- a/src/dbg_info/dbg_info.c +++ b/src/dbg_info/dbg_info.c @@ -1040,7 +1040,7 @@ ASYNC_WORK_DEF(di_parse_work) U64 start_wait_t = os_now_microseconds(); for(;;) { - B32 wait_done = os_process_join(process, os_now_microseconds()+1000); + B32 wait_done = os_process_join(process, os_now_microseconds()+1000, 0); if(wait_done) { rdi_file_is_up_to_date = 1; diff --git a/src/dbg_info/dbg_info2.c b/src/dbg_info/dbg_info2.c new file mode 100644 index 00000000..604adb75 --- /dev/null +++ b/src/dbg_info/dbg_info2.c @@ -0,0 +1,528 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Helpers + +internal DI2_Key +di2_key_zero(void) +{ + DI2_Key key = {0}; + return key; +} + +internal B32 +di2_key_match(DI2_Key a, DI2_Key b) +{ + B32 result = MemoryMatchStruct(&a, &b); + return result; +} + +//////////////////////////////// +//~ rjf: Main Layer Initialization + +internal void +di2_init(void) +{ + Arena *arena = arena_alloc(); + di2_shared = push_array(arena, DI2_Shared, 1); + di2_shared->arena = arena; + di2_shared->key_slots_count = 4096; + di2_shared->key_slots = push_array(arena, DI2_KeySlot, di2_shared->key_slots_count); + di2_shared->key_stripes = stripe_array_alloc(arena); + di2_shared->key_path_slots_count = 4096; + di2_shared->key_path_slots = push_array(arena, DI2_KeySlot, di2_shared->key_path_slots_count); + di2_shared->key_path_stripes = stripe_array_alloc(arena); + di2_shared->slots_count = 4096; + di2_shared->slots = push_array(arena, DI2_Slot, di2_shared->slots_count); + di2_shared->stripes = stripe_array_alloc(arena); + for EachElement(idx, di2_shared->req_batches) + { + di2_shared->req_batches[idx].mutex = mutex_alloc(); + di2_shared->req_batches[idx].arena = arena_alloc(); + } +} + +//////////////////////////////// +//~ rjf: Path * Timestamp Cache Submission & Lookup + +internal DI2_Key +di2_key_from_path_timestamp(String8 path, U64 min_timestamp) +{ + //- rjf: unpack key + U64 hash = u64_hash_from_str8(path); + U64 slot_idx = hash%di2_shared->key_slots_count; + DI2_KeySlot *slot = &di2_shared->key_slots[slot_idx]; + Stripe *stripe = stripe_from_slot_idx(&di2_shared->key_stripes, slot_idx); + + //- rjf: look up key, create if needed + DI2_Key key = {0}; + for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) + { + // rjf: look up node, with this write mode, to find existing key computation + B32 found = 0; + RWMutexScope(stripe->rw_mutex, write_mode) + { + DI2_KeyNode *node = 0; + for(DI2_KeyNode *n = slot->first; n != 0; n = n->next) + { + if(str8_match(n->path, path, 0) && min_timestamp <= n->min_timestamp) + { + found = 1; + node = n; + key = node->key; + break; + } + } + if(!found && write_mode) + { + node = stripe->free; + if(node) + { + stripe->free = node->next; + } + else + { + node = push_array(stripe->arena, DI2_KeyNode, 1); + } + node->path = str8_copy(stripe->arena, path); + node->min_timestamp = min_timestamp; + node->key = key; + DLLPushBack(slot->first, slot->last, node); + } + } + + // rjf: found the key? abort + if(found) + { + break; + } + + // rjf: didn't find the key on our read lookup? compute the key before entering + // write mode + if(!found && !write_mode) + { + B32 made_key = 0; + + //- rjf: try to make key from file's contents + if(!made_key) + { + OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path); + FileProperties props = os_properties_from_file(file); + if(min_timestamp <= props.modified) + { + //- rjf: PDB magic => use GUID for key + if(!made_key) + { + B32 is_pdb = 0; + if(!is_pdb) + { + U8 msf20_magic_maybe[sizeof(msf_msf20_magic)] = {0}; + os_file_read(file, r1u64(0, sizeof(msf20_magic_maybe)), msf20_magic_maybe); + if(MemoryMatch(msf20_magic_maybe, msf_msf20_magic, sizeof(msf20_magic_maybe))) + { + is_pdb = 1; + } + } + if(!is_pdb) + { + U8 msf70_magic_maybe[sizeof(msf_msf70_magic)] = {0}; + os_file_read(file, r1u64(0, sizeof(msf70_magic_maybe)), msf70_magic_maybe); + if(MemoryMatch(msf70_magic_maybe, msf_msf70_magic, sizeof(msf70_magic_maybe))) + { + is_pdb = 1; + } + } + if(is_pdb) + { + // TODO(rjf) + } + } + } + os_file_close(file); + } + + //- rjf: fallback: hash from path/timestamp + if(!made_key) + { + made_key = 1; + U128 hash = u128_hash_from_seed_str8(min_timestamp, path); + MemoryCopy(&key, &hash, Min(sizeof(hash), sizeof(key))); + } + + //- rjf: made key -> store in (key -> path/timestamp) table + if(made_key) + { + U64 key_hash = u64_hash_from_str8(str8_struct(&key)); + U64 key_slot_idx = key_hash%di2_shared->key_path_slots_count; + DI2_KeySlot *key_slot = &di2_shared->key_path_slots[key_slot_idx]; + Stripe *key_stripe = stripe_from_slot_idx(&di2_shared->key_path_stripes, key_slot_idx); + RWMutexScope(key_stripe->rw_mutex, 1) + { + DI2_KeyNode *node = 0; + for EachNode(n, DI2_KeyNode, key_slot->first) + { + if(di2_key_match(n->key, key)) + { + node = n; + break; + } + } + if(node == 0) + { + node = key_stripe->free; + if(node != 0) + { + key_stripe->free = node->next; + } + else + { + node = push_array(key_stripe->arena, DI2_KeyNode, 1); + } + DLLPushBack(key_slot->first, key_slot->last, node); + node->path = str8_copy(key_stripe->arena, path); + node->min_timestamp = min_timestamp; + node->key = key; + } + } + } + } + } + + return key; +} + +//////////////////////////////// +//~ rjf: Debug Info Opening / Closing + +internal void +di2_open(DI2_Key key) +{ + DI2_RequestBatch *batch = &di2_shared->req_batches[1]; + MutexScope(batch->mutex) + { + DI2_RequestNode *n = push_array(batch->arena, DI2_RequestNode, 1); + SLLQueuePush(batch->first, batch->last, n); + n->v.key = key; + batch->count += 1; + } +} + +internal void +di2_close(DI2_Key key) +{ + // TODO(rjf) +} + +//////////////////////////////// +//~ rjf: Debug Info Lookups + +internal RDI_Parsed * +di2_rdi_from_key(Access *access, DI2_Key key, B32 high_priority, U64 endt_us) +{ + RDI_Parsed *rdi = &rdi_parsed_nil; + { + // TODO(rjf) + } + return rdi; +} + +//////////////////////////////// +//~ rjf: Asynchronous Tick + +internal void +di2_async_tick(void) +{ + Temp scratch = scratch_begin(0, 0); + + ////////////////////////////// + //- rjf: do single-lane update: pop requests, update tasks, gather RDI paths to parse wide + // + typedef struct ParseTask ParseTask; + struct ParseTask + { + DI2_Key key; + String8 rdi_path; + }; + ParseTask *parse_tasks = 0; + U64 parse_tasks_count = 0; + if(lane_idx() == 0) + { + typedef struct ParseTaskNode ParseTaskNode; + struct ParseTaskNode + { + ParseTaskNode *next; + ParseTask v; + }; + ParseTaskNode *first_parse_task = 0; + ParseTaskNode *last_parse_task = 0; + + //////////////////////////// + //- rjf: pop requests, high priority first, and generate conversion tasks for them + // + for EachElement(idx, di2_shared->req_batches) + { + DI2_RequestBatch *b = &di2_shared->req_batches[idx]; + MutexScope(b->mutex) + { + for EachNode(n, DI2_RequestNode, b->first) + { + DI2_LoadTask *t = di2_shared->free_load_task; + if(t) + { + SLLStackPop(di2_shared->free_load_task); + } + else + { + t = push_array_no_zero(di2_shared->arena, DI2_LoadTask, 1); + } + MemoryZeroStruct(t); + DLLPushBack(di2_shared->first_load_task, di2_shared->last_load_task, t); + t->key = n->v.key; + } + arena_clear(b->arena); + b->first = b->last = 0; + b->count = 0; + } + } + + //////////////////////////// + //- rjf: update tasks: configure, launch if we can, & retire if we can + // + for(DI2_LoadTask *t = di2_shared->first_load_task, *next = 0; t != 0; t = next) + { + next = t->next; + + //- rjf: unpack key + DI2_Key key = t->key; + U64 key_hash = u64_hash_from_str8(str8_struct(&key)); + U64 key_slot_idx = key_hash%di2_shared->key_slots_count; + DI2_KeySlot *key_slot = &di2_shared->key_slots[key_slot_idx]; + Stripe *key_stripe = stripe_from_slot_idx(&di2_shared->key_stripes, key_slot_idx); + + //- rjf: get key's O.G. path + String8 og_path = {0}; + U64 og_min_timestamp = 0; + RWMutexScope(key_stripe->rw_mutex, 0) + { + for(DI2_KeyNode *n = key_slot->first; n != 0; n = n->next) + { + if(di2_key_match(n->key, key)) + { + og_path = str8_copy(scratch.arena, n->path); + og_min_timestamp = n->min_timestamp; + break; + } + } + } + + //- rjf: analyze O.G. debug info + if(!t->og_analyzed) + { + t->og_analyzed = 1; + OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, og_path); + FileProperties props = os_properties_from_file(file); + t->og_size = props.size; + U64 rdi_magic_maybe = 0; + if(os_file_read_struct(file, 0, &rdi_magic_maybe) == 8 && + rdi_magic_maybe == RDI_MAGIC_CONSTANT) + { + t->og_is_rdi = 1; + } + os_file_close(file); + } + U64 og_size = t->og_size; + B32 og_is_rdi = t->og_is_rdi; + + //- rjf: compute key's RDI path + String8 rdi_path = {0}; + { + if(og_is_rdi) + { + rdi_path = og_path; + } + else + { + rdi_path = str8f(scratch.arena, "%S.rdi", str8_chop_last_dot(og_path)); + } + } + + //- rjf: determine if RDI is stale + if(!t->rdi_analyzed) + { + t->rdi_analyzed = 1; + OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, rdi_path); + FileProperties props = os_properties_from_file(file); + if(props.modified < og_min_timestamp) + { + t->rdi_is_stale = 1; + } + else + { + t->rdi_is_stale = 1; + RDI_Header header = {0}; + if(os_file_read_struct(file, 0, &header) == sizeof(header)) + { + t->rdi_is_stale = (header.encoding_version != RDI_ENCODING_VERSION); + } + } + os_file_close(file); + } + B32 rdi_is_stale = t->rdi_is_stale; + + //- rjf: calculate thread counts for conversion processes + if(!og_is_rdi && rdi_is_stale && t->thread_count == 0) + { + U64 thread_count = 1; + U64 max_thread_count = os_get_system_info()->logical_processor_count; + { + if(0){} + else if(og_size <= MB(4)) {thread_count = 1;} + else if(og_size <= MB(256)) {thread_count = max_thread_count/4;} + else if(og_size <= MB(512)) {thread_count = max_thread_count/2;} + else {thread_count = max_thread_count;} + } + thread_count = Max(1, thread_count); + t->thread_count = thread_count; + } + + //- rjf: launch conversion processes + if(!og_is_rdi && rdi_is_stale && t->thread_count != 0 && t->status != DI2_LoadTaskStatus_Active) + { + B32 should_compress = 0; + OS_ProcessLaunchParams params = {0}; + params.path = os_get_process_info()->binary_path; + params.inherit_env = 1; + params.consoleless = 1; + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "raddbg"); + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--bin"); + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--quiet"); + if(should_compress) + { + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--compress"); + } + // str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--capture"); + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--rdi"); + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--out:%S", rdi_path); + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--thread_count:%I64u", t->thread_count); + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "%S", og_path); + t->process = os_process_launch(¶ms); + t->status = DI2_LoadTaskStatus_Active; + di2_shared->conversion_process_count += 1; + di2_shared->conversion_thread_count += t->thread_count; + } + + //- rjf: if active & process has completed, mark as done + { + U64 exit_code = 0; + if(t->status == DI2_LoadTaskStatus_Active && os_process_join(t->process, 0, &exit_code)) + { + t->status = DI2_LoadTaskStatus_Done; + } + } + + //- rjf: if the RDI for this task is not stale, then we're already done - mark this + // task as done & prepped for storing into the cache + if(!rdi_is_stale) + { + t->status = DI2_LoadTaskStatus_Done; + } + + //- rjf: if task is done, retire & recycle task; gather path to load + if(t->status == DI2_LoadTaskStatus_Done) + { + DLLRemove(di2_shared->first_load_task, di2_shared->last_load_task, t); + SLLStackPush(di2_shared->free_load_task, t); + di2_shared->conversion_process_count -= 1; + di2_shared->conversion_thread_count -= t->thread_count; + ParseTaskNode *n = push_array(scratch.arena, ParseTaskNode, 1); + n->v.key = key; + n->v.rdi_path = rdi_path; + SLLQueuePush(first_parse_task, last_parse_task, n); + parse_tasks_count += 1; + } + } + + //////////////////////////// + //- rjf: join all parse tasks + // + parse_tasks = push_array(scratch.arena, ParseTask, parse_tasks_count); + { + U64 idx = 0; + for EachNode(n, ParseTaskNode, first_parse_task) + { + parse_tasks[idx] = n->v; + idx += 1; + } + } + } + lane_sync(); + + ////////////////////////////// + //- rjf: do wide load of all prepped RDIs + // + U64 parse_task_take_counter = 0; + U64 *parse_task_take_counter_ptr = 0; + if(lane_idx() == 0) + { + parse_task_take_counter_ptr = &parse_task_take_counter; + } + lane_sync_u64(&parse_task_take_counter_ptr, 0); + { + for(;;) + { + //- rjf: take next task + U64 parse_task_idx = ins_atomic_u64_inc_eval(parse_task_take_counter_ptr); + if(parse_task_idx >= parse_tasks_count) + { + break; + } + + //- rjf: unpack task + DI2_Key key = parse_tasks[parse_task_idx].key; + String8 rdi_path = parse_tasks[parse_task_idx].rdi_path; + + //- rjf: open file + OS_Handle file = {0}; + OS_Handle file_map = {0}; + FileProperties file_props = {0}; + void *file_base = 0; + { + file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite, rdi_path); + file_map = os_file_map_open(OS_AccessFlag_Read, file); + file_props = os_properties_from_file(file); + file_base = os_file_map_view_open(file_map, OS_AccessFlag_Read, r1u64(0, file_props.size)); + } + + //- rjf: do initial parse of rdi + RDI_Parsed rdi_parsed_maybe_compressed = rdi_parsed_nil; + { + RDI_ParseStatus parse_status = rdi_parse((U8 *)file_base, file_props.size, &rdi_parsed_maybe_compressed); + (void)parse_status; + } + + //- rjf: decompress & re-parse, if necessary + Arena *rdi_parsed_arena = 0; + RDI_Parsed rdi_parsed = rdi_parsed_maybe_compressed; + { + U64 decompressed_size = rdi_decompressed_size_from_parsed(&rdi_parsed_maybe_compressed); + if(decompressed_size > file_props.size) + { + rdi_parsed_arena = arena_alloc(); + U8 *decompressed_data = push_array_no_zero(rdi_parsed_arena, U8, decompressed_size); + rdi_decompress_parsed(decompressed_data, decompressed_size, &rdi_parsed_maybe_compressed); + RDI_ParseStatus parse_status = rdi_parse(decompressed_data, decompressed_size, &rdi_parsed); + (void)parse_status; + } + } + + //- rjf: commit parsed info to cache + { + // TODO(rjf) + } + } + } + lane_sync(); + + scratch_end(scratch); +} diff --git a/src/dbg_info/dbg_info2.h b/src/dbg_info/dbg_info2.h new file mode 100644 index 00000000..01f5b0ab --- /dev/null +++ b/src/dbg_info/dbg_info2.h @@ -0,0 +1,199 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef DBG_INFO2_H +#define DBG_INFO2_H + +//////////////////////////////// +//~ rjf: Unique Debug Info Key + +typedef struct DI2_Key DI2_Key; +struct DI2_Key +{ + U64 u64[2]; +}; + +//////////////////////////////// +//~ rjf: Debug Info Path / Timestamp => Key Cache Types + +typedef struct DI2_KeyNode DI2_KeyNode; +struct DI2_KeyNode +{ + DI2_KeyNode *next; + DI2_KeyNode *prev; + String8 path; + U64 min_timestamp; + DI2_Key key; +}; + +typedef struct DI2_KeySlot DI2_KeySlot; +struct DI2_KeySlot +{ + DI2_KeyNode *first; + DI2_KeyNode *last; +}; + +//////////////////////////////// +//~ rjf: Debug Info Cache Types + +typedef struct DI2_Node DI2_Node; +struct DI2_Node +{ + // rjf: links + DI2_Node *next; + DI2_Node *prev; + + // rjf: metadata + AccessPt access_pt; + U64 refcount; + U64 working_count; + U64 completion_count; + + // rjf: key + DI2_Key key; + + // rjf: value + OS_Handle file; + OS_Handle file_map; + void *file_base; + FileProperties file_props; + Arena *arena; + RDI_Parsed rdi; +}; + +typedef struct DI2_Slot DI2_Slot; +struct DI2_Slot +{ + DI2_Node *first; + DI2_Node *last; +}; + +//////////////////////////////// +//~ rjf: Requests + +typedef struct DI2_Request DI2_Request; +struct DI2_Request +{ + DI2_Key key; +}; + +typedef struct DI2_RequestNode DI2_RequestNode; +struct DI2_RequestNode +{ + DI2_RequestNode *next; + DI2_Request v; +}; + +typedef struct DI2_RequestBatch DI2_RequestBatch; +struct DI2_RequestBatch +{ + Mutex mutex; + Arena *arena; + DI2_RequestNode *first; + DI2_RequestNode *last; + U64 count; +}; + +//////////////////////////////// +//~ rjf: Load Tasks + +typedef enum DI2_LoadTaskStatus +{ + DI2_LoadTaskStatus_Null, + DI2_LoadTaskStatus_Active, + DI2_LoadTaskStatus_Done, +} +DI2_LoadTaskStatus; + +typedef struct DI2_LoadTask DI2_LoadTask; +struct DI2_LoadTask +{ + DI2_LoadTask *next; + DI2_LoadTask *prev; + + DI2_Key key; + DI2_LoadTaskStatus status; + + B32 og_analyzed; + B32 og_is_rdi; + U64 og_size; + + B32 rdi_analyzed; + B32 rdi_is_stale; + + U64 thread_count; + OS_Handle process; +}; + +//////////////////////////////// +//~ rjf: Shared State + +typedef struct DI2_Shared DI2_Shared; +struct DI2_Shared +{ + Arena *arena; + + // rjf: key -> path cache + U64 key_slots_count; + DI2_KeySlot *key_slots; + StripeArray key_stripes; + + // rjf: path -> key cache + U64 key_path_slots_count; + DI2_KeySlot *key_path_slots; + StripeArray key_path_stripes; + + // rjf: debug info cache + U64 slots_count; + DI2_Slot *slots; + StripeArray stripes; + + // rjf: requests + DI2_RequestBatch req_batches[2]; // [0] -> high priority, [1] -> low priority + + // rjf: conversion tasks + DI2_LoadTask *first_load_task; + DI2_LoadTask *last_load_task; + DI2_LoadTask *free_load_task; + U64 conversion_process_count; + U64 conversion_thread_count; +}; + +//////////////////////////////// +//~ rjf: Globals + +global DI2_Shared *di2_shared = 0; + +//////////////////////////////// +//~ rjf: Helpers + +internal DI2_Key di2_key_zero(void); +internal B32 di2_key_match(DI2_Key a, DI2_Key b); + +//////////////////////////////// +//~ rjf: Main Layer Initialization + +internal void di2_init(void); + +//////////////////////////////// +//~ rjf: Path * Timestamp Cache Submission & Lookup + +internal DI2_Key di2_key_from_path_timestamp(String8 path, U64 timestamp); + +//////////////////////////////// +//~ rjf: Debug Info Opening / Closing + +internal void di2_open(DI2_Key key); +internal void di2_close(DI2_Key key); + +//////////////////////////////// +//~ rjf: Debug Info Lookups + +internal RDI_Parsed *di2_rdi_from_key(Access *access, DI2_Key key, B32 high_priority, U64 endt_us); + +//////////////////////////////// +//~ rjf: Asynchronous Tick + +internal void di2_async_tick(void); + +#endif // DBG_INFO2_H diff --git a/src/os/core/linux/os_core_linux.c b/src/os/core/linux/os_core_linux.c index 9e01d5ef..8a22f460 100644 --- a/src/os/core/linux/os_core_linux.c +++ b/src/os/core/linux/os_core_linux.c @@ -774,13 +774,13 @@ os_process_launch(OS_ProcessLaunchParams *params) } internal B32 -os_process_join(OS_Handle handle, U64 endt_us) +os_process_join(OS_Handle handle, U64 endt_us, U64 *exit_code_out) { NotImplemented; } -internal B32 -os_process_join_exit_code(OS_Handle handle, U64 endt_us, int *exit_code_out) +internal U64 +os_process_array_join(OS_HandleArray processes, U64 endt_us, U64 *exit_code_out) { NotImplemented; } diff --git a/src/os/core/os_core.h b/src/os/core/os_core.h index 317f1d05..2731228f 100644 --- a/src/os/core/os_core.h +++ b/src/os/core/os_core.h @@ -244,8 +244,7 @@ internal void os_sleep_milliseconds(U32 msec); //~ rjf: @os_hooks Child Processes (Implemented Per-OS) internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params); -internal B32 os_process_join(OS_Handle handle, U64 endt_us); -internal B32 os_process_join_exit_code(OS_Handle handle, U64 endt_us, int *exit_code_out); +internal B32 os_process_join(OS_Handle handle, U64 endt_us, U64 *exit_code_out); internal void os_process_detach(OS_Handle handle); internal B32 os_process_kill(OS_Handle handle); diff --git a/src/os/core/win32/os_core_win32.c b/src/os/core/win32/os_core_win32.c index 0e29fad9..d91b8088 100644 --- a/src/os/core/win32/os_core_win32.c +++ b/src/os/core/win32/os_core_win32.c @@ -1061,28 +1061,21 @@ os_process_launch(OS_ProcessLaunchParams *params) } internal B32 -os_process_join(OS_Handle handle, U64 endt_us) +os_process_join(OS_Handle handle, U64 endt_us, U64 *exit_code_out) { HANDLE process = (HANDLE)(handle.u64[0]); DWORD sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); DWORD result = WaitForSingleObject(process, sleep_ms); - return (result == WAIT_OBJECT_0); -} - -internal B32 -os_process_join_exit_code(OS_Handle handle, U64 endt_us, int *exit_code_out) -{ - B32 result = 0; - if(os_process_join(handle, endt_us)) + B32 process_joined = (result == WAIT_OBJECT_0); + if(process_joined && exit_code_out) { - DWORD exit_code; - if(GetExitCodeProcess((HANDLE)handle.u64[0], &exit_code)) + DWORD exit_code = 0; + if(GetExitCodeProcess(process, &exit_code)) { *exit_code_out = exit_code; - result = 1; } } - return result; + return process_joined; } internal B32 diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index a835cc51..14af7b95 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -249,6 +249,7 @@ #include "regs/regs.h" #include "regs/rdi/regs_rdi.h" #include "dbg_info/dbg_info.h" +#include "dbg_info/dbg_info2.h" #include "disasm/disasm.h" #include "demon/demon_inc.h" #include "eval/eval_inc.h" @@ -296,6 +297,7 @@ #include "regs/regs.c" #include "regs/rdi/regs_rdi.c" #include "dbg_info/dbg_info.c" +#include "dbg_info/dbg_info2.c" #include "disasm/disasm.c" #include "demon/demon_inc.c" #include "eval/eval_inc.c" diff --git a/src/tester/tester_main.c b/src/tester/tester_main.c index b221159e..4ee85062 100644 --- a/src/tester/tester_main.c +++ b/src/tester/tester_main.c @@ -114,7 +114,7 @@ for(Test *test = test_##name_identifier; test != 0; test = 0) } for(OS_HandleNode *n = processes.first; n != 0; n = n->next) { - os_process_join(n->v, max_U64); + os_process_join(n->v, max_U64, 0); } } @@ -130,7 +130,7 @@ for(Test *test = test_##name_identifier; test != 0; test = 0) } for(OS_HandleNode *n = processes.first; n != 0; n = n->next) { - os_process_join(n->v, max_U64); + os_process_join(n->v, max_U64, 0); } } diff --git a/src/torture/torture.c b/src/torture/torture.c index 78951f77..ab845134 100644 --- a/src/torture/torture.c +++ b/src/torture/torture.c @@ -142,7 +142,9 @@ t_invoke_linker_with_time_out(U64 time_out, String8 cmdline) if (os_handle_match(linker_handle, os_handle_zero())) { fprintf(stderr, "unable to start process: %.*s\n", str8_varg(g_linker)); } else { - B32 was_joined = os_process_join_exit_code(linker_handle, time_out, &exit_code); + U64 exit_code_u64 = 0; + B32 was_joined = os_process_join(linker_handle, time_out, &exit_code_u64); + exit_code = (int)exit_code_u64; if (!was_joined) { os_process_kill(linker_handle); exit_code = T_LINKER_TIME_OUT_EXIT_CODE; @@ -4428,8 +4430,8 @@ t_import_kernel32(void) str8_list_pushf(scratch.arena, &launch_opts.cmd_line, "%S/a.exe", g_wdir); OS_Handle handle = os_process_launch(&launch_opts); AssertAlways(!os_handle_match(handle, os_handle_zero())); - int exit_code = -1; - os_process_join_exit_code(handle, max_U64, &exit_code); + U64 exit_code = max_U64; + os_process_join(handle, max_U64, &exit_code); os_process_detach(handle); if (exit_code != 0) { goto exit; }