1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 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 (at) 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 */ 234