linux-rt-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Hector Perez Tijero <perezh@unican.es>
To: linux-rt-users@vger.kernel.org
Subject: Posix Execution time clock
Date: Tue, 01 Dec 2009 07:14:45 -0500	[thread overview]
Message-ID: <4B1508B5.7030202@unican.es> (raw)

Hi,

My question might be a little basic for this list... Maybe someone could 
point me out to another forum :)

I'm trying to get some measures using the execution time clock in my 
system and I found some slight differences in the use of the 
CLOCK_THREAD_CPUTIME_ID and CLOCK_MONOTONIC clocks. The measures are 
between the same points of code. My concern is that, sometimes, the 
measure obtained with CLOCK_MONOTONIC is lower than using 
CLOCK_THREAD_CPUTIME_ID. Find below a dummy example to test this strange 
behavior.

It doesn't happen very often but the error could be around hundreds of 
microseconds.

So my question is: are both POSIX clocks based on different physical 
clocks? I always though they use the TSC...

My previous guess was that such behavior could be caused by the CPU 
frequency scaling but the same happened when I disabled it.

My system is running Linux 2.6.24-25-rt #1 SMP PREEMPT RT  (Ubuntu 
package) and I run my tests using the affinity parameter to bind all the 
threads included in the test to the same CPU.

Thanks so much and great work

Hector

---

#include <time.h>
#include <pthread.h>
#include <float.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

#define THREAD_CLOCK CLOCK_THREAD_CPUTIME_ID
#define COMMON_CLOCK CLOCK_MONOTONIC

#define LAST_JOB   10000
#define PRIO_HIGH    90

#define MAX_SAFE_STACK (8*1024) /* The maximum stack size which is
                       guaranteed safe to access without
                       faulting */

#define CHK(p) { int ret;                                      \
                 if ((ret = p)) {                   \
                   printf ("Error:"#p":%s\n", strerror (ret)); \
                   exit (-1);                                  \
}                                             \
}

static int error_count = 0;

double timespec_to_double(const struct timespec *time)
{
  return time->tv_nsec*1E-9 + (double)time->tv_sec;
}

void double_to_timespec(double time, struct timespec *ts)
{
  ts->tv_sec = (long) time;
  ts->tv_nsec = (long)((time - (double)ts->tv_sec) * 1E9);
}

void  add_timespec (struct timespec *s,
                    const struct timespec *t1,
                    const struct timespec *t2)
{
  s->tv_sec  = t1->tv_sec  + t2->tv_sec;
  s->tv_nsec = t1->tv_nsec + t2->tv_nsec;
  if (s->tv_nsec >= 1E9) {
    s->tv_sec ++;
    s->tv_nsec -= 1E9;
  }
}

void incr_timespec (struct timespec *t1, const struct timespec *t2)
{
  t1->tv_sec += t2->tv_sec;
  t1->tv_nsec += t2->tv_nsec;
  if (t1->tv_nsec >= 1E9) {
    t1->tv_sec ++;
    t1->tv_nsec -= 1E9;
  }
}

int smaller_or_equal_timespec (const struct timespec *t1,
                                             const struct timespec *t2)
{
  return t1->tv_sec < t2->tv_sec || (t1->tv_sec == t2->tv_sec &&
      t1->tv_nsec <= t2->tv_nsec);
}

int compare_times (float time, struct timespec* start, struct timespec* 
stop)
{
  double diff, start_time, stop_time = 0.0;
 
  start_time = timespec_to_double (start);
  stop_time = timespec_to_double (stop);
 
  diff = stop_time - start_time;
 
  if (time > diff)
  {
    ++error_count;
    printf ("\tError number %d: %7.6f microseconds\n", error_count, 
(time-diff)*1E6);
  }
  return 0;
}

void stack_prefault(void) {

  unsigned char dummy[MAX_SAFE_STACK];

  memset(&dummy, 0, MAX_SAFE_STACK);
  return;
}

int posix_linux_requirements (void) {
  /* Lock memory */
  if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
    perror("mlockall failed");
    return (-1);
  }
 
  /* Pre-fault our stack */
  stack_prefault ();
 
  return 0;
}

void eat (float for_seconds)
{
  struct timespec now, temp, end;
 
  clock_gettime (THREAD_CLOCK, &now);
 
  double_to_timespec (for_seconds, &temp);
  add_timespec (&end, &now, &temp);
 
  do {
    clock_gettime(THREAD_CLOCK, &now);
  }
  while ( smaller_or_equal_timespec (&now, &end) );
}

int main (int argc, char *argv[])
{
  //  Execution Time
  float time = 9E-4;                 //900 microseconds
  struct timespec period = {0, 1.8E6}; //  1.8 milliseconds
  struct sched_param param_rt;
  struct timespec next_activation, start_time, stop_time;
  int count = 0;
 
    
  //  Change policy to SCHED_FIFO and priority to main thread
  param_rt.sched_priority = PRIO_HIGH;
  //CHK ( pthread_setschedparam (pthread_self(), SCHED_FIFO, &param_rt) );
  CHK ( sched_setscheduler (0, SCHED_FIFO, &param_rt) );
 
  //  Set Linux RT-PREEMPT requirements
  CHK ( posix_linux_requirements () );
 
  CHK ( clock_gettime(COMMON_CLOCK, &next_activation) );
 
  for (count = 0; count < LAST_JOB; count++)
  {
 
    CHK (clock_nanosleep(COMMON_CLOCK, TIMER_ABSTIME,
                       &next_activation, NULL));
   
    CHK ( clock_gettime(COMMON_CLOCK, &start_time) );
    //  Do job: execution time clock
    eat (time);
    CHK ( clock_gettime(COMMON_CLOCK, &stop_time) );
    CHK ( compare_times (time, &start_time, &stop_time) );
    //  Compute next activation
    incr_timespec (&next_activation, &period);
  }
  printf ("\nEnd of test\n");
  return 0;
}

             reply	other threads:[~2009-12-01  6:38 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-01 12:14 Hector Perez Tijero [this message]
2009-12-01  9:53 ` Posix Execution time clock Uwe Kleine-König
2009-12-01 12:32 ` Luis Claudio R. Goncalves
2009-12-02  9:01   ` Hector Perez Tijero
2009-12-02 19:08   ` Uwe Kleine-König
2009-12-05  2:23     ` Hector Perez Tijero

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B1508B5.7030202@unican.es \
    --to=perezh@unican.es \
    --cc=linux-rt-users@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).