diff --git a/src/base/base_entry_point.c b/src/base/base_entry_point.c index 7aa20d7f..3c4b9926 100644 --- a/src/base/base_entry_point.c +++ b/src/base/base_entry_point.c @@ -18,65 +18,62 @@ main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **argum { ProfBeginCapture(arguments[0]); } -#if defined(OS_CORE_H) +#if defined(OS_CORE_H) && !defined(OS_INIT_MANUAL) os_init(); #endif -#if defined(TASK_SYSTEM_H) +#if defined(TASK_SYSTEM_H) && !defined(TS_INIT_MANUAL) ts_init(); #endif -#if defined(HASH_STORE_H) +#if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL) hs_init(); #endif -#if defined(FILE_STREAM_H) +#if defined(FILE_STREAM_H) && !defined(FS_INIT_MANUAL) fs_init(); #endif -#if defined(TEXT_CACHE_H) +#if defined(TEXT_CACHE_H) && !defined(TXT_INIT_MANUAL) txt_init(); #endif -#if defined(DASM_CACHE_H) +#if defined(DASM_CACHE_H) && !defined(DASM_INIT_MANUAL) dasm_init(); #endif -#if defined(DBGI_H) - dbgi_init(); -#endif -#if defined(DI_H) +#if defined(DI_H) && !defined(DI_INIT_MANUAL) di_init(); #endif -#if defined(FUZZY_SEARCH_H) +#if defined(FUZZY_SEARCH_H) && !defined(FZY_INIT_MANUAL) fzy_init(); #endif -#if defined(TXTI_H) +#if defined(TXTI_H) && !defined(TXTI_INIT_MANUAL) txti_init(); #endif -#if defined(DEMON_CORE_H) +#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL) dmn_init(); #endif -#if defined(CTRL_CORE_H) +#if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL) ctrl_init(); #endif -#if defined(OS_GRAPHICAL_H) +#if defined(OS_GRAPHICAL_H) && !defined(OS_GFX_INIT_MANUAL) os_graphical_init(); #endif -#if defined(FONT_PROVIDER_H) +#if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL) fp_init(); #endif -#if defined(RENDER_CORE_H) +#if defined(RENDER_CORE_H) && !defined(R_INIT_MANUAL) r_init(&cmdline); #endif -#if defined(TEXTURE_CACHE_H) +#if defined(TEXTURE_CACHE_H) && !defined(TEX_INIT_MANUAL) tex_init(); #endif -#if defined(GEO_CACHE_H) +#if defined(GEO_CACHE_H) && !defined(GEO_INIT_MANUAL) geo_init(); #endif -#if defined(FONT_CACHE_H) +#if defined(FONT_CACHE_H) && !defined(F_INIT_MANUAL) f_init(); #endif -#if defined(DF_CORE_H) +#if defined(DF_CORE_H) && !defined(DF_INIT_MANUAL) DF_StateDeltaHistory *hist = df_state_delta_history_alloc(); df_core_init(&cmdline, hist); #endif -#if defined(DF_GFX_H) +#if defined(DF_GFX_H) && !defined(DF_GFX_INIT_MANUAL) df_gfx_init(update_and_render, df_state_delta_history()); #endif entry_point(&cmdline); diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 3ba03165..e2980b29 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -6379,6 +6379,7 @@ internal void df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec) { // rjf: log + if(params->os_event == 0 || params->os_event->kind != OS_EventKind_MouseMove) { Temp scratch = scratch_begin(0, 0); DF_Entity *entity = df_entity_from_handle(params->entity); diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index e1a15028..c879873c 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -333,7 +333,7 @@ DF_CoreCmdTable:// | | | {DuplicateEntity 1 Null Nil 0 0 0 0 0 0 Null "duplicate_entity" "Duplicate Entity" "Duplicates an entity." "" } //- rjf: breakpoints - {TextBreakpoint 1 Null Nil 0 0 0 0 0 0 CircleFilled "text_breakpoint" "Text Breakpoint" "Places or removes a breakpoint on the specified line of source code." "" } + {TextBreakpoint 1 FilePath Nil 0 0 0 0 0 0 CircleFilled "text_breakpoint" "Text Breakpoint" "Places or removes a breakpoint on the specified line of source code." "" } {AddressBreakpoint 0 VirtualAddr Nil 0 0 0 0 1 1 CircleFilled "address_breakpoint" "Address Breakpoint" "Places or removes a breakpoint on the specified address." "" } {FunctionBreakpoint 0 String Nil 0 0 0 0 1 1 CircleFilled "function_breakpoint" "Function Breakpoint" "Places or removes a breakpoint on the first address(es) of the specified function." "" } {ToggleBreakpointAtCursor 0 Null Nil 0 0 0 0 0 0 CircleFilled "toggle_breakpoint_cursor" "Toggle Breakpoint At Cursor" "Places or removes a breakpoint on the line on which the active cursor sits." "" } diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index b6edc57a..c2c5f704 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -374,7 +374,7 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[220] = { str8_lit_comp("name_entity"), str8_lit_comp("Equips an entity with a name."), str8_lit_comp(""), str8_lit_comp("Name Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("edit_entity"), str8_lit_comp("Opens the editor for an entity."), str8_lit_comp(""), str8_lit_comp("Edit Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("duplicate_entity"), str8_lit_comp("Duplicates an entity."), str8_lit_comp(""), str8_lit_comp("Duplicate Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, -{ str8_lit_comp("text_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the specified line of source code."), str8_lit_comp(""), str8_lit_comp("Text Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled}, +{ str8_lit_comp("text_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the specified line of source code."), str8_lit_comp(""), str8_lit_comp("Text Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled}, { str8_lit_comp("address_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the specified address."), str8_lit_comp(""), str8_lit_comp("Address Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_VirtualAddr, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CircleFilled}, { str8_lit_comp("function_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the first address(es) of the specified function."), str8_lit_comp(""), str8_lit_comp("Function Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_String, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CircleFilled}, { str8_lit_comp("toggle_breakpoint_cursor"), str8_lit_comp("Places or removes a breakpoint on the line on which the active cursor sits."), str8_lit_comp(""), str8_lit_comp("Toggle Breakpoint At Cursor"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled}, diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 8a0a9511..ee64236b 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -1039,7 +1039,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) ////////////////////////////// //- rjf: unpack context // - B32 window_is_focused = os_window_is_focused(ws->os); + B32 window_is_focused = os_window_is_focused(ws->os) || ws->window_temporarily_focused_ipc; B32 confirm_open = df_gfx_state->confirm_active; B32 query_is_open = !df_view_is_nil(ws->query_view_stack_top); B32 hover_eval_is_open = (!confirm_open && @@ -1050,6 +1050,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) { ws->menu_bar_key_held = 0; } + ws->window_temporarily_focused_ipc = 0; ui_select_state(ws->ui); ////////////////////////////// diff --git a/src/df/gfx/df_gfx.h b/src/df/gfx/df_gfx.h index 59a7c679..60e0f83f 100644 --- a/src/df/gfx/df_gfx.h +++ b/src/df/gfx/df_gfx.h @@ -513,6 +513,7 @@ struct DF_Window UI_State *ui; F32 code_font_size_delta; F32 main_font_size_delta; + B32 window_temporarily_focused_ipc; // rjf: view state delta history DF_StateDeltaHistory *view_state_hist; diff --git a/src/os/core/linux/os_core_linux.c b/src/os/core/linux/os_core_linux.c index f8b07e81..8a6db843 100644 --- a/src/os/core/linux/os_core_linux.c +++ b/src/os/core/linux/os_core_linux.c @@ -1607,7 +1607,7 @@ os_semaphore_close(OS_Handle semaphore) } internal B32 -os_semaphore_take(OS_Handle semaphore) +os_semaphore_take(OS_Handle semaphore, U64 endt_us) { NotImplemented; return 0; diff --git a/src/raddbg/raddbg.c b/src/raddbg/raddbg.c index c0af86cc..2b636d6a 100644 --- a/src/raddbg/raddbg.c +++ b/src/raddbg/raddbg.c @@ -393,7 +393,7 @@ update_and_render(OS_Handle repaint_window_handle, void *user_data) ProfEnd(); } -internal CTRL_WAKEUP_FUNCTION_DEF(wakeup_hook) +internal CTRL_WAKEUP_FUNCTION_DEF(wakeup_hook_ctrl) { os_send_wakeup_event(); } diff --git a/src/raddbg/raddbg.h b/src/raddbg/raddbg.h index 0a870216..c571a6b4 100644 --- a/src/raddbg/raddbg.h +++ b/src/raddbg/raddbg.h @@ -401,12 +401,23 @@ struct IPCInfo //////////////////////////////// //~ rjf: Globals -#define IPC_SHARED_MEMORY_BUFFER_SIZE MB(16) +//- rjf: IPC resources +#define IPC_SHARED_MEMORY_BUFFER_SIZE MB(4) StaticAssert(IPC_SHARED_MEMORY_BUFFER_SIZE > sizeof(IPCInfo), ipc_buffer_size_requirement); -read_only global String8 ipc_shared_memory_name = str8_lit_comp("_raddbg_ipc_shared_memory_"); -read_only global String8 ipc_semaphore_name = str8_lit_comp("_raddbg_ipc_semaphore_"); +global OS_Handle ipc_signal_semaphore = {0}; +global OS_Handle ipc_lock_semaphore = {0}; +global U8 *ipc_shared_memory_base = 0; +global U8 ipc_s2m_ring_buffer[MB(4)] = {0}; +global U64 ipc_s2m_ring_write_pos = 0; +global U64 ipc_s2m_ring_read_pos = 0; +global OS_Handle ipc_s2m_ring_mutex = {0}; +global OS_Handle ipc_s2m_ring_cv = {0}; + +//- rjf: frame time history global U64 frame_time_us_history[64] = {0}; global U64 frame_time_us_history_idx = 0; + +//- rjf: main thread log global Log *main_thread_log = 0; global String8 main_thread_log_path = {0}; diff --git a/src/raddbg/raddbg_main.cpp b/src/raddbg/raddbg_main.cpp index f259abee..280435af 100644 --- a/src/raddbg/raddbg_main.cpp +++ b/src/raddbg/raddbg_main.cpp @@ -11,6 +11,13 @@ #define BUILD_TITLE "The RAD Debugger" #define OS_FEATURE_GRAPHICAL 1 +#define R_INIT_MANUAL 1 +#define TEX_INIT_MANUAL 1 +#define GEO_INIT_MANUAL 1 +#define F_INIT_MANUAL 1 +#define DF_INIT_MANUAL 1 +#define DF_GFX_INIT_MANUAL 1 + //////////////////////////////// //~ rjf: Includes @@ -100,6 +107,42 @@ #include "df/df_inc.c" #include "raddbg.c" +//////////////////////////////// +//~ rjf: IPC Signaler Thread + +internal void +ipc_signaler_thread__entry_point(void *p) +{ + for(;;) + { + if(os_semaphore_take(ipc_signal_semaphore, max_U64)) + { + if(os_semaphore_take(ipc_lock_semaphore, max_U64)) + { + IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; + String8 msg = str8((U8 *)(ipc_info+1), ipc_info->msg_size); + msg.size = Min(msg.size, IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo)); + OS_MutexScope(ipc_s2m_ring_mutex) for(;;) + { + U64 unconsumed_size = ipc_s2m_ring_write_pos - ipc_s2m_ring_read_pos; + U64 available_size = (sizeof(ipc_s2m_ring_buffer) - unconsumed_size); + if(available_size >= sizeof(U64)+sizeof(msg.size)) + { + ipc_s2m_ring_write_pos += ring_write_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, &msg.size); + ipc_s2m_ring_write_pos += ring_write(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, msg.str, msg.size); + break; + } + os_condition_variable_wait(ipc_s2m_ring_cv, ipc_s2m_ring_mutex, max_U64); + } + os_condition_variable_broadcast(ipc_s2m_ring_cv); + os_send_wakeup_event(); + ipc_info->msg_size = 0; + os_semaphore_drop(ipc_lock_semaphore); + } + } + } +} + //////////////////////////////// //~ rjf: Entry Point @@ -178,7 +221,7 @@ entry_point(CmdLine *cmd_line) } //- rjf: set up layers - ctrl_set_wakeup_hook(wakeup_hook); + ctrl_set_wakeup_hook(wakeup_hook_ctrl); //- rjf: dispatch to top-level codepath based on execution mode switch(exec_mode) @@ -187,12 +230,16 @@ entry_point(CmdLine *cmd_line) default: case ExecMode_Normal: { - //- rjf: set up shared memory for ipc - OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name); - void *ipc_shared_memory_base = os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); - OS_Handle ipc_semaphore = os_semaphore_alloc(1, 1, ipc_semaphore_name); - IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; - ipc_info->msg_size = 0; + //- rjf: manual layer initialization + { + r_init(cmd_line); + tex_init(); + geo_init(); + f_init(); + DF_StateDeltaHistory *hist = df_state_delta_history_alloc(); + df_core_init(cmd_line, hist); + df_gfx_init(update_and_render, df_state_delta_history()); + } //- rjf: setup initial target from command line args { @@ -247,56 +294,97 @@ entry_point(CmdLine *cmd_line) } } + //- rjf: set up shared resources for ipc to this instance; launch IPC signaler thread + { + Temp scratch = scratch_begin(0, 0); + U32 instance_pid = os_get_pid(); + String8 ipc_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_shared_memory_%i_", instance_pid); + String8 ipc_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_signal_semaphore_%i_", instance_pid); + String8 ipc_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_lock_semaphore_%i_", instance_pid); + OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name); + ipc_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_signal_semaphore = os_semaphore_alloc(0, 1, ipc_signal_semaphore_name); + ipc_lock_semaphore = os_semaphore_alloc(1, 1, ipc_lock_semaphore_name); + ipc_s2m_ring_mutex = os_mutex_alloc(); + ipc_s2m_ring_cv = os_condition_variable_alloc(); + IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; + MemoryZeroStruct(ipc_info); + os_launch_thread(ipc_signaler_thread__entry_point, 0, 0); + scratch_end(scratch); + } + //- rjf: main application loop { for(;;) { - //- rjf: get IPC messages & dispatch ui commands from them + //- rjf: consume IPC messages, dispatch UI commands { - if(os_semaphore_take(ipc_semaphore, max_U64)) + Temp scratch = scratch_begin(0, 0); + B32 consumed = 0; + String8 msg = {0}; + OS_MutexScope(ipc_s2m_ring_mutex) { - if(ipc_info->msg_size != 0) + U64 unconsumed_size = ipc_s2m_ring_write_pos - ipc_s2m_ring_read_pos; + if(unconsumed_size >= sizeof(U64)) { - U8 *buffer = (U8 *)(ipc_info+1); - U64 msg_size = ipc_info->msg_size; - String8 cmd_string = str8(buffer, msg_size); - ipc_info->msg_size = 0; - DF_Window *dst_window = df_gfx_state->first_window; - for(DF_Window *window = dst_window; window != 0; window = window->next) + consumed = 1; + ipc_s2m_ring_read_pos += ring_read_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, &msg.size); + msg.size = Min(msg.size, unconsumed_size); + msg.str = push_array(scratch.arena, U8, msg.size); + ipc_s2m_ring_read_pos += ring_read(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, msg.str, msg.size); + } + } + if(consumed) + { + os_condition_variable_broadcast(ipc_s2m_ring_cv); + } + if(msg.size != 0) + { + log_infof("IPC message received: \"%S\"", msg); + DF_Window *dst_window = df_gfx_state->first_window; + for(DF_Window *window = dst_window; window != 0; window = window->next) + { + if(os_window_is_focused(window->os)) { - if(os_window_is_focused(window->os)) - { - dst_window = window; - break; - } - } - if(dst_window != 0) - { - Temp scratch = scratch_begin(0, 0); - String8 cmd_spec_string = df_cmd_name_part_from_string(cmd_string); - DF_CmdSpec *cmd_spec = df_cmd_spec_from_string(cmd_spec_string); - if(!df_cmd_spec_is_nil(cmd_spec)) - { - DF_CmdParams params = df_cmd_params_from_gfx(); - DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_window(dst_window); - String8 error = df_cmd_params_apply_spec_query(scratch.arena, &ctrl_ctx, ¶ms, cmd_spec, df_cmd_arg_part_from_string(cmd_string)); - if(error.size == 0) - { - df_push_cmd__root(¶ms, cmd_spec); - } - else - { - DF_CmdParams params = df_cmd_params_from_window(dst_window); - params.string = error; - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_String); - df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error)); - } - } - scratch_end(scratch); + dst_window = window; + break; + } + } + if(dst_window != 0) + { + dst_window->window_temporarily_focused_ipc = 1; + String8 cmd_spec_string = df_cmd_name_part_from_string(msg); + DF_CmdSpec *cmd_spec = df_cmd_spec_from_string(cmd_spec_string); + if(!df_cmd_spec_is_nil(cmd_spec)) + { + DF_CmdParams params = df_cmd_params_from_window(dst_window); + DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_window(dst_window); + String8 error = df_cmd_params_apply_spec_query(scratch.arena, &ctrl_ctx, ¶ms, cmd_spec, df_cmd_arg_part_from_string(msg)); + if(error.size == 0) + { + df_push_cmd__root(¶ms, cmd_spec); + df_gfx_request_frame(); + } + else + { + DF_CmdParams params = df_cmd_params_from_window(dst_window); + params.string = error; + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_String); + df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error)); + df_gfx_request_frame(); + } + } + else + { + DF_CmdParams params = df_cmd_params_from_window(dst_window); + params.string = push_str8f(scratch.arena, "\"%S\" is not a command.", cmd_spec_string); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_String); + df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error)); + df_gfx_request_frame(); } } - os_semaphore_drop(ipc_semaphore); } + scratch_end(scratch); } //- rjf: update & render frame @@ -344,25 +432,61 @@ entry_point(CmdLine *cmd_line) { Temp scratch = scratch_begin(0, 0); - //- rjf: grab ipc shared memory - OS_Handle ipc_shared_memory = os_shared_memory_open(ipc_shared_memory_name); - void *ipc_shared_memory_base = os_shared_memory_view_open(ipc_shared_memory, r1u64(0, MB(16))); - if(ipc_shared_memory_base != 0) + //- rjf: grab explicit PID argument + U32 dst_pid = 0; + if(cmd_line_has_argument(cmd_line, str8_lit("pid"))) { - OS_Handle ipc_semaphore = os_semaphore_open(ipc_semaphore_name); - IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; - if(os_semaphore_take(ipc_semaphore, os_now_microseconds() + Million(6))) + String8 dst_pid_string = cmd_line_string(cmd_line, str8_lit("pid")); + U64 dst_pid_u64 = 0; + if(dst_pid_string.size != 0 && + try_u64_from_str8_c_rules(dst_pid_string, &dst_pid_u64)) { - U8 *buffer = (U8 *)(ipc_info+1); - U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo); - StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")}; - String8 msg = str8_list_join(scratch.arena, &cmd_line->inputs, &join); - ipc_info->msg_size = Min(buffer_max, msg.size); - MemoryCopy(buffer, msg.str, ipc_info->msg_size); - os_semaphore_drop(ipc_semaphore); + dst_pid = (U32)dst_pid_u64; } } + //- rjf: no explicit PID? -> find PID to send message to, by looking for other raddbg instances + if(dst_pid == 0) + { + U32 this_pid = os_get_pid(); + DMN_ProcessIter it = {0}; + dmn_process_iter_begin(&it); + for(DMN_ProcessInfo info = {0}; dmn_process_iter_next(scratch.arena, &it, &info);) + { + if(str8_match(str8_skip_last_slash(str8_chop_last_dot(cmd_line->exe_name)), str8_skip_last_slash(str8_chop_last_dot(info.name)), StringMatchFlag_CaseInsensitive) && + this_pid != info.pid) + { + dst_pid = info.pid; + break; + } + } + dmn_process_iter_end(&it); + } + + //- rjf: grab destination instance's shared memory resources + String8 ipc_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_shared_memory_%i_", dst_pid); + String8 ipc_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_signal_semaphore_%i_", dst_pid); + String8 ipc_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_lock_semaphore_%i_", dst_pid); + OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name); + ipc_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_signal_semaphore = os_semaphore_alloc(0, 1, ipc_signal_semaphore_name); + ipc_lock_semaphore = os_semaphore_alloc(1, 1, ipc_lock_semaphore_name); + + //- rjf: got resources -> write message + if(ipc_shared_memory_base != 0 && + os_semaphore_take(ipc_lock_semaphore, max_U64)) + { + IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; + U8 *buffer = (U8 *)(ipc_info+1); + U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo); + StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")}; + String8 msg = str8_list_join(scratch.arena, &cmd_line->inputs, &join); + ipc_info->msg_size = Min(buffer_max, msg.size); + MemoryCopy(buffer, msg.str, ipc_info->msg_size); + os_semaphore_drop(ipc_signal_semaphore); + os_semaphore_drop(ipc_lock_semaphore); + } + scratch_end(scratch); }break;