summaryrefslogtreecommitdiffstats
path: root/firmware/target/hosted/sdl/kernel-sdl.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/sdl/kernel-sdl.c')
-rw-r--r--firmware/target/hosted/sdl/kernel-sdl.c62
1 files changed, 58 insertions, 4 deletions
diff --git a/firmware/target/hosted/sdl/kernel-sdl.c b/firmware/target/hosted/sdl/kernel-sdl.c
index d933b9097e..4fb1aede0a 100644
--- a/firmware/target/hosted/sdl/kernel-sdl.c
+++ b/firmware/target/hosted/sdl/kernel-sdl.c
@@ -34,6 +34,14 @@
static SDL_TimerID tick_timer_id;
long start_tick;
+#ifndef HAVE_SDL_THREADS
+/* for the wait_for_interrupt function */
+static bool do_exit;
+static SDL_cond *wfi_cond;
+static SDL_mutex *wfi_mutex;
+#else
+#define do_exit false
+#endif
/* Condition to signal that "interrupts" may proceed */
static SDL_cond *sim_thread_cond;
/* Mutex to serialize changing levels and exclude other threads while
@@ -98,6 +106,9 @@ void sim_exit_irq_handler(void)
status_reg = 0;
SDL_UnlockMutex(sim_irq_mtx);
+#ifndef HAVE_SDL_THREADS
+ SDL_CondSignal(wfi_cond);
+#endif
}
static bool sim_kernel_init(void)
@@ -115,15 +126,33 @@ static bool sim_kernel_init(void)
panicf("Cannot create sim_thread_cond\n");
return false;
}
-
+#ifndef HAVE_SDL_THREADS
+ wfi_cond = SDL_CreateCond();
+ if (wfi_cond == NULL)
+ {
+ panicf("Cannot create wfi\n");
+ return false;
+ }
+ wfi_mutex = SDL_CreateMutex();
+ if (wfi_mutex == NULL)
+ {
+ panicf("Cannot create wfi mutex\n");
+ return false;
+ }
+#endif
return true;
}
void sim_kernel_shutdown(void)
{
SDL_RemoveTimer(tick_timer_id);
+#ifndef HAVE_SDL_THREADS
+ do_exit = true;
+ SDL_CondSignal(wfi_cond);
+#endif
+ disable_irq();
SDL_DestroyMutex(sim_irq_mtx);
- SDL_DestroyCond(sim_thread_cond);
+ SDL_DestroyCond(sim_thread_cond);
}
Uint32 tick_timer(Uint32 interval, void *param)
@@ -135,7 +164,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ);
- while(new_tick != current_tick)
+ while(new_tick != current_tick && !do_exit)
{
sim_enter_irq_handler();
@@ -146,7 +175,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
sim_exit_irq_handler();
}
- return interval;
+ return do_exit ? 0 : interval;
}
void tick_start(unsigned int interval_in_ms)
@@ -168,4 +197,29 @@ void tick_start(unsigned int interval_in_ms)
}
tick_timer_id = SDL_AddTimer(interval_in_ms, tick_timer, NULL);
+#ifndef HAVE_SDL_THREADS
+ SDL_LockMutex(wfi_mutex);
+#endif
+}
+
+#ifndef HAVE_SDL_THREADS
+static void check_exit(void)
+{
+ if (UNLIKELY(do_exit))
+ {
+ SDL_DestroyCond(wfi_cond);
+ SDL_UnlockMutex(wfi_mutex);
+ SDL_DestroyMutex(wfi_mutex);
+ sim_do_exit();
+ }
+}
+
+void wait_for_interrupt(void)
+{
+ /* the exit may come at any time, during the CondWait or before,
+ * so check it twice */
+ check_exit();
+ SDL_CondWait(wfi_cond, wfi_mutex);
+ check_exit();
}
+#endif