summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-02-28 03:24:48 +0000
committerThomas Martitz <kugel@rockbox.org>2011-02-28 03:24:48 +0000
commitd8f6c75ab94ee97e9a49ce669d74dc252225586a (patch)
treef2eee157a098402ed5ae05866505bfa0e0a20d2b
parentd69d406e096d9df587e9b263cc16553d17b63162 (diff)
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
-rw-r--r--firmware/target/hosted/maemo/maemo-thread.c10
-rw-r--r--firmware/target/hosted/sdl/button-sdl.c8
-rw-r--r--firmware/target/hosted/sdl/kernel-sdl.c32
-rw-r--r--firmware/target/hosted/sdl/system-sdl.c32
-rw-r--r--firmware/target/hosted/sdl/system-sdl.h4
-rw-r--r--uisimulator/common/powermgmt-sim.c10
6 files changed, 45 insertions, 51 deletions
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 <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)
{
}
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 <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
diff --git a/uisimulator/common/powermgmt-sim.c b/uisimulator/common/powermgmt-sim.c
index 30b04d6a0b..12bb94fd5d 100644
--- a/uisimulator/common/powermgmt-sim.c
+++ b/uisimulator/common/powermgmt-sim.c
@@ -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)
{
}