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 <libosso.h>
#include <SDL_thread.h>
#include <SDL_events.h>
#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)
{
}

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -22,6 +22,8 @@
#define _SYSTEM_SDL_H_
#include <stdbool.h>
#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

View file

@ -24,7 +24,6 @@
#include <time.h>
#include "kernel.h"
#include "powermgmt.h"
#include <SDL_events.h>
#define BATT_MINMVOLT 2500 /* minimum 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)
{
}