Re: Re: time is running out
Theo Veenker <[email protected]> Mon, 14 Feb 2005 15:36:39 +0100
| Newsgroups | gmane.linux.real-time.rtlinux.general |
|---|---|
| Message-ID | <[email protected]> |
Der Herr Hofrat wrote: >>>did you check with the latest CVS changes ? >>>I had CLOCK_GPOS running - but I don't see that >>>behavior any longer with the changes (recompiling >>>the kernel and rtlinux) >>> >>>hofrat >> >>I will try after getting the CVS changes. Might take a few days I'm afraid, >>rather busy with more boring stuff. I'll let you know the result. >> > > I think I have the problem located. It happens on all AMD CPUs when > configured as generic 686 because the CLOCK_TICK_RATE for the AMD boxes > seems to be 1189200 instead of 1193100 - so after "correcting" the tick > rate in linux/include/asm-i386/timex.h (at the top of the file) - the > problem is resolved and your test code schows the expeced 0 +/- 32 (on > an idle system - under load the +/- will off course increase). > > pleas cross check on your system if this solves it for you - if it does > not I would need detailed specs from the system (checked here on three > different AMD archs (ELAN SC520, AMD Duron , AMD XP)). I read in linux/include/asm-i386/timex.h #ifdef CONFIG_MELAN # define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */ #else # define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ #endif You've changed the latter setting to 1189200 also? /proc/cpuinfo tells me: vendor_id : GenuineIntel cpu family : 15 model : 1 model name : Intel(R) Celeron(R) CPU 1.80GHz stepping : 3 and in linux/include/linux/autoconf.h I have in the processor type and features section: #define CONFIG_MPENTIUMIII 1 Which means in my case CLOCK_TICK_RATE is set to 1193180. Since on my boxes CLOCK_GPOS runs 151us/s faster than CLOCK_REALTIME the period of CLOCK_GPOS is (1s-151us)/1s times the period of CLOCK_REALTIME: 1193180 * (1s-151us)/1s = 1193000. So I corrected the 1193180 value to 1193000 and recompiled (left the HZ parameter at 1000 for now). And now I also get +/-32 ns (in idle situation). Apparently the definition of CLOCK_TICK_RATE can't be trusted. The real value is board specific. What I don't understand is why is the exact value of CLOCK_TICK_RATE important under RTLinux and apparently not under plain Linux. What is the difference in keeping wall clock time under Linux and RTLinux? Theo P.S. I have modified the test module to also print the 'corrected' CLOCK_TICK_RATE value. See attachment. _______________________________________________ Rtl mailing list [email protected] http://www2.fsmlabs.com/mailman/listinfo/rtl
clktst.c
(text/x-csrc, 1.8 KB)
/*
* clktst.c
*
* Gets CLOCK_REALTIME and CLOCK_GPOS once every second and prints
* the difference between the offsets between the two clock values.
* If the clocks run at the same pace this difference should be zero
* on average.
*
* Also printed is value of CLOCK_TICK_RATE corrected using the
* detected speed difference of CLOCK_REALTIME and CLOCK_GPOS. Of
* course this only makes sence if the actual measurement interval is
* correct.
*
*/
#include <rtl.h>
#include <posix/time.h>
#include <pthread.h>
static pthread_t mythread;
#define INTERVAL 1000000000
static void* testTask(void* arg)
{
hrtime_t realtime, gpostime;
hrtime_t offset, prevoffset;
hrtime_t diff, tickrate;
struct timespec rtres;
struct timespec gpres;
int n;
pthread_make_periodic_np(pthread_self(),
clock_gethrtime(CLOCK_RTL_SCHED), INTERVAL);
clock_getres(CLOCK_REALTIME, &rtres);
clock_getres(CLOCK_GPOS, &gpres);
rtl_printf("rt resolution: %ld ns\n", (long)rtres.tv_nsec);
rtl_printf("gp resolution: %ld ns\n", (long)gpres.tv_nsec);
realtime = clock_gethrtime(CLOCK_REALTIME);
gpostime = clock_gethrtime(CLOCK_GPOS);
prevoffset = offset = gpostime - realtime;
diff = 0;
for (n = 0; ; n++) {
pthread_wait_np();
realtime = clock_gethrtime(CLOCK_REALTIME);
gpostime = clock_gethrtime(CLOCK_GPOS);
offset = gpostime - realtime;
diff = offset - prevoffset;
prevoffset = offset;
tickrate = ((INTERVAL - diff) * CLOCK_TICK_RATE) / INTERVAL;
rtl_printf("%d: %lld %lld\n", n, diff, tickrate);
}
return 0;
}
int init_module(void)
{
pthread_create(&mythread, NULL, testTask, NULL);
return 0;
}
void cleanup_module(void)
{
pthread_cancel(mythread);
pthread_join(mythread, NULL);
}