/ src / libnml / os_intf / _timer.c
_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  }