Re: Question: realtime tasks and the rtc driver in 2.0.x

Martin Cornelius (mac@wiesbaden.aieg.mot.com)
Fri, 15 May 1998 11:50:05 +0200


Paul, many thanks for your help first. You wrote:

> A simple no-thought solution could be to busy loop on gettimeofday().

i had not expected gettimeofday() is that exact. Having had a look into the
kernel source (time.c), i once again think: what a great work is this OS !!! But
busy looping on gettimeofday() under FIFO scheduling will block all other tasks,
right ?> I think you misinterpret things.> If the driver was so broken as to rely
on the timer interrupt like this,> then it would be impossible to use freq. >
100Hz without event pileup.
> Fortunately this is not the case. A 486-33 can typically run a 4096Hz
> rate in a tight read loop without any pileup.

exactly that's what happens with my test program. Just to make clear how i
understand it, here's an excerpt of my source:

***************************************************************
// switch to realtime mode
go_realtime();
// start rtc interrupts
setup_rtc();

while(1) {
unsigned long data,irqs;
if (read(rtc_fd,&data,sizeof(unsigned long))<0) err_exit("read rtc: ");
irqs=data>>8;
if(irqs>1) printf("%ld ",irqs);fflush(stdout);
}
***************************************************************

this is run with root priviledge. The ouput depends on the load of the machine.
If its not heavy loaded (a little network traffic), about once a second a number
appears. If i start compilation of the kernel in another shell, the output
becomes a steady stream of numbers. In any case, there is NEVER a number greater
than 11. ( if i run with OTHER scheduling, of course there are some bigger
numbers)

My interpretation of this is:

when read(rtc_fd,...) is called, and there are no 'piled up' IRQ's, the task is
put in wait queue rtc_wait, and schedule() is called, switching to some other
task. When the nex t interrupt from the rtc arrives, rtc_interrupt() calls
wake_up_interruptible(&rtc_wait). This function, in turn, calls
wake_up_process(). This function calls add_to_runqueue(), which put's my task
back into running state, and sets need_resched to 1, because it's running with
SCHED_FIFO.
However, schedule() is NOT called in the IRQ processing sequence. For this
reason, the task will not get the CPU until the next invocation of schedule(),
which will in any case happen at the next timer-tick. It will also happen if the
system becomes idle, because the idle-task checks for need_resched, or any other
'slow' interrupt occurs.
Up to this event (which might be 10 ms later), there might arrive 10 more IRQ's
from rtc, which will then be reported when read() returns. Of course, on an idle
system this will not happen, because the idle process calls schedule(), but what
i need is a method to reliably sleep for about 4 milliseconds under any load.
Btw, i wrote a little 10 liner that reports the schedule policy of a process, to
be sure my task really runs FIFO scheduled.

> I can send you a little program which will
> allow you to test for the behaviour you want.

if you still think i'm misunderstanding how it works, i'd be very happy about
that.
If i got it right, what do you think about the solution i suggested: register the
driver without SA_INTERRUPT, and do the CMOS_READ inside rtc_interrupt() with
interrupts disabled ? I don't mean this should go in the distribution, i just
want to know if you think it's safe to do that.

--
Martin Cornelius, Electrical Engineer
MOTOROLA AECS Wiesbaden, Germany
Phone: +49-611-3611-283  +49-172-9419066
Fax:   +49-611-3611-266

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu