diff options
author | Thomas Martitz <kugel@rockbox.org> | 2011-02-18 22:46:01 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2011-02-18 22:46:01 +0000 |
commit | 6d85de341928aef8178465c60122f3cbe76f5dd6 (patch) | |
tree | ff86c384a574ac20d3418c1b904ed4d0de1f6980 /firmware/target/hosted/sdl | |
parent | 3926c30705cc7235122e2f2e35ab506b53238cdf (diff) | |
download | rockbox-6d85de341928aef8178465c60122f3cbe76f5dd6.tar.gz rockbox-6d85de341928aef8178465c60122f3cbe76f5dd6.zip |
Implement cooperative threads on hosted platforms using C code.
This replaces SDL threads with real cooperative threads, which are less cpu intensive and allow priority scheduling.
The backend for context switching is dependant on the host (sigaltstack/longjmp on Unix, Fibers on Windows).
configure has options to force or disallow SDL threads.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29327 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/hosted/sdl')
-rw-r--r-- | firmware/target/hosted/sdl/kernel-sdl.c | 62 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/system-sdl.c | 21 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/system-sdl.h | 3 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/thread-sdl.h | 2 |
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 @@ | |||
34 | static SDL_TimerID tick_timer_id; | 34 | static SDL_TimerID tick_timer_id; |
35 | long start_tick; | 35 | long start_tick; |
36 | 36 | ||
37 | #ifndef HAVE_SDL_THREADS | ||
38 | /* for the wait_for_interrupt function */ | ||
39 | static bool do_exit; | ||
40 | static SDL_cond *wfi_cond; | ||
41 | static 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 */ |
38 | static SDL_cond *sim_thread_cond; | 46 | static 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 | ||
103 | static bool sim_kernel_init(void) | 114 | static 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 | ||
122 | void sim_kernel_shutdown(void) | 146 | void 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 | ||
129 | Uint32 tick_timer(Uint32 interval, void *param) | 158 | Uint32 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 | ||
152 | void tick_start(unsigned int interval_in_ms) | 181 | void 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 | ||
206 | static 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 | |||
217 | void 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 | ||
204 | uintptr_t *stackbegin; | ||
205 | uintptr_t *stackend; | ||
202 | void system_init(void) | 206 | void 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 | ||
227 | void system_exception_wait(void) | ||
228 | { | ||
229 | sim_thread_exception_wait(); | ||
230 | } | ||
231 | 232 | ||
232 | void system_reboot(void) | 233 | void 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 | ||
242 | void system_exception_wait(void) | ||
243 | { | ||
244 | system_reboot(); | ||
245 | } | ||
237 | 246 | ||
238 | void sys_handle_argv(int argc, char *argv[]) | 247 | void 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); | |||
46 | void sys_handle_argv(int argc, char *argv[]); | 46 | void sys_handle_argv(int argc, char *argv[]); |
47 | void gui_message_loop(void); | 47 | void gui_message_loop(void); |
48 | void sim_do_exit(void); | 48 | void sim_do_exit(void); |
49 | #ifndef HAVE_SDL_THREADS | ||
50 | void wait_for_interrupt(void); | ||
51 | #endif | ||
49 | 52 | ||
50 | extern bool background; /* True if the background image is enabled */ | 53 | extern bool background; /* True if the background image is enabled */ |
51 | extern bool showremote; | 54 | extern 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 */ |
26 | void sim_thread_lock(void *me); | 27 | void sim_thread_lock(void *me); |
27 | void * sim_thread_unlock(void); | 28 | void * sim_thread_unlock(void); |
28 | void sim_thread_exception_wait(void); | 29 | void sim_thread_exception_wait(void); |
29 | void sim_thread_shutdown(void); /* Shut down all kernel threads gracefully */ | 30 | void 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 | ||