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 @@ | |||
1 | /*************************************************************************** | ||
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 | |||
20 | #include "autoconf.h" | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <pthread.h> | ||
24 | |||
25 | #include "kernel.h" | ||
26 | #include <sys/time.h> | ||
27 | |||
28 | #ifdef ROCKBOX_HAS_SIMSOUND | ||
29 | #include "sound.h" | ||
30 | #endif | ||
31 | |||
32 | long current_tick = 0; | ||
33 | extern void sim_tick_tasks(void); | ||
34 | |||
35 | static void msleep(int msec) | ||
36 | { | ||
37 | struct timeval delay; | ||
38 | |||
39 | delay.tv_sec = msec / 1000; | ||
40 | delay.tv_usec = (msec % 1000) * 1000; | ||
41 | select(0, NULL, NULL, NULL, &delay); /* portable sub-second sleep */ | ||
42 | } | ||
43 | |||
44 | /* | ||
45 | * This is not a target thread, so it does not fall under the 1 thread at a | ||
46 | * time thing. | ||
47 | */ | ||
48 | static void update_tick_thread() | ||
49 | { | ||
50 | struct timeval start, now; | ||
51 | long new_tick; | ||
52 | |||
53 | gettimeofday(&start, NULL); | ||
54 | while (1) | ||
55 | { | ||
56 | msleep(5); /* check twice per simulated target tick */ | ||
57 | gettimeofday(&now, NULL); | ||
58 | 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 | { | ||
62 | sim_tick_tasks(); | ||
63 | current_tick = new_tick; | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * 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 | |||
74 | pthread_mutex_t mp; | ||
75 | |||
76 | void init_threads(void) | ||
77 | { | ||
78 | pthread_t tick_tid; | ||
79 | |||
80 | pthread_mutex_init(&mp, NULL); | ||
81 | /* get mutex to only allow one thread running at a time */ | ||
82 | pthread_mutex_lock(&mp); | ||
83 | |||
84 | /* start a tick thread */ | ||
85 | pthread_create(&tick_tid, NULL, (void *(*)(void *)) update_tick_thread, | ||
86 | NULL); | ||
87 | |||
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 | |||
97 | } | ||
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 | |||
104 | void yield(void) | ||
105 | { | ||
106 | pthread_mutex_unlock(&mp); /* return */ | ||
107 | msleep(1); /* prevent busy loop */ | ||
108 | pthread_mutex_lock(&mp); /* get it again */ | ||
109 | } | ||
110 | |||
111 | void newfunc(void (*func)(void)) | ||
112 | { | ||
113 | pthread_mutex_lock(&mp); | ||
114 | func(); | ||
115 | pthread_mutex_unlock(&mp); | ||
116 | } | ||
117 | |||
118 | |||
119 | int create_thread(void (*fp)(void), void* sp, int stk_size) | ||
120 | { | ||
121 | pthread_t tid; | ||
122 | int i; | ||
123 | int error; | ||
124 | |||
125 | /* 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); | ||
136 | |||
137 | yield(); | ||
138 | |||
139 | return error; | ||
140 | } | ||
141 | |||
142 | void sim_sleep(int ticks) | ||
143 | { | ||
144 | pthread_mutex_unlock(&mp); /* return */ | ||
145 | msleep((1000/HZ) * ticks); | ||
146 | pthread_mutex_lock(&mp); /* get it again */ | ||
147 | } | ||
148 | |||