summaryrefslogtreecommitdiff
path: root/firmware/target/hosted/sdl
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/sdl')
-rw-r--r--firmware/target/hosted/sdl/kernel-sdl.c62
-rw-r--r--firmware/target/hosted/sdl/system-sdl.c21
-rw-r--r--firmware/target/hosted/sdl/system-sdl.h3
-rw-r--r--firmware/target/hosted/sdl/thread-sdl.h2
4 files changed, 78 insertions, 10 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 @@
34static SDL_TimerID tick_timer_id; 34static SDL_TimerID tick_timer_id;
35long start_tick; 35long start_tick;
36 36
37#ifndef HAVE_SDL_THREADS
38/* for the wait_for_interrupt function */
39static bool do_exit;
40static SDL_cond *wfi_cond;
41static SDL_mutex *wfi_mutex;
42#else
43#define do_exit false
44#endif
37/* Condition to signal that "interrupts" may proceed */ 45/* Condition to signal that "interrupts" may proceed */
38static SDL_cond *sim_thread_cond; 46static SDL_cond *sim_thread_cond;
39/* Mutex to serialize changing levels and exclude other threads while 47/* Mutex to serialize changing levels and exclude other threads while
@@ -98,6 +106,9 @@ void sim_exit_irq_handler(void)
98 106
99 status_reg = 0; 107 status_reg = 0;
100 SDL_UnlockMutex(sim_irq_mtx); 108 SDL_UnlockMutex(sim_irq_mtx);
109#ifndef HAVE_SDL_THREADS
110 SDL_CondSignal(wfi_cond);
111#endif
101} 112}
102 113
103static bool sim_kernel_init(void) 114static bool sim_kernel_init(void)
@@ -115,15 +126,33 @@ static bool sim_kernel_init(void)
115 panicf("Cannot create sim_thread_cond\n"); 126 panicf("Cannot create sim_thread_cond\n");
116 return false; 127 return false;
117 } 128 }
118 129#ifndef HAVE_SDL_THREADS
130 wfi_cond = SDL_CreateCond();
131 if (wfi_cond == NULL)
132 {
133 panicf("Cannot create wfi\n");
134 return false;
135 }
136 wfi_mutex = SDL_CreateMutex();
137 if (wfi_mutex == NULL)
138 {
139 panicf("Cannot create wfi mutex\n");
140 return false;
141 }
142#endif
119 return true; 143 return true;
120} 144}
121 145
122void sim_kernel_shutdown(void) 146void sim_kernel_shutdown(void)
123{ 147{
124 SDL_RemoveTimer(tick_timer_id); 148 SDL_RemoveTimer(tick_timer_id);
149#ifndef HAVE_SDL_THREADS
150 do_exit = true;
151 SDL_CondSignal(wfi_cond);
152#endif
153 disable_irq();
125 SDL_DestroyMutex(sim_irq_mtx); 154 SDL_DestroyMutex(sim_irq_mtx);
126 SDL_DestroyCond(sim_thread_cond); 155 SDL_DestroyCond(sim_thread_cond);
127} 156}
128 157
129Uint32 tick_timer(Uint32 interval, void *param) 158Uint32 tick_timer(Uint32 interval, void *param)
@@ -135,7 +164,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
135 164
136 new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ); 165 new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ);
137 166
138 while(new_tick != current_tick) 167 while(new_tick != current_tick && !do_exit)
139 { 168 {
140 sim_enter_irq_handler(); 169 sim_enter_irq_handler();
141 170
@@ -146,7 +175,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
146 sim_exit_irq_handler(); 175 sim_exit_irq_handler();
147 } 176 }
148 177
149 return interval; 178 return do_exit ? 0 : interval;
150} 179}
151 180
152void tick_start(unsigned int interval_in_ms) 181void tick_start(unsigned int interval_in_ms)
@@ -168,4 +197,29 @@ void tick_start(unsigned int interval_in_ms)
168 } 197 }
169 198
170 tick_timer_id = SDL_AddTimer(interval_in_ms, tick_timer, NULL); 199 tick_timer_id = SDL_AddTimer(interval_in_ms, tick_timer, NULL);
200#ifndef HAVE_SDL_THREADS
201 SDL_LockMutex(wfi_mutex);
202#endif
203}
204
205#ifndef HAVE_SDL_THREADS
206static void check_exit(void)
207{
208 if (UNLIKELY(do_exit))
209 {
210 SDL_DestroyCond(wfi_cond);
211 SDL_UnlockMutex(wfi_mutex);
212 SDL_DestroyMutex(wfi_mutex);
213 sim_do_exit();
214 }
215}
216
217void wait_for_interrupt(void)
218{
219 /* the exit may come at any time, during the CondWait or before,
220 * so check it twice */
221 check_exit();
222 SDL_CondWait(wfi_cond, wfi_mutex);
223 check_exit();
171} 224}
225#endif
diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c
index 9ea25c1014..1cc9b2c919 100644
--- a/firmware/target/hosted/sdl/system-sdl.c
+++ b/firmware/target/hosted/sdl/system-sdl.c
@@ -184,7 +184,9 @@ static int sdl_event_thread(void * param)
184 184
185 /* Order here is relevent to prevent deadlocks and use of destroyed 185 /* Order here is relevent to prevent deadlocks and use of destroyed
186 sync primitives by kernel threads */ 186 sync primitives by kernel threads */
187 sim_thread_shutdown(); 187#ifdef HAVE_SDL_THREADS
188 sim_thread_shutdown(); /* not needed for native threads */
189#endif
188 sim_kernel_shutdown(); 190 sim_kernel_shutdown();
189 191
190 return 0; 192 return 0;
@@ -199,9 +201,13 @@ void sim_do_exit(void)
199 exit(EXIT_SUCCESS); 201 exit(EXIT_SUCCESS);
200} 202}
201 203
204uintptr_t *stackbegin;
205uintptr_t *stackend;
202void system_init(void) 206void system_init(void)
203{ 207{
204 SDL_sem *s; 208 SDL_sem *s;
209 /* fake stack, OS manages size (and growth) */
210 stackbegin = stackend = (uintptr_t*)&s;
205 211
206#if (CONFIG_PLATFORM & PLATFORM_MAEMO) 212#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
207 /* Make glib thread safe */ 213 /* Make glib thread safe */
@@ -219,21 +225,24 @@ void system_init(void)
219 /* wait for sdl_event_thread to run so that it can initialize the surfaces 225 /* wait for sdl_event_thread to run so that it can initialize the surfaces
220 * and video subsystem needed for SDL events */ 226 * and video subsystem needed for SDL events */
221 SDL_SemWait(s); 227 SDL_SemWait(s);
222
223 /* cleanup */ 228 /* cleanup */
224 SDL_DestroySemaphore(s); 229 SDL_DestroySemaphore(s);
225} 230}
226 231
227void system_exception_wait(void)
228{
229 sim_thread_exception_wait();
230}
231 232
232void system_reboot(void) 233void system_reboot(void)
233{ 234{
235#ifdef HAVE_SDL_THREADS
234 sim_thread_exception_wait(); 236 sim_thread_exception_wait();
237#else
238 sim_do_exit();
239#endif
235} 240}
236 241
242void system_exception_wait(void)
243{
244 system_reboot();
245}
237 246
238void sys_handle_argv(int argc, char *argv[]) 247void sys_handle_argv(int argc, char *argv[])
239{ 248{
diff --git a/firmware/target/hosted/sdl/system-sdl.h b/firmware/target/hosted/sdl/system-sdl.h
index 01952e50a0..bec01ec81d 100644
--- a/firmware/target/hosted/sdl/system-sdl.h
+++ b/firmware/target/hosted/sdl/system-sdl.h
@@ -46,6 +46,9 @@ void sys_poweroff(void);
46void sys_handle_argv(int argc, char *argv[]); 46void sys_handle_argv(int argc, char *argv[]);
47void gui_message_loop(void); 47void gui_message_loop(void);
48void sim_do_exit(void); 48void sim_do_exit(void);
49#ifndef HAVE_SDL_THREADS
50void wait_for_interrupt(void);
51#endif
49 52
50extern bool background; /* True if the background image is enabled */ 53extern bool background; /* True if the background image is enabled */
51extern bool showremote; 54extern bool showremote;
diff --git a/firmware/target/hosted/sdl/thread-sdl.h b/firmware/target/hosted/sdl/thread-sdl.h
index 9384e6060d..9edb3ee74e 100644
--- a/firmware/target/hosted/sdl/thread-sdl.h
+++ b/firmware/target/hosted/sdl/thread-sdl.h
@@ -22,11 +22,13 @@
22#ifndef __THREADSDL_H__ 22#ifndef __THREADSDL_H__
23#define __THREADSDL_H__ 23#define __THREADSDL_H__
24 24
25#ifdef HAVE_SDL_THREADS
25/* extra thread functions that only apply when running on hosting platforms */ 26/* extra thread functions that only apply when running on hosting platforms */
26void sim_thread_lock(void *me); 27void sim_thread_lock(void *me);
27void * sim_thread_unlock(void); 28void * sim_thread_unlock(void);
28void sim_thread_exception_wait(void); 29void sim_thread_exception_wait(void);
29void sim_thread_shutdown(void); /* Shut down all kernel threads gracefully */ 30void sim_thread_shutdown(void); /* Shut down all kernel threads gracefully */
31#endif
30 32
31#endif /* #ifndef __THREADSDL_H__ */ 33#endif /* #ifndef __THREADSDL_H__ */
32 34