2006-01-09 11:22:36 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Copyright (C) 2002 Daniel Stenberg
|
|
|
|
*
|
|
|
|
* All files in this archive are subject to the GNU General Public License.
|
|
|
|
* See the file COPYING in the source tree root for full license agreement.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "autoconf.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2006-01-13 13:38:31 +00:00
|
|
|
|
|
|
|
/* SDL threading wrapper */
|
|
|
|
#include <SDL.h>
|
|
|
|
#include <SDL_thread.h>
|
2006-01-09 11:22:36 +00:00
|
|
|
|
|
|
|
#include "kernel.h"
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
|
|
|
#ifdef ROCKBOX_HAS_SIMSOUND
|
|
|
|
#include "sound.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
long current_tick = 0;
|
|
|
|
extern void sim_tick_tasks(void);
|
|
|
|
|
|
|
|
static void msleep(int msec)
|
|
|
|
{
|
|
|
|
struct timeval delay;
|
|
|
|
|
|
|
|
delay.tv_sec = msec / 1000;
|
|
|
|
delay.tv_usec = (msec % 1000) * 1000;
|
|
|
|
select(0, NULL, NULL, NULL, &delay); /* portable sub-second sleep */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is not a target thread, so it does not fall under the 1 thread at a
|
|
|
|
* time thing.
|
|
|
|
*/
|
2006-01-13 13:38:31 +00:00
|
|
|
static int update_tick_thread(void* p)
|
2006-01-09 11:22:36 +00:00
|
|
|
{
|
|
|
|
struct timeval start, now;
|
|
|
|
long new_tick;
|
|
|
|
|
2006-01-13 13:38:31 +00:00
|
|
|
(void)p;
|
|
|
|
|
2006-01-09 11:22:36 +00:00
|
|
|
gettimeofday(&start, NULL);
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
msleep(5); /* check twice per simulated target tick */
|
|
|
|
gettimeofday(&now, NULL);
|
|
|
|
new_tick = (now.tv_sec - start.tv_sec) * HZ
|
|
|
|
+ (now.tv_usec - start.tv_usec) / (1000000/HZ);
|
|
|
|
if (new_tick > current_tick)
|
|
|
|
{
|
|
|
|
sim_tick_tasks();
|
|
|
|
current_tick = new_tick;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-01-13 13:38:31 +00:00
|
|
|
* We emulate the target threads by using SDL threads. We have a mutex
|
|
|
|
* that only allows one thread at a time to execute. It forces each
|
|
|
|
* thread to yield() for the other(s) to run.
|
2006-01-09 11:22:36 +00:00
|
|
|
*/
|
|
|
|
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_mutex * mp;
|
2006-01-09 11:22:36 +00:00
|
|
|
|
|
|
|
void init_threads(void)
|
|
|
|
{
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_Thread *tick_tid;
|
2006-01-09 11:22:36 +00:00
|
|
|
|
2006-01-13 13:38:31 +00:00
|
|
|
mp=SDL_CreateMutex();
|
2006-01-09 11:22:36 +00:00
|
|
|
/* get mutex to only allow one thread running at a time */
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_mutexP(mp);
|
2006-01-09 11:22:36 +00:00
|
|
|
|
|
|
|
/* start a tick thread */
|
2006-01-13 13:38:31 +00:00
|
|
|
tick_tid=SDL_CreateThread(update_tick_thread, NULL);
|
2006-01-09 11:22:36 +00:00
|
|
|
|
|
|
|
#ifdef ROCKBOX_HAS_SIMSOUND /* start thread that plays PCM data */
|
|
|
|
{
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_Thread *sound_tid;
|
|
|
|
sound_tid = SDL_CreateThread(sound_playback_thread, NULL);
|
2006-01-09 11:22:36 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void yield(void)
|
|
|
|
{
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_mutexV(mp); /* return */
|
2006-01-09 11:22:36 +00:00
|
|
|
msleep(1); /* prevent busy loop */
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_mutexP(mp); /* get it again */
|
2006-01-09 11:22:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void newfunc(void (*func)(void))
|
|
|
|
{
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_mutexP(mp);
|
2006-01-09 11:22:36 +00:00
|
|
|
func();
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_mutexV(mp);
|
2006-01-09 11:22:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int create_thread(void (*fp)(void), void* sp, int stk_size)
|
|
|
|
{
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_Thread * tid;
|
2006-01-09 11:22:36 +00:00
|
|
|
int i;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
/* we really don't care about these arguments */
|
|
|
|
(void)sp;
|
|
|
|
(void)stk_size;
|
2006-01-13 13:38:31 +00:00
|
|
|
tid = SDL_CreateThread(
|
|
|
|
(int(*)(void *))newfunc, /* function to start */
|
2006-01-09 11:22:36 +00:00
|
|
|
fp /* start argument */);
|
2006-01-13 13:38:31 +00:00
|
|
|
if(0 == tid) /* don't really have an error number here. */
|
|
|
|
fprintf(stderr, "Couldn't run thread number %d\n", i);
|
2006-01-09 11:22:36 +00:00
|
|
|
else
|
2006-01-13 13:38:31 +00:00
|
|
|
fprintf(stderr, "Thread %d is running\n", (int)SDL_GetThreadID(tid));
|
2006-01-09 11:22:36 +00:00
|
|
|
|
|
|
|
yield();
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
void sim_sleep(int ticks)
|
|
|
|
{
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_mutexV(mp); /* return */
|
2006-01-09 11:22:36 +00:00
|
|
|
msleep((1000/HZ) * ticks);
|
2006-01-13 13:38:31 +00:00
|
|
|
SDL_mutexP(mp); /* get it again */
|
2006-01-09 11:22:36 +00:00
|
|
|
}
|
|
|
|
|