1/* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2006 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 */ 38static Uint32 timerStart; 39/* Timer running function */ 40void RISCOS_CheckTimer(); 41#else 42#include <pthread.h> 43extern Uint32 riscos_main_thread; 44extern int riscos_using_threads; 45extern Uint32 SDL_ThreadID(); 46extern Uint32 SDL_EventThreadID(void); 47#endif 48 49 50extern void RISCOS_BackgroundTasks(void); 51 52/* The first ticks value of the application */ 53clock_t start; 54 55void SDL_StartTicks(void) 56{ 57 /* Set first ticks value */ 58 start = clock(); 59} 60 61Uint32 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 84void 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 134int SDL_SYS_TimerInit(void) 135{ 136 return(0); 137} 138 139void SDL_SYS_TimerQuit(void) 140{ 141 SDL_SetTimer(0, NULL); 142} 143 144int SDL_SYS_StartTimer(void) 145{ 146 timerStart = SDL_GetTicks(); 147 148 return(0); 149} 150 151void 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 158void 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 */ 187static int timer_alive = 0; 188static SDL_Thread *timer = NULL; 189 190static 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 */ 202int 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 211void SDL_SYS_TimerQuit(void) 212{ 213 timer_alive = 0; 214 if ( timer ) { 215 SDL_WaitThread(timer, NULL); 216 timer = NULL; 217 } 218} 219 220int SDL_SYS_StartTimer(void) 221{ 222 SDL_SetError("Internal logic error: RISC OS uses threaded timer"); 223 return(-1); 224} 225 226void SDL_SYS_StopTimer(void) 227{ 228 return; 229} 230 231#endif /* SDL_THREADS_DISABLED */ 232 233#endif /* SDL_TIMER_RISCOS */ 234