From d08117e30a52bedff8fced26bc9f12856cba9134 Mon Sep 17 00:00:00 2001 From: capehill <juha.niemimaki@gmail.com> Date: Thu, 10 Oct 2019 20:55:32 +0300 Subject: [PATCH] Tweak timer logic. Now a single CTRL-C signal should quit properly --- main.c | 123 ++++++++++++++++++++++++++++++++++++++------ timer.c | 1 + warp3dnova_module.c | 22 ++++++-- warp3dnova_module.h | 2 +- 4 files changed, 125 insertions(+), 23 deletions(-) diff --git a/main.c b/main.c index bf8ec6f..627511c 100644 --- a/main.c +++ b/main.c @@ -31,9 +31,14 @@ static struct Params params = { 0, 0, 0, 0, NULL, NULL, NULL }; static struct MsgPort* port; +struct Task* mainTask; +BYTE mainSig = -1; + static ULONG startTime; static ULONG duration; +static BOOL running = TRUE; + static BOOL already_running(void) { IExec->Forbid(); @@ -64,6 +69,38 @@ static void remove_port() } } +static void sanitiseParams(void) +{ + if (params.gui) { + // Some of these limitations may be lifted in the future + if (startTime) { + puts("Using STARTTIME with GUI is not possible yet"); + startTime = 0; + } + + if (duration) { + puts("Using DURATION with GUI is not possible yet"); + duration = 0; + } + } + + if (!params.profiling) { + if (startTime) { + puts("STARTTIME is meant to be used with PROFILE"); + startTime = 0; + } + if (duration) { + puts("DURATION is meant to be used with PROFILE"); + duration = 0; + } + } + + if (!params.ogles2 && !params.nova) { + // If user gives nothing, assume everything + params.ogles2 = params.nova = TRUE; + } +} + static BOOL parse_args(void) { const char* const enabled = "enabled"; @@ -93,10 +130,7 @@ static BOOL parse_args(void) return FALSE; } - if (!params.ogles2 && !params.nova) { - // If user gives nothing, assume everything - params.ogles2 = params.nova = TRUE; - } + sanitiseParams(); puts("--- Configuration ---"); printf(" OGLES2 module: [%s]\n", params.ogles2 ? enabled : disabled); @@ -118,7 +152,7 @@ static void install_patches(void) } if (params.nova) { - warp3dnova_install_patches(startTime); + warp3dnova_install_patches(startTime, duration); } } @@ -150,22 +184,33 @@ static void remove_patches(void) ogles2_free(); } -static void waitForStartAndStop() +// When STARTTIME > 0 +static void waitForStartTimer() { const uint32 timerSig = timer_signal(&triggerTimer); - if (timer_wait_for_signal(timerSig, "Start") == ESignalType_Timer) { - puts("First timer signal - start profiling"); + const ESignalType type = timer_wait_for_signal(timerSig, "Start"); + + if (type == ESignalType_Timer) { + puts("Timer signal - start profiling"); timer_handle_events(&triggerTimer); ogles2_start_profiling(); warp3dnova_start_profiling(); + } else if (type == ESignalType_Break) { + running = FALSE; + } +} - if (duration) { - timer_start(&triggerTimer, duration, 0); - puts("Waiting..."); - } +static void waitForEndTimer() +{ + if (running) { + timer_start(&triggerTimer, duration, 0); + + const uint32 timerSig = timer_signal(&triggerTimer); + + puts("Waiting for timer..."); if (timer_wait_for_signal(timerSig, "Stop") == ESignalType_Timer) { puts("Timer signal - stop profiling"); @@ -174,10 +219,41 @@ static void waitForStartAndStop() } } -static void waitForBreakSignal() +static void waitForSignal() +{ + if (running) { + const uint32 sigMask = 1L << mainSig; + const uint32 wait = IExec->Wait(sigMask | SIGBREAKF_CTRL_C); + + if (wait & sigMask) { + puts("Start signal received"); + } + + if (wait & SIGBREAKF_CTRL_C) { + puts("Break signal received"); + running = FALSE; + } + } +} + +static void waitForTimers() { - if (IExec->Wait(SIGBREAKF_CTRL_C)) { - puts("*** Control-C detected ***"); + if (startTime) { + waitForStartTimer(); + } + + if (duration) { + if (!startTime) { + // NOVA module Signal()s us + puts("Waiting for signal..."); + waitForSignal(); + } + + waitForEndTimer(); + } else { + if (startTime) { + waitForSignal(); + } } } @@ -187,9 +263,9 @@ static void run(void) run_gui(params.profiling); } else { if (startTime || duration) { - waitForStartAndStop(); + waitForTimers(); } else { - waitForBreakSignal(); + waitForSignal(); } } } @@ -207,6 +283,8 @@ int main(int argc __attribute__((unused)), char* argv[] __attribute__((unused))) goto out; } + mainTask = IExec->FindTask(NULL); + if (!timer_init(&timer)) { goto out; } @@ -217,6 +295,12 @@ int main(int argc __attribute__((unused)), char* argv[] __attribute__((unused))) } } + mainSig = IExec->AllocSignal(-1); + if (mainSig == -1) { + puts("Failed to allocate signal"); + goto out; + } + create_port(); if (!load_filters(filterFile)) { @@ -239,6 +323,11 @@ int main(int argc __attribute__((unused)), char* argv[] __attribute__((unused))) puts("Patches removed. glSnoop terminating"); out: + if (mainSig != -1) { + IExec->FreeSignal(mainSig); + mainSig = -1; + } + remove_port(); free_filters(); diff --git a/timer.c b/timer.c index 59d7c9d..03a7dbb 100644 --- a/timer.c +++ b/timer.c @@ -166,6 +166,7 @@ void timer_stop(TimerContext * tc) } if (!IExec->CheckIO((struct IORequest *) tc->request)) { + logLine("%s: aborting timer IO request %p", __func__, tc->request); IExec->AbortIO((struct IORequest *) tc->request); IExec->WaitIO((struct IORequest *) tc->request); } diff --git a/warp3dnova_module.c b/warp3dnova_module.c index 4427603..e526301 100644 --- a/warp3dnova_module.c +++ b/warp3dnova_module.c @@ -11,6 +11,9 @@ #include <stdio.h> #include <string.h> +extern BYTE mainSig; +extern struct Task* mainTask; + typedef enum NovaFunction { BindBitMapAsTexture, BindShaderDataBuffer, @@ -248,6 +251,7 @@ static unsigned errorCount; static BOOL profilingStarted = TRUE; static ULONG startTime = 0; +static ULONG duration = 0; static const char* mapNovaError(const W3DN_ErrorCode code) { @@ -2983,10 +2987,17 @@ static W3DN_Context* my_W3DN_CreateContext(struct Warp3DNovaIFace *Self, W3DN_Er patch_context_functions(nova); PROF_INIT(nova, NovaFunctionCount) - logLine("Trigger start timer in %lu seconds", startTime); - // TODO: supports only one app. A proper implementation - // would need a some kind of a timer pool? - timer_start(&triggerTimer, startTime, 0); + if (startTime) { + logLine("Trigger timer in %lu seconds", startTime); + // TODO: supports only one app. A proper implementation + // would need a some kind of a timer pool? + timer_start(&triggerTimer, startTime, 0); + } else { + if (duration) { + logLine("Signal glSnoop task %p with signal %d", mainTask, mainSig); + IExec->Signal(mainTask, 1L << mainSig); + } + } } } else { logAlways("Cannot allocate memory for NOVA context data: cannot patch"); @@ -2999,9 +3010,10 @@ static W3DN_Context* my_W3DN_CreateContext(struct Warp3DNovaIFace *Self, W3DN_Er GENERATE_PATCH(Warp3DNovaIFace, W3DN_CreateContext, my, ContextCreation) -void warp3dnova_install_patches(ULONG startTimeInSeconds) +void warp3dnova_install_patches(ULONG startTimeInSeconds, ULONG durationTimeInSeconds) { startTime = startTimeInSeconds; + duration = durationTimeInSeconds; mutex = IExec->AllocSysObject(ASOT_MUTEX, TAG_DONE); diff --git a/warp3dnova_module.h b/warp3dnova_module.h index 1b6e985..bb8d369 100644 --- a/warp3dnova_module.h +++ b/warp3dnova_module.h @@ -3,7 +3,7 @@ #include <exec/types.h> -void warp3dnova_install_patches(ULONG startTimeInSeconds); +void warp3dnova_install_patches(ULONG startTimeInSeconds, ULONG durationTimeInSeconds); void warp3dnova_remove_patches(void); void warp3dnova_free(void);