Hehe, well thanks Norm for looking at the code... no need to mess with
this yourself unless you are of course curious about this quirk.

You are in principle, correct.

However, that rtl_printf() doesn't get factored into anything that affects
the calculation of how long nanosleep slept, and the other simple
computations, including gethrtime() each take only on the order of 50-128
nanosecond on my machine.  All of this doesn't account for the tens of
thousands of lost nanoseconds after *each* call to nanosleep().  My
suspicion is that nanosleep oversleeps due to inherent latency in
programming the motherboard's timer each time.  A better solution, I know,
is to use periodic threads, which program the timer only once (I think..).

I tried what you suggested, just as a proof of concept.

After sleeping for hundreds of thousands of times, without any extraneous
code aside from sleeping and computing the next wakeup time (all of which
should take on the order of hundreds of nanos _tops_), nanosleep still
seems to oversleep on the order of TENS OF THOUSANDS of nanos, per call.
(I verified this by adding up the time slept and then later outputting it
to a printk()  on module termination.. and yes, I did get around the
inability to printk long longs in the kernel by doing some hacking..).


Still no go.  I am going to avoid nanosleep() at all costs due to its
consistent overleeping.  Instead, I will always use periodic tasks, which
don't seem to suffer from this problem (as severely).

-Calin

 On Wed, 24 Apr 2002, Norm
Dresner wrote:

> >From a very brief inspection, I see that the loop contains, in addition to
> the nanosleep invocation,  several calls to gethrtime() and one
> printf_rtl(), all of which contribute to the loop's period.  I think a
> better test would be to have a very simple loop toggling a bit on an output
> port and observing the results on a 'scope or a frequency meter.
>
>     Norm
>
> (As soon as the rush is over, I'd love to take some time and play with
> this.  Maybe July at my current loading.)
>
> ----- Original Message -----
> From: Calin A. Culianu <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Wednesday, April 24, 2002 4:24 PM
> Subject: [rtl] Does nanosleep() oversleep?
>
>
> >
> >
> > What's wrong with this code?  Why does nanosleep() *always* oversleep by
> > not a few nanosecond.. but by like 15 microseconds on a PII-400, per
> > iteration?
> >
> >
> > /*
> >  * Copyright (C) 2002 Calin Culianu
> >  *
> >  * This program is free software; you can redistribute it and/or
> >  * modify it under the terms of the GNU General Public License
> >  * as published by the Free Software Foundation; either version 2
> >  * of the License, or (at your option) any later version.
> >  *
> >  * This program is distributed in the hope that it will be useful,
> >  * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >  * GNU General Public License for more details.
> >  *
> >  * You should have received a copy of the GNU General Public License
> >  * along with this program (see COPYRIGHT file); if not, write to the
> >  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> >  * Boston, MA 02111-1307, USA, or go to their website at
> >  * http://www.gnu.org.
> >  */
> >
> >
> > #include <linux/module.h>
> > #include <linux/kernel.h>
> > #include <linux/version.h>
> > #include <linux/types.h>
> > #include <linux/errno.h>
> >
> > #include <rtl.h>
> > #include <rtl_sched.h>
> >
> > #define MYNAME "nanotest"
> >
> > static void *rt_task (void *arg);
> >
> > static const int n_sleeps = 660;
> > static const hrtime_t ns_bet_sleeps = 1000000;
> >
> > static pthread_t task = 0;          /* main RT task */
> >
> > int init_module(void)
> > {
> >   pthread_attr_t attr;
> >   struct sched_param sched_param;
> >
> >   /* create the realtime task */
> >   pthread_attr_init(&attr);
> >   pthread_attr_setfp_np(&attr, 1);
> >   sched_param.sched_priority = 1;
> >   pthread_attr_setschedparam(&attr, &sched_param);
> >   if ( pthread_create(&task, &attr, rt_task, (void *)0) ) {
> >     return -1;
> >   }
> >
> >   return 0;
> >
> > }
> >
> > void cleanup_module(void)
> > {
> >   /* delete daq_task */
> >   if (task) {
> >     if (!pthread_delete_np(task))
> >       printk (MYNAME ": deleted RT task\n");
> >     else
> >       printk (MYNAME ": cannot find RT task (it died?).\n");
> >   }
> > }
> >
> > /* dummy rt loop to test nanosleep and how much it oversleeps */
> > static void *rt_task (void *arg)
> > {
> >   int n_loops = 0, diff = 0, one_call_to_gethrtime;
> >   hrtime_t projected_wakeup_time = 0, loopstart, nanos_to_sleep, tmp;
> >
> >   tmp = gethrtime();
> >   one_call_to_gethrtime = gethrtime() - tmp;
> >
> >   rtl_printf(MYNAME ": one call to gethrtime() takes %d ns\n",
> >              one_call_to_gethrtime);
> >
> >   do {
> >
> >     loopstart = gethrtime();
> >
> >     if (projected_wakeup_time) /* skips first iteration */
> >       diff += loopstart - projected_wakeup_time;
> >
> >     if ( (++n_loops) % n_sleeps == 0) {
> >       rtl_printf(MYNAME ": cum difference after %d iterations is %d\n",
> >                  n_sleeps, diff);
> >       diff = 0;
> >     }
> >
> >     nanos_to_sleep = ns_bet_sleeps - (gethrtime() - loopstart);
> >     projected_wakeup_time = gethrtime() + nanos_to_sleep;
> >
> >   } while ( !nanosleep (hrt2ts(nanos_to_sleep), NULL) );
> >
> >   return (void *)0;
> > }
> >
> >
> > -- [rtl] ---
> > To unsubscribe:
> > echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
> > echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
> > --
> > For more information on Real-Time Linux see:
> > http://www.rtlinux.org/
> >
>

-- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
--
For more information on Real-Time Linux see:
http://www.rtlinux.org/

Reply via email to