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
This commit is contained in:
Thomas Martitz 2011-02-28 03:24:48 +00:00
parent d69d406e09
commit d8f6c75ab9
6 changed files with 45 additions and 51 deletions

View file

@ -23,7 +23,6 @@
#include <libhal.h> #include <libhal.h>
#include <libosso.h> #include <libosso.h>
#include <SDL_thread.h> #include <SDL_thread.h>
#include <SDL_events.h>
#include "config.h" #include "config.h"
#include "system.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) void cancel_shutdown(void)
{ {
} }

View file

@ -275,8 +275,8 @@ static bool event_handler(SDL_Event *event)
break; break;
} }
case SDL_QUIT: case SDL_QUIT:
/* Post SYS_POWEROFF event. Will post SDL_USEREVENT in shutdown_hw() if successful. */ /* Will post SDL_USEREVENT in shutdown_hw() if successful. */
queue_broadcast(SYS_POWEROFF, 0); sys_poweroff();
break; break;
case SDL_USEREVENT: case SDL_USEREVENT:
return true; return true;
@ -324,8 +324,8 @@ static void button_event(int key, bool pressed)
#if (CONFIG_PLATFORM & PLATFORM_PANDORA) #if (CONFIG_PLATFORM & PLATFORM_PANDORA)
case SDLK_LCTRL: case SDLK_LCTRL:
/* Post SYS_POWEROFF event. Will post SDL_USEREVENT in shutdown_hw() if successful. */ /* Will post SDL_USEREVENT in shutdown_hw() if successful. */
queue_broadcast(SYS_POWEROFF, 0); sys_poweroff();
break; break;
#endif #endif
#ifdef HAS_BUTTON_HOLD #ifdef HAS_BUTTON_HOLD

View file

@ -36,11 +36,8 @@ long start_tick;
#ifndef HAVE_SDL_THREADS #ifndef HAVE_SDL_THREADS
/* for the wait_for_interrupt function */ /* for the wait_for_interrupt function */
static bool do_exit;
static SDL_cond *wfi_cond; static SDL_cond *wfi_cond;
static SDL_mutex *wfi_mutex; static SDL_mutex *wfi_mutex;
#else
#define do_exit false
#endif #endif
/* Condition to signal that "interrupts" may proceed */ /* Condition to signal that "interrupts" may proceed */
static SDL_cond *sim_thread_cond; 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 /* Not in a handler and "interrupts" are going from disabled to
* enabled; signal any pending handlers still waiting */ * enabled; signal any pending handlers still waiting */
if (handlers_pending > 0) if (handlers_pending > 0)
SDL_CondSignal(sim_thread_cond); SDL_CondBroadcast(sim_thread_cond);
} }
interrupt_level = level; /* save new level */ interrupt_level = level; /* save new level */
@ -147,10 +144,14 @@ void sim_kernel_shutdown(void)
{ {
SDL_RemoveTimer(tick_timer_id); SDL_RemoveTimer(tick_timer_id);
#ifndef HAVE_SDL_THREADS #ifndef HAVE_SDL_THREADS
do_exit = true; SDL_DestroyCond(wfi_cond);
SDL_CondSignal(wfi_cond); SDL_UnlockMutex(wfi_mutex);
SDL_DestroyMutex(wfi_mutex);
#endif #endif
disable_irq(); enable_irq();
while(handlers_pending > 0)
SDL_Delay(10);
SDL_DestroyMutex(sim_irq_mtx); SDL_DestroyMutex(sim_irq_mtx);
SDL_DestroyCond(sim_thread_cond); SDL_DestroyCond(sim_thread_cond);
} }
@ -164,7 +165,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ); new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ);
while(new_tick != current_tick && !do_exit) while(new_tick != current_tick)
{ {
sim_enter_irq_handler(); sim_enter_irq_handler();
@ -175,7 +176,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
sim_exit_irq_handler(); sim_exit_irq_handler();
} }
return do_exit ? 0 : interval; return interval;
} }
void tick_start(unsigned int interval_in_ms) void tick_start(unsigned int interval_in_ms)
@ -203,23 +204,10 @@ void tick_start(unsigned int interval_in_ms)
} }
#ifndef HAVE_SDL_THREADS #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) void wait_for_interrupt(void)
{ {
/* the exit may come at any time, during the CondWait or before, /* the exit may come at any time, during the CondWait or before,
* so check it twice */ * so check it twice */
check_exit();
SDL_CondWait(wfi_cond, wfi_mutex); SDL_CondWait(wfi_cond, wfi_mutex);
check_exit();
} }
#endif #endif

View file

@ -71,9 +71,10 @@ bool debug_audio = false;
bool debug_wps = false; bool debug_wps = false;
int wps_verbose_level = 3; int wps_verbose_level = 3;
void sys_poweroff(void) 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 #ifdef HAVE_SDL_THREADS
sim_thread_shutdown(); /* not needed for native threads */ sim_thread_shutdown(); /* not needed for native threads */
#endif #endif
sim_kernel_shutdown();
return 0; 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 */ /* wait for event thread to finish */
SDL_WaitThread(evt_thread, NULL); 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(); SDL_Quit();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }

View file

@ -22,6 +22,8 @@
#define _SYSTEM_SDL_H_ #define _SYSTEM_SDL_H_
#include <stdbool.h> #include <stdbool.h>
#include "config.h"
#include "gcc_extensions.h"
#define HIGHEST_IRQ_LEVEL 1 #define HIGHEST_IRQ_LEVEL 1
@ -45,7 +47,7 @@ void sim_kernel_shutdown(void);
void sys_poweroff(void); void sys_poweroff(void);
void sys_handle_argv(int argc, char *argv[]); void sys_handle_argv(int argc, char *argv[]);
void gui_message_loop(void); void gui_message_loop(void);
void sim_do_exit(void); void sim_do_exit(void) NORETURN_ATTR;
#ifndef HAVE_SDL_THREADS #ifndef HAVE_SDL_THREADS
void wait_for_interrupt(void); void wait_for_interrupt(void);
#endif #endif

View file

@ -24,7 +24,6 @@
#include <time.h> #include <time.h>
#include "kernel.h" #include "kernel.h"
#include "powermgmt.h" #include "powermgmt.h"
#include <SDL_events.h>
#define BATT_MINMVOLT 2500 /* minimum millivolts of battery */ #define BATT_MINMVOLT 2500 /* minimum millivolts of battery */
#define BATT_MAXMVOLT 4500 /* maximum millivolts of battery */ #define BATT_MAXMVOLT 4500 /* maximum millivolts of battery */
@ -154,15 +153,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) void cancel_shutdown(void)
{ {
} }