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, ¶m_rt) );
CHK ( sched_setscheduler (0, SCHED_FIFO, ¶m_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;
}
next 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).