_timer.c
1 /******************************************************************** 2 * Description: _timer.c 3 * timer.cc -- interval timer code. A TIMER object lets you wait 4 * on the expiration of a cyclic period, to the resolution of the 5 * system clock. 6 * 7 * Derived from a work by Fred Proctor & Will Shackleford 8 * 9 * Author: 10 * License: LGPL Version 2 11 * System: Linux 12 * 13 * Copyright (c) 2004 All rights reserved. 14 * 15 * Last change: 16 ********************************************************************/ 17 18 #include "rcs_print.hh" /* rcs_print_error */ 19 20 #include <stdio.h> /* NULL */ 21 #include <errno.h> /* errno */ 22 #include <string.h> /* strerror() */ 23 24 #include <errno.h> /* EINTR */ 25 #include <unistd.h> /* select(), sysconf(), _SC_CLK_TCK */ 26 #include <sys/time.h> /* struct timeval, gettimeofday(), struct 27 itimerval, setitimer(), ITIMER_REAL */ 28 #include <sched.h> 29 30 #include "_timer.h" 31 32 /* number of seconds in a system clock tick */ 33 double clk_tck() 34 { 35 return 1.0 / (double) sysconf(_SC_CLK_TCK); 36 } 37 38 /* 39 These values can be used with a debugger to prevent 40 or deliberately cause timeouts. 41 */ 42 43 int etime_disabled = 0; 44 double etime_disable_time = 0.0; 45 46 /* number of seconds from some epoch, to clock tick resolution */ 47 double etime() 48 { 49 struct timeval tp; 50 double retval; 51 52 if (0 != gettimeofday(&tp, NULL)) { 53 rcs_print_error("etime: can't get time\n"); 54 return 0.0; 55 } 56 57 retval = ((double) tp.tv_sec) + ((double) tp.tv_usec) / 1000000.0; 58 return retval; 59 } 60 61 int esleep_use_yield = 0; 62 63 /* sleeps # of seconds */ 64 void esleep(double seconds_to_sleep) 65 { 66 struct timeval tval; 67 static double clk_tck_val = 0; 68 double total = seconds_to_sleep; /* total sleep asked for */ 69 double started = etime(); /* time when called */ 70 double left = total; 71 if (seconds_to_sleep <= 0.0) 72 return; 73 if (clk_tck_val <= 0) { 74 clk_tck_val = clk_tck(); 75 } 76 do { 77 if (left < clk_tck_val && esleep_use_yield) { 78 sched_yield(); 79 } else { 80 tval.tv_sec = (long) left; /* double->long truncates, ANSI */ 81 tval.tv_usec = (long) ((left - (double) tval.tv_sec) * 1000000.0); 82 if (tval.tv_sec == 0 && tval.tv_usec == 0) { 83 tval.tv_usec = 1; 84 } 85 if (select(0, NULL, NULL, NULL, &tval) < 0) { 86 if (errno != EINTR) { 87 break; 88 } 89 } 90 } 91 left = total - etime() + started; 92 } 93 while (left > 0 && (left > clk_tck_val && esleep_use_yield)); 94 return; 95 } 96 97 void print_etime() 98 { 99 printf("etime = %f\n", etime()); 100 }