From d8f6c75ab94ee97e9a49ce669d74dc252225586a Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Mon, 28 Feb 2011 03:24:48 +0000 Subject: Hopefully get shutdown/exit handling on SDL/maemo right. Make shutdown_hw() not return as it's supposed to, ensure sim_do_exit() is called from main thread and move sim_kernel_shutdown() into it to simplify things. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29455 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/hosted/maemo/maemo-thread.c | 10 --------- firmware/target/hosted/sdl/button-sdl.c | 8 ++++---- firmware/target/hosted/sdl/kernel-sdl.c | 32 +++++++++-------------------- firmware/target/hosted/sdl/system-sdl.c | 32 +++++++++++++++++++++++++---- firmware/target/hosted/sdl/system-sdl.h | 4 +++- 5 files changed, 45 insertions(+), 41 deletions(-) (limited to 'firmware/target/hosted') diff --git a/firmware/target/hosted/maemo/maemo-thread.c b/firmware/target/hosted/maemo/maemo-thread.c index 6593a9faa5..a0e5824252 100644 --- a/firmware/target/hosted/maemo/maemo-thread.c +++ b/firmware/target/hosted/maemo/maemo-thread.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "config.h" #include "system.h" @@ -212,15 +211,6 @@ void reset_poweroff_timer(void) { } -void shutdown_hw(void) -{ - /* Shut down SDL event loop */ - SDL_Event event; - memset(&event, 0, sizeof(SDL_Event)); - event.type = SDL_USEREVENT; - SDL_PushEvent(&event); -} - void cancel_shutdown(void) { } diff --git a/firmware/target/hosted/sdl/button-sdl.c b/firmware/target/hosted/sdl/button-sdl.c index 00afc0c8ef..f14e53fb44 100644 --- a/firmware/target/hosted/sdl/button-sdl.c +++ b/firmware/target/hosted/sdl/button-sdl.c @@ -275,8 +275,8 @@ static bool event_handler(SDL_Event *event) break; } case SDL_QUIT: - /* Post SYS_POWEROFF event. Will post SDL_USEREVENT in shutdown_hw() if successful. */ - queue_broadcast(SYS_POWEROFF, 0); + /* Will post SDL_USEREVENT in shutdown_hw() if successful. */ + sys_poweroff(); break; case SDL_USEREVENT: return true; @@ -324,8 +324,8 @@ static void button_event(int key, bool pressed) #if (CONFIG_PLATFORM & PLATFORM_PANDORA) case SDLK_LCTRL: - /* Post SYS_POWEROFF event. Will post SDL_USEREVENT in shutdown_hw() if successful. */ - queue_broadcast(SYS_POWEROFF, 0); + /* Will post SDL_USEREVENT in shutdown_hw() if successful. */ + sys_poweroff(); break; #endif #ifdef HAS_BUTTON_HOLD diff --git a/firmware/target/hosted/sdl/kernel-sdl.c b/firmware/target/hosted/sdl/kernel-sdl.c index 4fb1aede0a..5c16f86749 100644 --- a/firmware/target/hosted/sdl/kernel-sdl.c +++ b/firmware/target/hosted/sdl/kernel-sdl.c @@ -36,11 +36,8 @@ 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; @@ -74,7 +71,7 @@ int set_irq_level(int level) /* Not in a handler and "interrupts" are going from disabled to * enabled; signal any pending handlers still waiting */ if (handlers_pending > 0) - SDL_CondSignal(sim_thread_cond); + SDL_CondBroadcast(sim_thread_cond); } interrupt_level = level; /* save new level */ @@ -147,10 +144,14 @@ void sim_kernel_shutdown(void) { SDL_RemoveTimer(tick_timer_id); #ifndef HAVE_SDL_THREADS - do_exit = true; - SDL_CondSignal(wfi_cond); + SDL_DestroyCond(wfi_cond); + SDL_UnlockMutex(wfi_mutex); + SDL_DestroyMutex(wfi_mutex); #endif - disable_irq(); + enable_irq(); + while(handlers_pending > 0) + SDL_Delay(10); + SDL_DestroyMutex(sim_irq_mtx); SDL_DestroyCond(sim_thread_cond); } @@ -164,7 +165,7 @@ Uint32 tick_timer(Uint32 interval, void *param) new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ); - while(new_tick != current_tick && !do_exit) + while(new_tick != current_tick) { sim_enter_irq_handler(); @@ -175,7 +176,7 @@ Uint32 tick_timer(Uint32 interval, void *param) sim_exit_irq_handler(); } - return do_exit ? 0 : interval; + return interval; } void tick_start(unsigned int interval_in_ms) @@ -203,23 +204,10 @@ void tick_start(unsigned int interval_in_ms) } #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 diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c index 4dc5509397..7ddc5f8699 100644 --- a/firmware/target/hosted/sdl/system-sdl.c +++ b/firmware/target/hosted/sdl/system-sdl.c @@ -71,9 +71,10 @@ bool debug_audio = false; bool debug_wps = false; int wps_verbose_level = 3; - void sys_poweroff(void) { + /* Post SYS_POWEROFF event. Will post SDL_USEREVENT in shutdown_hw() if successful. */ + queue_broadcast(SYS_POWEROFF, 0); } /* @@ -187,16 +188,39 @@ static int sdl_event_thread(void * param) #ifdef HAVE_SDL_THREADS sim_thread_shutdown(); /* not needed for native threads */ #endif - sim_kernel_shutdown(); - return 0; } -void sim_do_exit(void) +void shutdown_hw(void) { + /* Shut down SDL event loop */ + SDL_Event event; + memset(&event, 0, sizeof(SDL_Event)); + event.type = SDL_USEREVENT; + SDL_PushEvent(&event); +#ifdef HAVE_SDL_THREADS + /* since sim_thread_shutdown() grabs the mutex we need to let it free, + * otherwise SDL_WaitThread will deadlock */ + struct thread_entry* t = sim_thread_unlock(); +#endif /* wait for event thread to finish */ SDL_WaitThread(evt_thread, NULL); +#ifdef HAVE_SDL_THREADS + /* lock again before entering the scheduler */ + sim_thread_lock(t); + /* sim_thread_shutdown() will cause sim_do_exit() to be called via longjmp, + * but only if we let the sdl thread scheduler exit the other threads */ + while(1) yield(); +#else + sim_do_exit(); +#endif +} + +void sim_do_exit() +{ + sim_kernel_shutdown(); + SDL_Quit(); exit(EXIT_SUCCESS); } diff --git a/firmware/target/hosted/sdl/system-sdl.h b/firmware/target/hosted/sdl/system-sdl.h index bec01ec81d..9021a12543 100644 --- a/firmware/target/hosted/sdl/system-sdl.h +++ b/firmware/target/hosted/sdl/system-sdl.h @@ -22,6 +22,8 @@ #define _SYSTEM_SDL_H_ #include +#include "config.h" +#include "gcc_extensions.h" #define HIGHEST_IRQ_LEVEL 1 @@ -45,7 +47,7 @@ void sim_kernel_shutdown(void); void sys_poweroff(void); void sys_handle_argv(int argc, char *argv[]); void gui_message_loop(void); -void sim_do_exit(void); +void sim_do_exit(void) NORETURN_ATTR; #ifndef HAVE_SDL_THREADS void wait_for_interrupt(void); #endif -- cgit v1.2.3