Exemple #1
0
Fichier : 2-3.c Projet : 1587/ltp
int main(void)
{
#ifndef _POSIX_REALTIME_SIGNALS
	printf("_POSIX_REALTIME_SIGNALS is not defined\n");
	return PTS_UNTESTED;
#endif
	sigset_t set;
	struct sigevent ev;
	timer_t tid;
	struct itimerspec its;
	struct timespec tssleep, tsres;
	int overruns;
	int valuensec, intervalnsec, expectedoverruns;
	int fudge;

	if (sigemptyset(&set) != 0) {
		perror("sigemptyset() did not return success\n");
		return PTS_UNRESOLVED;
	}

	if (sigaddset(&set, SIGCONT) != 0) {
		perror("sigaddset() did not return success\n");
		return PTS_UNRESOLVED;
	}

	if (sigprocmask(SIG_SETMASK, &set, NULL) != 0) {
		perror("sigprocmask() did not return success\n");
		return PTS_UNRESOLVED;
	}

	ev.sigev_notify = SIGEV_SIGNAL;
	ev.sigev_signo = SIGCONT;

	/*
	 * create first timer
	 */
	if (timer_create(CLOCK_REALTIME, &ev, &tid) != 0) {
		perror("timer_create() did not return success\n");
		return PTS_UNRESOLVED;
	}

	if (clock_getres(CLOCK_REALTIME, &tsres) != 0) {
		perror("clock_gettime() did not return success\n");
		return PTS_UNRESOLVED;
	}

	if (tsres.tv_sec != 0) {
		printf("Clock resolution in seconds, not nsecs.  Exiting.\n");
		return PTS_UNRESOLVED;
	}

	valuensec = tsres.tv_nsec;
	intervalnsec = 2 * valuensec;
	//expectedoverruns = (1000000000 - valuensec) / intervalnsec;
	expectedoverruns = 1000000000 / intervalnsec - 1;

	printf("value = %d sec, interval = %d nsec, "
	       "expected overruns = %d\n", 1, intervalnsec, expectedoverruns);

	its.it_interval.tv_sec = 0;
	its.it_interval.tv_nsec = intervalnsec;
	its.it_value.tv_sec = 1;
	its.it_value.tv_nsec = 0;
	//its.it_value.tv_sec = 0;
	//its.it_value.tv_nsec = valuensec;

	if (timer_settime(tid, 0, &its, NULL) != 0) {
		perror("timer_settime() did not return success\n");
		return PTS_UNRESOLVED;
	}
	//tssleep.tv_nsec = valuensec + (expectedoverruns*intervalnsec);
	tssleep.tv_nsec = 0;
	tssleep.tv_sec = 2;
	if (nanosleep(&tssleep, NULL) != 0) {
		perror("nanosleep() did not return success\n");
		return PTS_UNRESOLVED;
	}

	/*
	 * Since the overrun count is only meaningful with respect
	 * to a particular timer expiry disable the timer before
	 * un-blocking the signal.  This ensures that there is only
	 * one expiry and it should have a meaningful overrun count.
	 */
	//its.it_interval.tv_sec = 0;
	//its.it_interval.tv_nsec = 0;
	//its.it_value.tv_sec = 0;
	//its.it_value.tv_nsec = 0;
	//if (timer_settime(tid, 0, &its, NULL) != 0) {
	//      perror("timer_settime() did not return success\n");
	//      return PTS_UNRESOLVED;
	//}

	if (sigprocmask(SIG_UNBLOCK, &set, NULL) != 0) {
		perror("sigprocmask() did not return success\n");
		return PTS_UNRESOLVED;
	}

	overruns = timer_getoverrun(tid);
	printf("%d overruns occurred\n", overruns);
	/*
	 * Depending on the clock resolution we may have a few
	 * extra expiries after the nanosleep completes so do
	 * a range check.
	 */
	fudge = expectedoverruns / 100;
	if (overruns >= expectedoverruns && overruns < expectedoverruns + fudge) {
		printf("Test PASSED\n");
		return PTS_PASS;
	}

	printf("FAIL:  %d overruns sent; expected %d\n",
	       overruns, expectedoverruns);
	return PTS_FAIL;
}
Exemple #2
0
/*
 * Opens the specified RS-485 device (i.e. /dev/ttyUSB0), initializes it for
 * DMX operation, and returns its file descriptor.  Returns -1 on error.
 * Displays no device open error messages if quiet is nonzero (other errors and
 * warnings will still be displayed).
 */
dmx_state *dmx_open_ex(char *filename, int quiet, dmx_state *status)
{
	struct serial_struct serinfo;	// Linux-specific serial port settings
	struct termios terminfo;	// Terminal settings
	int actual_rate;		// Actual baud rate achieved
	int mctrl;			// Modem control lines
	int fd;				// File descriptor
	struct timespec res;		// Monotonic clock resolution

	// Open device
	if((fd = open(filename, O_WRONLY)) < 0) {
		if(!quiet) {
			fprintf(stderr, "Error opening %s: %s\n", filename, strerror(errno));
		}
		return NULL;
	}

	// Set the custom baud rate
	if(ioctl(fd, TIOCGSERIAL, &serinfo)) {
		perror("Error getting serial port settings");
		close(fd);
		return NULL;
	}

	serinfo.flags &= ~ASYNC_SPD_MASK;
	serinfo.flags |= ASYNC_SPD_CUST;
	serinfo.custom_divisor = serinfo.baud_base / 250000;
	actual_rate = serinfo.baud_base / serinfo.custom_divisor;

	if(actual_rate != 250000) {
		// Rate is inexact, but within DMX specs
		if(actual_rate > 248756 && actual_rate < 255102) {
			fprintf(stderr, "Warning: actual baud rate is not exactly 250000 (%d)\n", actual_rate);
		} else {
			fprintf(stderr, "Error: actual baud rate is too far from 250000 (%d)\n", actual_rate);
			close(fd);
			return NULL;
		}
	}

	if(ioctl(fd, TIOCSSERIAL, &serinfo)) {
		perror("Error setting serial port settings");
		close(fd);
		return NULL;
	}

	// Set terminal and line settings (echo, stop bits, etc.)
	if(tcgetattr(fd, &terminfo)) {
		perror("Error getting terminal settings");
		close(fd);
		return NULL;
	}

	cfmakeraw(&terminfo);
	terminfo.c_cflag = CS8 | CSTOPB;
	cfsetspeed(&terminfo, B38400); // custom speed will be used instead of 38400

	if(tcsetattr(fd, TCSAFLUSH, &terminfo)) {
		perror("Error setting terminal settings");
		close(fd);
		return NULL;
	}

	// Set control lines low
	mctrl = 0;
	if(ioctl(fd, TIOCMSET, &mctrl)) {
		perror("Error setting handshaking lines");
		close(fd);
		return NULL;
	}


	status->fd = fd;
	status->channels_to_send = DEFAULT_CHANNELS_TO_SEND;
	status->break_time = DEFAULT_BRK;
	status->mark_time = DEFAULT_MAB;
	status->frame_period = DEFAULT_PERIOD;
	status->actual_rate = actual_rate;

	// Initialize rate control
	if(clock_getres(CLOCK_MONOTONIC, &res)) {
		perror("Error: no monotonic clock?");
		close(fd);
		return NULL;
	}
	if(res.tv_sec != 0 || res.tv_nsec > 100000) {
		fprintf(stderr, "Warning: monotonic clock resolution is worse than 100us (%ld.%09lds)\n",
				(long)res.tv_sec, res.tv_nsec);
	}

	status->next_time = malloc(sizeof(struct timespec));
	if(status->next_time == NULL) {
		perror("Error allocating timer memory");
		close(fd);
		return NULL;
	}

	// Make sure the first frame gets sent immediately
	clock_gettime(CLOCK_MONOTONIC, status->next_time);

	return status;
}
Exemple #3
0
void Timer::InitFreq()
{
    clock_getres(CLOCK_MONOTONIC, &gFreq);
}
Exemple #4
0
	/*!
	 * Default constructor.
	 *
	 * \post elapsed() == 0
	 */
	Timer() {
		clock_getres(CLOCK_REALTIME, &start_time);
		freq = (long)(1.0 / (start_time.tv_sec + 0.001*0.001*0.001*start_time.tv_nsec));
	}
Exemple #5
0
static gboolean initialize_caps(struct mcap_mcl *mcl)
{
	struct timespec t1, t2;
	int latencies[SAMPLE_COUNT];
	int latency, avg, dev;
	uint32_t btclock;
	uint16_t btaccuracy;
	int i;
	int retries;

	clock_getres(CLK, &t1);

	_caps.ts_res = time_us(&t1);
	if (_caps.ts_res < 1)
		_caps.ts_res = 1;

	_caps.ts_acc = 20; /* ppm, estimated */

	/* A little exercise before measuing latency */
	clock_gettime(CLK, &t1);
	read_btclock_retry(mcl, &btclock, &btaccuracy);

	/* Read clock a number of times and measure latency */
	avg = 0;
	i = 0;
	retries = MAX_RETRIES;
	while (i < SAMPLE_COUNT && retries > 0) {
		clock_gettime(CLK, &t1);
		if (!read_btclock(mcl, &btclock, &btaccuracy)) {
			retries--;
			continue;
		}
		clock_gettime(CLK, &t2);

		latency = time_us(&t2) - time_us(&t1);
		latencies[i] = latency;
		avg += latency;
		i++;
	}

	if (retries <= 0)
		return FALSE;

	/* Calculate average and deviation */
	avg /= SAMPLE_COUNT;
	dev = 0;
	for (i = 0; i < SAMPLE_COUNT; ++i)
		dev += abs(latencies[i] - avg);
	dev /= SAMPLE_COUNT;

	/* Calculate corrected average, without 'freak' latencies */
	latency = 0;
	for (i = 0; i < SAMPLE_COUNT; ++i) {
		if (latencies[i] > (avg + dev * 6))
			latency += avg;
		else
			latency += latencies[i];
	}
	latency /= SAMPLE_COUNT;

	_caps.latency = latency;
	_caps.preempt_thresh = latency * 4;
	_caps.syncleadtime_ms = latency * 50 / 1000;

	csp_caps_initialized = TRUE;
	return TRUE;
}
Exemple #6
0
/*
 * Calculate a second-aligned starting time for the packet stream.  Busy
 * wait between our calculated interval and dropping the provided packet
 * into the socket.  If we hit our duration limit, bail.
 * We sweep the ports from a->port to a->port_max included.
 * If the two ports are the same we connect() the socket upfront, which
 * almost halves the cost of the sendto() call.
 */
static int
timing_loop(struct _a *a)
{
	struct timespec nexttime, starttime, tmptime;
	long long waited;
	u_int32_t counter;
	long finishtime;
	long send_errors, send_calls;
	/* do not call gettimeofday more than every 20us */
	long minres_ns = 200000;
	int ic, gettimeofday_cycles;
	int cur_port;
	uint64_t n, ns;

	if (clock_getres(CLOCK_REALTIME, &tmptime) == -1) {
		perror("clock_getres");
		return (-1);
	}

	ns = a->interval.tv_nsec;
	if (timespec_ge(&tmptime, &a->interval))
		fprintf(stderr,
		    "warning: interval (%jd.%09ld) less than resolution (%jd.%09ld)\n",
		    (intmax_t)a->interval.tv_sec, a->interval.tv_nsec,
		    (intmax_t)tmptime.tv_sec, tmptime.tv_nsec);
		/* interval too short, limit the number of gettimeofday()
		 * calls, but also make sure there is at least one every
		 * some 100 packets.
		 */
	if ((long)ns < minres_ns/100)
		gettimeofday_cycles = 100;
	else
		gettimeofday_cycles = minres_ns/ns;
	fprintf(stderr,
	    "calling time every %d cycles\n", gettimeofday_cycles);

	if (clock_gettime(CLOCK_REALTIME, &starttime) == -1) {
		perror("clock_gettime");
		return (-1);
	}
	tmptime.tv_sec = 2;
	tmptime.tv_nsec = 0;
	timespec_add(&starttime, &tmptime);
	starttime.tv_nsec = 0;
	if (wait_time(starttime, NULL, NULL) == -1)
		return (-1);
	nexttime = starttime;
	finishtime = starttime.tv_sec + a->duration;

	send_errors = send_calls = 0;
	counter = 0;
	waited = 0;
	ic = gettimeofday_cycles;
	cur_port = a->port;
	if (a->port == a->port_max) {
		if (a->ipv6) {
			if (connect(a->s, (struct sockaddr *)&a->sin6, sizeof(a->sin6))) {
				perror("connect (ipv6)");
				return (-1);
			}
		} else {
			if (connect(a->s, (struct sockaddr *)&a->sin, sizeof(a->sin))) {
				perror("connect (ipv4)");
				return (-1);
			}
		}
	}
	while (1) {
		int ret;

		timespec_add(&nexttime, &a->interval);
		if (--ic <= 0) {
			ic = gettimeofday_cycles;
			if (wait_time(nexttime, &tmptime, &waited) == -1)
				return (-1);
		}
		/*
		 * We maintain and, if there's room, send a counter.  Note
		 * that even if the error is purely local, we still increment
		 * the counter, so missing sequence numbers on the receive
		 * side should not be assumed to be packets lost in transit.
		 * For example, if the UDP socket gets back an ICMP from a
		 * previous send, the error will turn up the current send
		 * operation, causing the current sequence number also to be
		 * skipped.
		 * The counter is incremented only on the initial port number,
		 * so all destinations will see the same set of packets.
		 */
		if (cur_port == a->port && a->packet_len >= 4) {
			be32enc(a->packet, counter);
			counter++;
		}
		if (a->port == a->port_max) { /* socket already bound */
			ret = send(a->s, a->packet, a->packet_len, 0);
		} else {
			a->sin.sin_port = htons(cur_port++);
			if (cur_port > a->port_max)
				cur_port = a->port;
			if (a->ipv6) {
			ret = sendto(a->s, a->packet, a->packet_len, 0,
			    (struct sockaddr *)&a->sin6, sizeof(a->sin6));
			} else {
			ret = sendto(a->s, a->packet, a->packet_len, 0,
				(struct sockaddr *)&a->sin, sizeof(a->sin));
			}
		}
		if (ret < 0)
			send_errors++;
		send_calls++;
		if (a->duration != 0 && tmptime.tv_sec >= finishtime)
			goto done;
	}

done:
	if (clock_gettime(CLOCK_REALTIME, &tmptime) == -1) {
		perror("clock_gettime");
		return (-1);
	}

	printf("\n");
	printf("start:             %jd.%09ld\n", (intmax_t)starttime.tv_sec,
	    starttime.tv_nsec);
	printf("finish:            %jd.%09ld\n", (intmax_t)tmptime.tv_sec,
	    tmptime.tv_nsec);
	printf("send calls:        %ld\n", send_calls);
	printf("send errors:       %ld\n", send_errors);
	printf("approx send rate:  %ld pps\n", (send_calls - send_errors) /
	    a->duration);
	n = send_calls - send_errors;
	if (n > 0) {
		ns = (tmptime.tv_sec - starttime.tv_sec) * 1000000000UL +
			(tmptime.tv_nsec - starttime.tv_nsec);
		n = ns / n;
	}
	printf("time/packet:       %u ns\n", (u_int)n);
	printf("approx error rate: %ld\n", (send_errors / send_calls));
	printf("waited:            %lld\n", waited);
	printf("approx waits/sec:  %lld\n", (long long)(waited / a->duration));
	printf("approx wait rate:  %lld\n", (long long)(waited / send_calls));

	return (0);
}
Exemple #7
0
main()
{

  struct timespec tp1, tp2;
  long timp1, timp2, timp3;
  int i1,i2,x,y;
  int count;
  int s1;
  long double s2;
  long double accum;
  long double accum1;
  struct timespec     clock_resolution;
  int stat;

  
  
  wiringPiSetup () ;
  pinMode (7, INPUT) ;




  printf("Start\n");

     stat = clock_getres(CLOCK_REALTIME, &clock_resolution);
     printf("Clock resolution is %d seconds, %ld nanoseconds\n", clock_resolution.tv_sec, clock_resolution.tv_nsec);


  clock_gettime(CLOCK_REALTIME, &tp1);
  count=0;
   
   while ( count < 200000 ) 
   {
     
     while ( digitalRead(7) == LOW )
     { 
     }
     count++;
      while ( digitalRead(7) == HIGH )
     {
     }
     count++;
    }
  clock_gettime(CLOCK_REALTIME, &tp2);
  s1 = tp2.tv_sec-tp1.tv_sec;

  clock_gettime(CLOCK_REALTIME, &tp1);
  count=0;
   
   while ( count < 200000 ) 
   {
     
     while ( digitalRead(7) == LOW )
     { 
     }
     count++;
      while ( digitalRead(7) == HIGH )
     {
     }
     count++;
    }
  clock_gettime(CLOCK_REALTIME, &tp2);
  s1 = tp2.tv_sec-tp1.tv_sec;


  s2 = tp2.tv_nsec-tp1.tv_nsec;

  

  accum = ( tp2.tv_nsec - tp1.tv_nsec );
  accum1= accum;
  if ( accum<0 )
  {
   accum=accum+1000000000;
   printf(" acumulator atenuat \n");
  }
  accum1=accum1+s1*1000000000;
  printf( "ACCUM %lf \n", accum );
  printf( "!! ACCUM1 %lf !! \n", accum1);

  
   printf(" dif1 calcul scadere secunde %ld \n",s1);
   printf(" dif2 calcul scadere nanosec %ld \n",s2);
   
 
  printf(" Rez citit secunde  %d %d \n",tp1.tv_sec, tp1.tv_nsec);
  printf(" Rez citit nanosec  %ld %lld \n",tp2.tv_sec, tp2.tv_nsec);
  
  printf(" Rez calc     sec %ld \n",tp2.tv_sec-tp1.tv_sec);
  printf(" Rez calc nanosec %ld \n",tp2.tv_nsec-tp1.tv_nsec);

  printf("Stop\n");
  
}
int main(void) {
	pid_t childPid = -1;
	int pipeArr[2];
	int retval = -1;
	struct timespec real_time_res, parentNow, childNow;
	sigset_t mask, oldmask, zeromask;
	struct sigaction sigact;
	union sigval value;

	// Get clock resolution
	clock_getres(CLOCK_REALTIME, &real_time_res);
	printf("Real time clock resolution is: %ld s %ld ns\n", real_time_res.tv_sec, real_time_res.tv_nsec);
	// Create a pipe for parent-child communication
	if (pipe(pipeArr) < 0) {
		perror("pipe");
		exit(EXIT_FAILURE);
	}
	// Install signal handler
	sigemptyset(&sigact.sa_mask);
	sigact.sa_flags = SA_SIGINFO;	// use real-time signal handler
	sigact.sa_sigaction = sigactionHandler;
	sigaction(SIGRTMAX, &sigact, NULL);
	// Block SIGRTMAX signal to prevent race condition
	sigemptyset(&mask); sigemptyset(&zeromask);
	sigaddset(&mask, SIGRTMAX);
	sigprocmask(SIG_BLOCK, &mask, &oldmask);

	// Initialize variables to zero
	memset(&childTimeNow, 0, sizeof(struct timespec));
	memset(&parentNow, 0, sizeof(struct timespec));
	memset(&childNow, 0, sizeof(struct timespec));
	value.sival_int = 0;

	// Fork a child
	childPid = fork();
	if (childPid < 0) {
		perror("fork");
		exit(EXIT_FAILURE);
	} else if (childPid > 0) {
		clock_gettime(CLOCK_REALTIME, &parentNow);
		if (sigqueue(childPid, SIGRTMAX, value) < 0) {
			perror("sigqueue");
			exit(EXIT_FAILURE);
		}
		close(pipeArr[0]);
		if (write(pipeArr[1], &parentNow, sizeof(struct timespec)) < 0) {
			perror("write");
			exit(EXIT_FAILURE);
		}
		close(pipeArr[1]);
		wait(NULL);
		printf("Child terminated\n");
		exit(EXIT_SUCCESS);
	} else {
		sigprocmask(SIG_SETMASK, &oldmask, NULL);
		while(n < 1)
			sigsuspend(&zeromask);
		retval = read(pipeArr[0], &childNow, sizeof(struct timespec));
		if (retval < 0) {
			perror("read");
			exit(EXIT_FAILURE);
		}
		else {
			// Calculate real-time signal delivery delay and display the delay in microsecond
			printf("Real time signal delivery delay: %ld s %ld us\n",
					(childTimeNow.tv_sec - childNow.tv_sec), (childTimeNow.tv_nsec - childNow.tv_nsec)/1000);
		}
		exit(EXIT_SUCCESS);
	}

	return EXIT_SUCCESS;
}
Exemple #9
0
void main(int argc, char* argv[])
{

//  struct timespec tp1, tp2;
  long timp1, timp2, timp3;
  int i1,i2,x,y;
  int s1;
  long double s2;
  long double accum;
  long double accum1;
  float rb;
  float ra;
  struct timespec     clock_resolution;
  int stat;
  unsigned int cycle1;

  
  wiringPiSetup () ;
  pinMode (tsl_pin, INPUT) ;
//  cycle1=100;
//  printf("COnversie %d ",atoi(argv[0]));
  printf("COnversie parametru %d \n",atoi(argv[1]));
//  printf("COnversie %d ",atoi(argv[3]));
  cycle1=atoi(argv[1]);

  printf("Start\n");
  printf(" Cycles = %d \n",cycle1);
  stat = clock_getres(CLOCK_REALTIME, &clock_resolution);
  printf("Clock resolution is %d seconds, %ld nanoseconds\n", clock_resolution.tv_sec, clock_resolution.tv_nsec);




//actual readout - gettime/ loop untill "cycles" counts are met / gettime again and make diff

  clock_gettime(CLOCK_REALTIME, &tp1);
  count_wait_tsl(cycle1);
  clock_gettime(CLOCK_REALTIME, &tp2);
  

// here frequency should be computed and converted to uW/cm2 .  1khz = 1 uW/m2
  ra=time_diff(tp1,tp2)/1000;
  rb=cycle1*500000/ra;
  printf("Frequency is : %f \n",ra);   
  printf("Power is : %f uW/cm2\n",rb);   
 
//Just verification prints

  printf(" Rezultat %ld \n",time_diff(tp1,tp2));
  printf("Sec2 %d \n",tp2.tv_sec);
  printf("Sec1 %d \n",tp1.tv_sec);
  printf("NANO Sec2 %ld \n",tp2.tv_nsec);
  printf("NANO Sec1 %ld \n",tp1.tv_nsec);
  printf(" REZ  %ld \n",tp2.tv_nsec-tp1.tv_nsec+1000000000*(tp2.tv_sec-tp1.tv_sec));
 
//----------------------------

//actual readout - gettime/ loop untill "cycles" counts are met / gettime again and make diff
cycle1=cycle1*2;

  clock_gettime(CLOCK_REALTIME, &tp1);
  count_wait_tsl(cycle1);
  clock_gettime(CLOCK_REALTIME, &tp2);
  

// here frequency should be computed and converted to uW/cm2 .  1khz = 1 uW/m2
  ra=time_diff(tp1,tp2)/1000;
  rb=cycle1*500000/ra;
  printf("Frequency is : %f \n",ra);   
  printf("Power is : %f uW/cm2\n",rb);   
 
//Just verification prints

  printf(" Rezultat %ld \n",time_diff(tp1,tp2));
  printf("Sec2 %d \n",tp2.tv_sec);
  printf("Sec1 %d \n",tp1.tv_sec);
  printf("NANO Sec2 %ld \n",tp2.tv_nsec);
  printf("NANO Sec1 %ld \n",tp1.tv_nsec);
  printf(" REZ  %ld \n",tp2.tv_nsec-tp1.tv_nsec+1000000000*(tp2.tv_sec-tp1.tv_sec));



  printf("Stop\n");
  
}
Exemple #10
0
void
sys_init_time(ErtsSysInitTimeResult *init_resp)
{
#if defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT)
    int major, minor, build, vsn;
#endif
#if defined(ERTS_MACH_CLOCKS)
    mach_clocks_init();
#endif
#if !defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT)

    init_resp->have_os_monotonic_time = 0;

#else /* defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT) */

#ifdef ERTS_HAVE_CORRECTED_OS_MONOTONIC_TIME
    init_resp->have_corrected_os_monotonic_time = 1;
#else
    init_resp->have_corrected_os_monotonic_time = 0;
#endif

    init_resp->os_monotonic_time_info.resolution = (Uint64) 1000*1000*1000;
#if defined(HAVE_CLOCK_GETRES) && defined(MONOTONIC_CLOCK_ID)
    {
	struct timespec ts;
	if (clock_getres(MONOTONIC_CLOCK_ID, &ts) == 0) {
	    if (ts.tv_sec == 0 && ts.tv_nsec != 0)
		init_resp->os_monotonic_time_info.resolution /= ts.tv_nsec;
	    else if (ts.tv_sec >= 1)
		init_resp->os_monotonic_time_info.resolution = 1;
	}
    }
#elif defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(MONOTONIC_CLOCK_ID)
    init_resp->os_monotonic_time_info.resolution
	= mach_clock_getres(&internal_state.r.o.mach.clock.monotonic);
#endif

#ifdef MONOTONIC_CLOCK_ID_STR
    init_resp->os_monotonic_time_info.clock_id = MONOTONIC_CLOCK_ID_STR;
#else
    init_resp->os_monotonic_time_info.clock_id = NULL;
#endif

    init_resp->os_monotonic_time_info.locked_use = 0;

#if defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)
    init_resp->os_monotonic_time_info.func = "clock_gettime";
#elif defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME)
    init_resp->os_monotonic_time_info.func = "clock_get_time";
#elif defined(OS_MONOTONIC_TIME_USING_GETHRTIME)
    init_resp->os_monotonic_time_info.func = "gethrtime";
#elif defined(OS_MONOTONIC_TIME_USING_TIMES)
    init_resp->os_monotonic_time_info.func = "times";
#else
# error Unknown erts_os_monotonic_time() implementation
#endif

    init_resp->have_os_monotonic_time = 1;

    os_version(&major, &minor, &build);

    vsn = ERTS_MK_VSN_INT(major, minor, build);


#if defined(__linux__) && defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)
    if (vsn >= ERTS_MK_VSN_INT(2, 6, 33)) {
	erts_sys_time_data__.r.o.os_monotonic_time =
	    clock_gettime_monotonic;
#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
	erts_sys_time_data__.r.o.os_times =
	    clock_gettime_times;
#endif
    }
    else {
	/*
	 * Linux versions prior to 2.6.33 have a
	 * known bug that sometimes cause the NTP
	 * adjusted monotonic clock to take small
	 * steps backwards. Use raw monotonic clock
	 * if it is present; otherwise, fall back
	 * on locked verification of values.
	 */
	init_resp->have_corrected_os_monotonic_time = 0;
#if defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
	/* We know that CLOCK_MONOTONIC_RAW is defined,
	   but we don't know if we got a kernel that
	   supports it. Support for CLOCK_MONOTONIC_RAW
	   appeared in kernel 2.6.28... */
	if (vsn >= ERTS_MK_VSN_INT(2, 6, 28)) {
	    erts_sys_time_data__.r.o.os_monotonic_time =
		clock_gettime_monotonic_raw;
#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
	    erts_sys_time_data__.r.o.os_times =
		clock_gettime_times_raw;
#endif
	    init_resp->os_monotonic_time_info.clock_id =
		"CLOCK_MONOTONIC_RAW";
	}
	else
#endif /* defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW) */
	{
	    erts_sys_time_data__.r.o.os_monotonic_time =
		clock_gettime_monotonic_verified;
#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
	    erts_sys_time_data__.r.o.os_times =
		clock_gettime_times_verified;
#endif
	    erts_smp_mtx_init(&internal_state.w.f.mtx,
			      "os_monotonic_time");
	    internal_state.w.f.last_delivered
		= clock_gettime_monotonic();
	    init_resp->os_monotonic_time_info.locked_use = 1;
	}
    }
#else /* !(defined(__linux__) && defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)) */
    {
	char flavor[1024];

	os_flavor(flavor, sizeof(flavor));

	if (sys_strcmp(flavor, "sunos") == 0) {
	    /*
	     * Don't trust hrtime on multi processors
	     * on SunOS prior to SunOS 5.8
	     */
	    if (vsn < ERTS_MK_VSN_INT(5, 8, 0)) {
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
		if (sysconf(_SC_NPROCESSORS_CONF) > 1)
#endif
		    init_resp->have_os_monotonic_time = 0;
	    }
	}
    }
#endif /* !(defined(__linux__) && defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)) */

#endif /* defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT) */

#ifdef ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
    init_resp->os_monotonic_time_unit = ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT;
#endif
    init_resp->sys_clock_resolution = SYS_CLOCK_RESOLUTION;

    /* 
     * This (erts_sys_time_data__.r.o.ticks_per_sec) is only for
     * times() (CLK_TCK), the resolution is always one millisecond..
     */
    if ((erts_sys_time_data__.r.o.ticks_per_sec = TICKS_PER_SEC()) < 0)
	erl_exit(ERTS_ABORT_EXIT, "Can't get clock ticks/sec\n");
    
#if defined(OS_MONOTONIC_TIME_USING_TIMES)
#if ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
#  error Time unit is supposed to be determined at runtime...
#endif
    {
	ErtsMonotonicTime resolution = erts_sys_time_data__.r.o.ticks_per_sec;
	ErtsMonotonicTime time_unit = resolution;
	int shift = 0;

	while (time_unit < 1000*1000) {
	    time_unit <<= 1;
	    shift++;
	}

	init_resp->os_monotonic_time_info.resolution = resolution;
	init_resp->os_monotonic_time_unit = time_unit;
	init_resp->os_monotonic_time_info.extended = 1;
	internal_state.r.o.times_shift = shift;

	erts_init_os_monotonic_time_extender(&internal_state.wr.m.os_mtime_xtnd,
					     get_tick_count,
					     (1 << 29) / resolution);
    }
#endif /* defined(OS_MONOTONIC_TIME_USING_TIMES) */

#ifdef WALL_CLOCK_ID_STR
    init_resp->os_system_time_info.clock_id = WALL_CLOCK_ID_STR;
#else
    init_resp->os_system_time_info.clock_id = NULL;
#endif

    init_resp->os_system_time_info.locked_use = 0;
    init_resp->os_system_time_info.resolution = (Uint64) 1000*1000*1000;
#if defined(HAVE_CLOCK_GETRES) && defined(WALL_CLOCK_ID)
    {
	struct timespec ts;
	if (clock_getres(WALL_CLOCK_ID, &ts) == 0) {
	    if (ts.tv_sec == 0 && ts.tv_nsec != 0)
		init_resp->os_system_time_info.resolution /= ts.tv_nsec;
	    else if (ts.tv_sec >= 1)
		init_resp->os_system_time_info.resolution = 1;
	}
    }
#elif defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(WALL_CLOCK_ID)
    init_resp->os_system_time_info.resolution
	= mach_clock_getres(&internal_state.r.o.mach.clock.wall);
#endif

#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
    init_resp->os_system_time_info.func = "clock_gettime";
#elif defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME)
    init_resp->os_system_time_info.func = "clock_get_time";
#elif defined(OS_SYSTEM_TIME_GETTIMEOFDAY)
    init_resp->os_system_time_info.func = "gettimeofday";    
    init_resp->os_system_time_info.resolution = 1000*1000;
    init_resp->os_system_time_info.clock_id = NULL;
#else
#  error Missing erts_os_system_time() implementation
#endif

}
int
main (void)
{
  struct timespec ts;
  timer_t timer_sig, timer_thr1, timer_thr2;
  int retval;
  struct sigevent sigev1 =
  {
    .sigev_notify = SIGEV_SIGNAL,
    .sigev_signo = ZSIGALRM
  };
  struct sigevent sigev2 =
  {
    .sigev_notify = SIGEV_THREAD,
    ._sigev_un =
    {
      ._sigev_thread =
      {
	._function = notify_func
      }
    }
  };
  struct itimerspec itimer1 = { { 0, 200000000 }, { 0, 200000000 } };
  struct itimerspec itimer2 = { { 0, 100000000 }, { 0, 500000000 } };
  struct itimerspec itimer3 = { { 0, 150000000 }, { 0, 300000000 } };
  struct itimerspec old;

  retval = clock_gettime (CLOCK_REALTIME, &ts);

  setvbuf (stdout, 0, _IOLBF, 0);

  printf ("clock_gettime returned %d, timespec = { %ld, %ld }\n",
	  retval, ts.tv_sec, ts.tv_nsec);

  retval = clock_getres (CLOCK_REALTIME, &ts);

  printf ("clock_getres returned %d, timespec = { %ld, %ld }\n",
	  retval, ts.tv_sec, ts.tv_nsec);

  timer_create (CLOCK_REALTIME, &sigev1, &timer_sig);
  timer_create (CLOCK_REALTIME, &sigev2, &timer_thr1);
  timer_create (CLOCK_REALTIME, &sigev2, &timer_thr2);

  timer_settime (timer_thr1, 0, &itimer2, &old);
  timer_settime (timer_thr2, 0, &itimer3, &old);

  signal (ZSIGALRM, signal_func);

  timer_settime (timer_sig, 0, &itimer1, &old);

  timer_delete (-1);

  intr_sleep (3);

  timer_delete (timer_sig);
  timer_delete (timer_thr1);

  intr_sleep (3);

  timer_delete (timer_thr2);

  return 0;
}