summaryrefslogtreecommitdiffstats
path: root/uisimulator/sdl/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'uisimulator/sdl/thread.c')
-rw-r--r--uisimulator/sdl/thread.c148
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 */
+}
+