e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 Sam Lantinga |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with this library; if not, write to the Free Software |
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | |
19 | Sam Lantinga |
20 | slouken@libsdl.org |
21 | */ |
22 | #include "SDL_config.h" |
23 | |
24 | #ifdef SDL_TIMER_RISCOS |
25 | |
26 | #include <stdio.h> |
27 | #include <time.h> |
28 | #include <sys/time.h> |
29 | #include <unistd.h> |
30 | #include <string.h> |
31 | #include <errno.h> |
32 | |
33 | #include "SDL_timer.h" |
34 | #include "../SDL_timer_c.h" |
35 | |
36 | #if SDL_THREADS_DISABLED |
37 | /* Timer SDL_arraysize(Timer ),start/reset time */ |
38 | static Uint32 timerStart; |
39 | /* Timer running function */ |
40 | void RISCOS_CheckTimer(); |
41 | #else |
42 | #include <pthread.h> |
43 | extern Uint32 riscos_main_thread; |
44 | extern int riscos_using_threads; |
45 | extern Uint32 SDL_ThreadID(); |
46 | extern Uint32 SDL_EventThreadID(void); |
47 | #endif |
48 | |
49 | |
50 | extern void RISCOS_BackgroundTasks(void); |
51 | |
52 | /* The first ticks value of the application */ |
53 | clock_t start; |
54 | |
55 | void SDL_StartTicks(void) |
56 | { |
57 | /* Set first ticks value */ |
58 | start = clock(); |
59 | } |
60 | |
61 | Uint32 SDL_GetTicks (void) |
62 | { |
63 | clock_t ticks; |
64 | |
65 | ticks=clock()-start; |
66 | |
67 | |
68 | #if CLOCKS_PER_SEC == 1000 |
69 | |
70 | return(ticks); |
71 | |
72 | #elif CLOCKS_PER_SEC == 100 |
73 | |
74 | return (ticks * 10); |
75 | |
76 | #else |
77 | |
78 | return ticks*(1000/CLOCKS_PER_SEC); |
79 | |
80 | #endif |
81 | |
82 | } |
83 | |
84 | void SDL_Delay (Uint32 ms) |
85 | { |
86 | Uint32 now,then,elapsed; |
87 | #if !SDL_THREADS_DISABLED |
88 | int is_event_thread; |
89 | if (riscos_using_threads) |
90 | { |
91 | is_event_thread = 0; |
92 | if (SDL_EventThreadID()) |
93 | { |
94 | if (SDL_EventThreadID() == SDL_ThreadID()) is_event_thread = 1; |
95 | } else if (SDL_ThreadID() == riscos_main_thread) is_event_thread = 1; |
96 | } else is_event_thread = 1; |
97 | #endif |
98 | |
99 | /*TODO: Next version of Unixlib may allow us to use usleep here */ |
100 | /* for non event threads */ |
101 | |
102 | /* Set the timeout interval - Linux only needs to do this once */ |
103 | then = SDL_GetTicks(); |
104 | |
105 | do { |
106 | /* Do background tasks required while sleeping as we are not multithreaded */ |
107 | #if SDL_THREADS_DISABLED |
108 | RISCOS_BackgroundTasks(); |
109 | #else |
110 | /* For threaded build only run background tasks in event thread */ |
111 | if (is_event_thread) RISCOS_BackgroundTasks(); |
112 | #endif |
113 | |
114 | /* Calculate the time interval left (in case of interrupt) */ |
115 | now = SDL_GetTicks(); |
116 | elapsed = (now-then); |
117 | then = now; |
118 | if ( elapsed >= ms ) { |
119 | break; |
120 | } |
121 | ms -= elapsed; |
122 | #if !SDL_THREADS_DISABLED |
123 | /* Need to yield to let other threads have a go */ |
124 | if (riscos_using_threads) pthread_yield(); |
125 | #endif |
126 | |
127 | } while ( 1 ); |
128 | } |
129 | |
130 | #if SDL_THREADS_DISABLED |
131 | |
132 | /* Non-threaded version of timer */ |
133 | |
134 | int SDL_SYS_TimerInit(void) |
135 | { |
136 | return(0); |
137 | } |
138 | |
139 | void SDL_SYS_TimerQuit(void) |
140 | { |
141 | SDL_SetTimer(0, NULL); |
142 | } |
143 | |
144 | int SDL_SYS_StartTimer(void) |
145 | { |
146 | timerStart = SDL_GetTicks(); |
147 | |
148 | return(0); |
149 | } |
150 | |
151 | void SDL_SYS_StopTimer(void) |
152 | { |
153 | /* Don't need to do anything as we use SDL_timer_running |
154 | to detect if we need to check the timer */ |
155 | } |
156 | |
157 | |
158 | void RISCOS_CheckTimer() |
159 | { |
160 | if (SDL_timer_running && SDL_GetTicks() - timerStart >= SDL_alarm_interval) |
161 | { |
162 | Uint32 ms; |
163 | |
164 | ms = SDL_alarm_callback(SDL_alarm_interval); |
165 | if ( ms != SDL_alarm_interval ) |
166 | { |
167 | if ( ms ) |
168 | { |
169 | SDL_alarm_interval = ROUND_RESOLUTION(ms); |
170 | } else |
171 | { |
172 | SDL_alarm_interval = 0; |
173 | SDL_timer_running = 0; |
174 | } |
175 | } |
176 | if (SDL_alarm_interval) timerStart = SDL_GetTicks(); |
177 | } |
178 | } |
179 | |
180 | #else |
181 | |
182 | /* Threaded version of timer - based on code for linux */ |
183 | |
184 | #include "SDL_thread.h" |
185 | |
186 | /* Data to handle a single periodic alarm */ |
187 | static int timer_alive = 0; |
188 | static SDL_Thread *timer = NULL; |
189 | |
190 | static int RunTimer(void *unused) |
191 | { |
192 | while ( timer_alive ) { |
193 | if ( SDL_timer_running ) { |
194 | SDL_ThreadedTimerCheck(); |
195 | } |
196 | SDL_Delay(1); |
197 | } |
198 | return(0); |
199 | } |
200 | |
201 | /* This is only called if the event thread is not running */ |
202 | int SDL_SYS_TimerInit(void) |
203 | { |
204 | timer_alive = 1; |
205 | timer = SDL_CreateThread(RunTimer, NULL); |
206 | if ( timer == NULL ) |
207 | return(-1); |
208 | return(SDL_SetTimerThreaded(1)); |
209 | } |
210 | |
211 | void SDL_SYS_TimerQuit(void) |
212 | { |
213 | timer_alive = 0; |
214 | if ( timer ) { |
215 | SDL_WaitThread(timer, NULL); |
216 | timer = NULL; |
217 | } |
218 | } |
219 | |
220 | int SDL_SYS_StartTimer(void) |
221 | { |
222 | SDL_SetError("Internal logic error: RISC OS uses threaded timer"); |
223 | return(-1); |
224 | } |
225 | |
226 | void SDL_SYS_StopTimer(void) |
227 | { |
228 | return; |
229 | } |
230 | |
231 | #endif /* SDL_THREADS_DISABLED */ |
232 | |
233 | #endif /* SDL_TIMER_RISCOS */ |