• C

What is the most accurate timer on a unix system?

I am simulating the datalink layer between two  entities in a network.

I need to get down to microseconds if possible.

I'm compiling c code on a the gcc compiler.

I basically need to do this.

StartTime = getTime();

loop(   )
  CurrentTime = getTime();
  if(CurrentTime - StartTime > 50 microseconds)
     do this;

Any ideas on the best timer function to use?

Thank you.
Who is Participating?
sunnycoderConnect With a Mentor Commented:
Hi oxygen_728,

minimum assured accuracy that you get from a userspace function on linux is 10ms

However you can use one of the following depending on your needs:

1. use assembly language programming to read the timestamp counter directly
The P3 has a 64-bit timestamp counter that counts cpu clock ticks. Here's how to read out the low 32 bits with gcc:

unsigned int rdtsc()
     unsigned int high, low;

     __asm__ __volatile__ ("rdtsc" : "=a" (low), "=d" (high));
     return low;

The low bits wrap quite quickly, but should work fine for measuring subsecond intervals. One caveat, the TSC is global, so you might end up counting ticks spend in interrupts and other processes.
You can use a similar instruction for your hardware.

2. There is a do_gettimeofday() function availbale inside the kernel ... It has better than microsecond resolution and provides it too !!

3. Use times() or gettimeofday() or clock() function ... But you can get results delayed by upto 10ms .... btw, clock function was meant to measure time taken by the program ...
man 2 times
man gettimeofday
man clock

brettmjohnsonConnect With a Mentor Commented:
Although gettimeofday() supports microsecond resolution, the clocks on most
machines do not tick more than a few hundred times per second, causing the
returned microsecond values from gettimeofday() to jump by large quanta.
idtConnect With a Mentor Commented:
Like Brett.. said, gettimeofday supports usec resolution, but diiferent systems may jump by large increments, run the following test app to test your system.

#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>

const char* TimeToString(const struct tm* t) {
  static char buf[30];
  strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",t);
  return buf;

const char* FormatTime(const struct timeval* v) {
  static char buf[128];
  struct tm t;
  localtime_r(&v->tv_sec, &t);
  sprintf(buf,"%s.%ld", TimeToString(&t),v->tv_usec);
  return buf;

void difftimeval(const struct timeval* v, const struct timeval* w, struct timeval *r) {
  r->tv_sec=(v->tv_sec - w->tv_sec);
  r->tv_usec=(v->tv_usec - w->tv_usec);

int main(void) {
  int i;
  struct timeval v,w,r;
  for(i=0;i<10;i++) {
    //printf("time is now:%s  elapsed:%ld seconds, %ld usecs\n",FormatTime(&v),r.tv_sec,r.tv_usec);
    printf("elapsed:%ld seconds, %ld usecs\n",r.tv_sec,r.tv_usec);
  return 0;

My output is:

elapsed:0 seconds, 1 usecs
elapsed:0 seconds, 56 usecs
elapsed:0 seconds, 4 usecs
elapsed:0 seconds, 4 usecs
elapsed:0 seconds, 3 usecs
elapsed:0 seconds, 4 usecs
elapsed:0 seconds, 3 usecs
elapsed:0 seconds, 4 usecs
elapsed:0 seconds, 3 usecs
elapsed:0 seconds, 3 usecs

Unremark for more verbose date/time output
time is now:2004-04-10 00:17:53.583650  elapsed:0 seconds, 1 usecs
time is now:2004-04-10 00:17:53.583863  elapsed:0 seconds, 213 usecs
time is now:2004-04-10 00:17:53.583872  elapsed:0 seconds, 9 usecs
time is now:2004-04-10 00:17:53.583880  elapsed:0 seconds, 8 usecs
time is now:2004-04-10 00:17:53.583888  elapsed:0 seconds, 8 usecs
time is now:2004-04-10 00:17:53.583895  elapsed:0 seconds, 7 usecs
time is now:2004-04-10 00:17:53.583902  elapsed:0 seconds, 7 usecs
time is now:2004-04-10 00:17:53.583909  elapsed:0 seconds, 7 usecs
time is now:2004-04-10 00:17:53.583917  elapsed:0 seconds, 8 usecs
time is now:2004-04-10 00:17:53.583924  elapsed:0 seconds, 7 usecs

compiled with gcc version 3.2.2 (Mandrake Linux 9.1 3.2.2-3mdk)

oxygen_728Author Commented:
Thanks for the help!
You had posted two identical questions,

One in unix_programming and one in c language.
You accepted my answer in unix_programming language and gave brettmjohnson an assist.
You accepted sunnycoder's answer in c language an gave both brettmjohnson and I an assist.

While your actions are beyone reproach, a true gentleman, you did needlessly spend 500 points that were not required.  You can always post a link to a question in another TA for a small number of points.

Eg. 20 point, Link to 500 point unix question in C.

If this was totally intentional because of the urgency of your request, so be it., however, if this was unintentional, I have no objection to you requesting an adjustment, and having points of the unix_programming question reduced to a small number, does brettmjohnson concur?

Incedently, out of plain curiosity, did you run my test app, and what was the results on your platform?

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.