blob: 6d9139c35def1422701a6c39d993c9ca6022e998 [file] [log] [blame]
Daniel Stenberg604cce72002-06-10 10:17:54 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Daniel Stenberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
Daniel Stenbergfebb52f2005-07-14 21:46:07 +000020#include "autoconf.h"
21
Daniel Stenberg604cce72002-06-10 10:17:54 +000022#include <stdio.h>
23#include <pthread.h>
24
Daniel Stenberg5fbeb6d2002-06-14 12:33:51 +000025#include "kernel.h"
Jens Arnold6c19c852005-03-07 20:04:05 +000026#include <sys/time.h>
Daniel Stenberg5fbeb6d2002-06-14 12:33:51 +000027
Daniel Stenbergfebb52f2005-07-14 21:46:07 +000028#ifdef ROCKBOX_HAS_SIMSOUND
29#include "sound.h"
30#endif
31
Daniel Stenberg973b1a82002-06-14 12:44:51 +000032long current_tick = 0;
Jens Arnoldb51f7df2005-11-21 23:55:39 +000033extern void sim_tick_tasks(void);
Jens Arnold74b731e2005-03-18 23:51:52 +000034
35static void msleep(int msec)
36{
37 struct timeval delay;
38
39 delay.tv_sec = msec / 1000;
Jens Arnold441e5122005-05-11 20:04:43 +000040 delay.tv_usec = (msec % 1000) * 1000;
Jens Arnold74b731e2005-03-18 23:51:52 +000041 select(0, NULL, NULL, NULL, &delay); /* portable sub-second sleep */
42}
Daniel Stenberg5fbeb6d2002-06-14 12:33:51 +000043
Daniel Stenberg604cce72002-06-10 10:17:54 +000044/*
Jens Arnold6c19c852005-03-07 20:04:05 +000045 * This is not a target thread, so it does not fall under the 1 thread at a
46 * time thing.
47 */
48static void update_tick_thread()
49{
Jens Arnold74b731e2005-03-18 23:51:52 +000050 struct timeval start, now;
51 long new_tick;
Jens Arnold6c19c852005-03-07 20:04:05 +000052
53 gettimeofday(&start, NULL);
54 while (1)
55 {
Jens Arnold74b731e2005-03-18 23:51:52 +000056 msleep(5); /* check twice per simulated target tick */
Jens Arnold6c19c852005-03-07 20:04:05 +000057 gettimeofday(&now, NULL);
Jens Arnold74b731e2005-03-18 23:51:52 +000058 new_tick = (now.tv_sec - start.tv_sec) * HZ
59 + (now.tv_usec - start.tv_usec) / (1000000/HZ);
60 if (new_tick > current_tick)
61 {
Jens Arnoldb51f7df2005-11-21 23:55:39 +000062 sim_tick_tasks();
Jens Arnold74b731e2005-03-18 23:51:52 +000063 current_tick = new_tick;
Jens Arnold74b731e2005-03-18 23:51:52 +000064 }
Jens Arnold6c19c852005-03-07 20:04:05 +000065 }
66}
67
68/*
Daniel Stenberg604cce72002-06-10 10:17:54 +000069 * We emulate the target threads by using pthreads. We have a mutex that only
70 * allows one thread at a time to execute. It forces each thread to yield()
71 * for the other(s) to run.
72 */
73
74pthread_mutex_t mp;
75
76void init_threads(void)
77{
Jens Arnold6c19c852005-03-07 20:04:05 +000078 pthread_t tick_tid;
Daniel Stenberg5fbeb6d2002-06-14 12:33:51 +000079
Jens Arnold6c19c852005-03-07 20:04:05 +000080 pthread_mutex_init(&mp, NULL);
81 /* get mutex to only allow one thread running at a time */
82 pthread_mutex_lock(&mp);
83
Daniel Stenbergfebb52f2005-07-14 21:46:07 +000084 /* start a tick thread */
Jens Arnold6c19c852005-03-07 20:04:05 +000085 pthread_create(&tick_tid, NULL, (void *(*)(void *)) update_tick_thread,
86 NULL);
Daniel Stenbergfebb52f2005-07-14 21:46:07 +000087
88#ifdef ROCKBOX_HAS_SIMSOUND /* start thread that plays PCM data */
89 {
90 pthread_t sound_tid;
91 pthread_create(&sound_tid, NULL,
92 (void *(*)(void *)) sound_playback_thread,
93 NULL);
94 }
95#endif
96
Daniel Stenberg604cce72002-06-10 10:17:54 +000097}
98/*
99 int pthread_create(pthread_t *new_thread_ID,
100 const pthread_attr_t *attr,
101 void * (*start_func)(void *), void *arg);
102*/
103
Daniel Stenberg973b1a82002-06-14 12:44:51 +0000104void yield(void)
Daniel Stenberg604cce72002-06-10 10:17:54 +0000105{
Jens Arnold6c19c852005-03-07 20:04:05 +0000106 pthread_mutex_unlock(&mp); /* return */
Jens Arnold74b731e2005-03-18 23:51:52 +0000107 msleep(1); /* prevent busy loop */
108 pthread_mutex_lock(&mp); /* get it again */
Daniel Stenberg604cce72002-06-10 10:17:54 +0000109}
110
Daniel Stenberg5fbeb6d2002-06-14 12:33:51 +0000111void newfunc(void (*func)(void))
112{
Jens Arnold6c19c852005-03-07 20:04:05 +0000113 pthread_mutex_lock(&mp);
Daniel Stenberg973b1a82002-06-14 12:44:51 +0000114 func();
Jens Arnold6c19c852005-03-07 20:04:05 +0000115 pthread_mutex_unlock(&mp);
Daniel Stenberg5fbeb6d2002-06-14 12:33:51 +0000116}
117
118
Linus Nielsen Feltzinga19acbd2005-07-12 10:05:13 +0000119int create_thread(void (*fp)(void), void* sp, int stk_size)
Daniel Stenberg604cce72002-06-10 10:17:54 +0000120{
Jens Arnold6c19c852005-03-07 20:04:05 +0000121 pthread_t tid;
122 int i;
123 int error;
Daniel Stenberg604cce72002-06-10 10:17:54 +0000124
Jens Arnold6c19c852005-03-07 20:04:05 +0000125 /* we really don't care about these arguments */
126 (void)sp;
127 (void)stk_size;
128 error = pthread_create(&tid,
129 NULL, /* default attributes please */
130 (void *(*)(void *)) newfunc, /* function to start */
131 fp /* start argument */);
132 if(0 != error)
133 fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
134 else
135 fprintf(stderr, "Thread %ld is running\n", (long)tid);
Daniel Stenberg604cce72002-06-10 10:17:54 +0000136
Jens Arnold6c19c852005-03-07 20:04:05 +0000137 yield();
Daniel Stenberg604cce72002-06-10 10:17:54 +0000138
Jens Arnold6c19c852005-03-07 20:04:05 +0000139 return error;
Daniel Stenberg604cce72002-06-10 10:17:54 +0000140}
Daniel Stenberg5fbeb6d2002-06-14 12:33:51 +0000141
Linus Nielsen Feltzinga6142ab2004-06-10 13:29:52 +0000142void sim_sleep(int ticks)
Daniel Stenberg5fbeb6d2002-06-14 12:33:51 +0000143{
Jens Arnold6c19c852005-03-07 20:04:05 +0000144 pthread_mutex_unlock(&mp); /* return */
Jens Arnold74b731e2005-03-18 23:51:52 +0000145 msleep((1000/HZ) * ticks);
146 pthread_mutex_lock(&mp); /* get it again */
Daniel Stenberg5fbeb6d2002-06-14 12:33:51 +0000147}
Daniel Stenberg22b77012005-02-22 12:19:12 +0000148