summaryrefslogtreecommitdiff
path: root/firmware/target/hosted/sdl/kernel-sdl.c
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-02-18 22:46:01 +0000
committerThomas Martitz <kugel@rockbox.org>2011-02-18 22:46:01 +0000
commit6d85de341928aef8178465c60122f3cbe76f5dd6 (patch)
treeff86c384a574ac20d3418c1b904ed4d0de1f6980 /firmware/target/hosted/sdl/kernel-sdl.c
parent3926c30705cc7235122e2f2e35ab506b53238cdf (diff)
downloadrockbox-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/kernel-sdl.c')
-rw-r--r--firmware/target/hosted/sdl/kernel-sdl.c62
1 files changed, 58 insertions, 4 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