/* XBubble - timer.c Copyright (C) 2002 Ivan Djelic This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include /* exit */ #include #include #include struct timeval interval; extern int fps; /* I couldn't find a portable way to get the actual interval timer resolution; typical values are: * ix86 : 10 ms * alpha : 1 ms So I'll stick to a 10ms resolution. If you've got an Alpha CPU you can probably set ITIMER_RESOLUTION to 1000. */ #define ITIMER_RESOLUTION 10000 long get_closest_itimer_interval( long usec ) { if ( usec % ITIMER_RESOLUTION ) return ( usec/ITIMER_RESOLUTION + 1 )*ITIMER_RESOLUTION; return usec; } void start_timer( long usec, void (*handler)(int)) { struct sigaction action; struct itimerval value; /* setup interval timer */ interval.tv_sec = 0; interval.tv_usec = usec; value.it_interval = interval; value.it_value = interval; /* prepare for catching SIGALRM signal */ action.sa_handler = handler; action.sa_flags = 0; sigemptyset(&(action.sa_mask)); if (( sigaction( SIGALRM, &action, NULL ) != 0 )|| ( setitimer( ITIMER_REAL, &value, NULL) < 0 )) { perror( "start_timer"); exit(1); } } void stop_timer() { struct itimerval value; interval.tv_sec = 0; interval.tv_usec = 0; value.it_interval = interval; value.it_value = interval; setitimer( ITIMER_REAL, &value, NULL); } void timer_sleep( long ms ) { long i; for ( i = ms*fps/1000; i > 0; i-- ) pause(); } void block_timer() { sigset_t set; sigemptyset( &set ); sigaddset( &set, SIGALRM ); sigprocmask( SIG_BLOCK, &set, NULL ); } void unblock_timer() { sigset_t set; sigemptyset( &set ); sigaddset( &set, SIGALRM ); sigprocmask( SIG_UNBLOCK, &set, NULL ); }