forked from len0rd/rockbox
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
This commit is contained in:
parent
3926c30705
commit
6d85de3419
13 changed files with 580 additions and 27 deletions
|
|
@ -34,6 +34,14 @@
|
|||
static SDL_TimerID tick_timer_id;
|
||||
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;
|
||||
/* Mutex to serialize changing levels and exclude other threads while
|
||||
|
|
@ -98,6 +106,9 @@ void sim_exit_irq_handler(void)
|
|||
|
||||
status_reg = 0;
|
||||
SDL_UnlockMutex(sim_irq_mtx);
|
||||
#ifndef HAVE_SDL_THREADS
|
||||
SDL_CondSignal(wfi_cond);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool sim_kernel_init(void)
|
||||
|
|
@ -115,15 +126,33 @@ static bool sim_kernel_init(void)
|
|||
panicf("Cannot create sim_thread_cond\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef HAVE_SDL_THREADS
|
||||
wfi_cond = SDL_CreateCond();
|
||||
if (wfi_cond == NULL)
|
||||
{
|
||||
panicf("Cannot create wfi\n");
|
||||
return false;
|
||||
}
|
||||
wfi_mutex = SDL_CreateMutex();
|
||||
if (wfi_mutex == NULL)
|
||||
{
|
||||
panicf("Cannot create wfi mutex\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void sim_kernel_shutdown(void)
|
||||
{
|
||||
SDL_RemoveTimer(tick_timer_id);
|
||||
#ifndef HAVE_SDL_THREADS
|
||||
do_exit = true;
|
||||
SDL_CondSignal(wfi_cond);
|
||||
#endif
|
||||
disable_irq();
|
||||
SDL_DestroyMutex(sim_irq_mtx);
|
||||
SDL_DestroyCond(sim_thread_cond);
|
||||
SDL_DestroyCond(sim_thread_cond);
|
||||
}
|
||||
|
||||
Uint32 tick_timer(Uint32 interval, void *param)
|
||||
|
|
@ -135,7 +164,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
|
|||
|
||||
new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ);
|
||||
|
||||
while(new_tick != current_tick)
|
||||
while(new_tick != current_tick && !do_exit)
|
||||
{
|
||||
sim_enter_irq_handler();
|
||||
|
||||
|
|
@ -146,7 +175,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
|
|||
sim_exit_irq_handler();
|
||||
}
|
||||
|
||||
return interval;
|
||||
return do_exit ? 0 : interval;
|
||||
}
|
||||
|
||||
void tick_start(unsigned int interval_in_ms)
|
||||
|
|
@ -168,4 +197,29 @@ void tick_start(unsigned int interval_in_ms)
|
|||
}
|
||||
|
||||
tick_timer_id = SDL_AddTimer(interval_in_ms, tick_timer, NULL);
|
||||
#ifndef HAVE_SDL_THREADS
|
||||
SDL_LockMutex(wfi_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
#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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue