diff options
Diffstat (limited to 'uisimulator/sdl/thread.c')
-rw-r--r-- | uisimulator/sdl/thread.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/uisimulator/sdl/thread.c b/uisimulator/sdl/thread.c new file mode 100644 index 0000000000..6d9139c35d --- /dev/null +++ b/uisimulator/sdl/thread.c @@ -0,0 +1,148 @@ +/*************************************************************************** + * __________ __ ___. + * 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> +#include <pthread.h> + +#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. + */ +static void update_tick_thread() +{ + struct timeval start, now; + long new_tick; + + 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; + } + } +} + +/* + * We emulate the target threads by using pthreads. 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. + */ + +pthread_mutex_t mp; + +void init_threads(void) +{ + pthread_t tick_tid; + + pthread_mutex_init(&mp, NULL); + /* get mutex to only allow one thread running at a time */ + pthread_mutex_lock(&mp); + + /* start a tick thread */ + pthread_create(&tick_tid, NULL, (void *(*)(void *)) update_tick_thread, + NULL); + +#ifdef ROCKBOX_HAS_SIMSOUND /* start thread that plays PCM data */ + { + pthread_t sound_tid; + pthread_create(&sound_tid, NULL, + (void *(*)(void *)) sound_playback_thread, + NULL); + } +#endif + +} +/* + int pthread_create(pthread_t *new_thread_ID, + const pthread_attr_t *attr, + void * (*start_func)(void *), void *arg); +*/ + +void yield(void) +{ + pthread_mutex_unlock(&mp); /* return */ + msleep(1); /* prevent busy loop */ + pthread_mutex_lock(&mp); /* get it again */ +} + +void newfunc(void (*func)(void)) +{ + pthread_mutex_lock(&mp); + func(); + pthread_mutex_unlock(&mp); +} + + +int create_thread(void (*fp)(void), void* sp, int stk_size) +{ + pthread_t tid; + int i; + int error; + + /* we really don't care about these arguments */ + (void)sp; + (void)stk_size; + error = pthread_create(&tid, + NULL, /* default attributes please */ + (void *(*)(void *)) newfunc, /* function to start */ + fp /* start argument */); + if(0 != error) + fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error); + else + fprintf(stderr, "Thread %ld is running\n", (long)tid); + + yield(); + + return error; +} + +void sim_sleep(int ticks) +{ + pthread_mutex_unlock(&mp); /* return */ + msleep((1000/HZ) * ticks); + pthread_mutex_lock(&mp); /* get it again */ +} + |