src/timer/linux/SDL_systimer.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SDL_StartTicks
  2. SDL_GetTicks
  3. SDL_Delay
  4. HandleAlarm
  5. SDL_SYS_TimerInit
  6. SDL_SYS_TimerQuit
  7. SDL_SYS_StartTimer
  8. SDL_SYS_StopTimer
  9. RunTimer
  10. SDL_SYS_TimerInit
  11. SDL_SYS_TimerQuit
  12. SDL_SYS_StartTimer
  13. SDL_SYS_StopTimer

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 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     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_systimer.c,v 1.1.2.11 2001/03/21 17:19:56 hercules Exp $";
  26 #endif
  27 
  28 #include <stdio.h>
  29 #include <sys/time.h>
  30 #include <signal.h>
  31 #include <unistd.h>
  32 #include <string.h>
  33 #include <errno.h>
  34 
  35 #include "SDL_error.h"
  36 #include "SDL_timer.h"
  37 #include "SDL_timer_c.h"
  38 
  39 #if defined(DISABLE_THREADS) || defined(FORK_HACK)
  40 #define USE_ITIMER
  41 #endif
  42 
  43 /* The following defines should really be determined at configure time */
  44 
  45 #ifdef linux
  46 /* Linux select() changes its timeout parameter upon return to contain
  47    the remaining time. Most other unixen leave it unchanged or undefined. */
  48 #define SELECT_SETS_REMAINING
  49 #elif defined(__bsdi__) || defined(__FreeBSD__) || defined(__sun__)
  50 #define USE_NANOSLEEP
  51 #endif
  52 
  53 
  54 /* The first ticks value of the application */
  55 static struct timeval start;
  56 
  57 void SDL_StartTicks(void)
     /* [<][>][^][v][top][bottom][index][help] */
  58 {
  59         /* Set first ticks value */
  60         gettimeofday(&start, NULL);
  61 }
  62 
  63 Uint32 SDL_GetTicks (void)
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65         struct timeval now;
  66         Uint32 ticks;
  67 
  68         gettimeofday(&now, NULL);
  69         ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
  70         return(ticks);
  71 }
  72 
  73 void SDL_Delay (Uint32 ms)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75         int was_error;
  76 
  77 #ifdef USE_NANOSLEEP
  78         struct timespec elapsed, tv;
  79 #else
  80         struct timeval tv;
  81 #ifndef SELECT_SETS_REMAINING
  82         Uint32 then, now, elapsed;
  83 #endif
  84 #endif
  85 
  86         /* Set the timeout interval - Linux only needs to do this once */
  87 #ifdef SELECT_SETS_REMAINING
  88         tv.tv_sec = ms/1000;
  89         tv.tv_usec = (ms%1000)*1000;
  90 #elif defined(USE_NANOSLEEP)
  91         elapsed.tv_sec = ms/1000;
  92         elapsed.tv_nsec = (ms%1000)*1000000;
  93 #else
  94         then = SDL_GetTicks();
  95 #endif
  96         do {
  97                 errno = 0;
  98 
  99 #ifdef USE_NANOSLEEP
 100                 tv.tv_sec = elapsed.tv_sec;
 101                 tv.tv_nsec = elapsed.tv_nsec;
 102                 was_error = nanosleep(&tv, &elapsed);
 103 #else
 104 #ifndef SELECT_SETS_REMAINING
 105                 /* Calculate the time interval left (in case of interrupt) */
 106                 now = SDL_GetTicks();
 107                 elapsed = (now-then);
 108                 then = now;
 109                 if ( elapsed >= ms ) {
 110                         break;
 111                 }
 112                 ms -= elapsed;
 113                 tv.tv_sec = ms/1000;
 114                 tv.tv_usec = (ms%1000)*1000;
 115 #endif
 116                 was_error = select(0, NULL, NULL, NULL, &tv);
 117 #endif /* USE_NANOSLEEP */
 118         } while ( was_error && (errno == EINTR) );
 119 }
 120 
 121 #ifdef USE_ITIMER
 122 
 123 static void HandleAlarm(int sig)
     /* [<][>][^][v][top][bottom][index][help] */
 124 {
 125         Uint32 ms;
 126 
 127         if ( SDL_alarm_callback ) {
 128                 ms = (*SDL_alarm_callback)(SDL_alarm_interval);
 129                 if ( ms != SDL_alarm_interval ) {
 130                         SDL_SetTimer(ms, SDL_alarm_callback);
 131                 }
 132         }
 133 }
 134 
 135 int SDL_SYS_TimerInit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 136 {
 137         struct sigaction action;
 138 
 139         /* Set the alarm handler (Linux specific) */
 140         memset(&action, 0, sizeof(action));
 141         action.sa_handler = HandleAlarm;
 142         action.sa_flags = SA_RESTART;
 143         sigemptyset(&action.sa_mask);
 144         sigaction(SIGALRM, &action, NULL);
 145         return(0);
 146 }
 147 
 148 void SDL_SYS_TimerQuit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 149 {
 150         SDL_SetTimer(0, NULL);
 151 }
 152 
 153 int SDL_SYS_StartTimer(void)
     /* [<][>][^][v][top][bottom][index][help] */
 154 {
 155         struct itimerval timer;
 156 
 157         timer.it_value.tv_sec = (SDL_alarm_interval/1000);
 158         timer.it_value.tv_usec = (SDL_alarm_interval%1000)*1000;
 159         timer.it_interval.tv_sec = (SDL_alarm_interval/1000);
 160         timer.it_interval.tv_usec = (SDL_alarm_interval%1000)*1000;
 161         setitimer(ITIMER_REAL, &timer, NULL);
 162         return(0);
 163 }
 164 
 165 void SDL_SYS_StopTimer(void)
     /* [<][>][^][v][top][bottom][index][help] */
 166 {
 167         struct itimerval timer;
 168 
 169         memset(&timer, 0, (sizeof timer));
 170         setitimer(ITIMER_REAL, &timer, NULL);
 171 }
 172 
 173 #else /* USE_ITIMER */
 174 
 175 #include "SDL_thread.h"
 176 
 177 /* Data to handle a single periodic alarm */
 178 static int timer_alive = 0;
 179 static SDL_Thread *timer = NULL;
 180 
 181 static int RunTimer(void *unused)
     /* [<][>][^][v][top][bottom][index][help] */
 182 {
 183         while ( timer_alive ) {
 184                 if ( SDL_timer_running ) {
 185                         SDL_ThreadedTimerCheck();
 186                 }
 187                 SDL_Delay(1);
 188         }
 189         return(0);
 190 }
 191 
 192 /* This is only called if the event thread is not running */
 193 int SDL_SYS_TimerInit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 194 {
 195         timer_alive = 1;
 196         timer = SDL_CreateThread(RunTimer, NULL);
 197         if ( timer == NULL )
 198                 return(-1);
 199         return(SDL_SetTimerThreaded(1));
 200 }
 201 
 202 void SDL_SYS_TimerQuit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 203 {
 204         timer_alive = 0;
 205         if ( timer ) {
 206                 SDL_WaitThread(timer, NULL);
 207                 timer = NULL;
 208         }
 209 }
 210 
 211 int SDL_SYS_StartTimer(void)
     /* [<][>][^][v][top][bottom][index][help] */
 212 {
 213         SDL_SetError("Internal logic error: Linux uses threaded timer");
 214         return(-1);
 215 }
 216 
 217 void SDL_SYS_StopTimer(void)
     /* [<][>][^][v][top][bottom][index][help] */
 218 {
 219         return;
 220 }
 221 
 222 #endif /* USE_ITIMER */

/* [<][>][^][v][top][bottom][index][help] */