2001-03-07 10:06:41

by Michael Reinelt

[permalink] [raw]
Subject: nanosleep question

Hi,

I've got a question regarding the nanosleep() system call.

I'm writing a little tool called lcd4linux
(http://lcd4linux.sourceforge.net), where I have to drive displays
connected to the parallel port. I'm doing this in userland, using
outb().

Some of this displays require quite short delays (e.g. 40 microseconds),
which cannot be done with normal nanosleep() because of the 10 msec
timer resolution.

At the moment I implemented by own delay loop using a small assembler
loop similar to the one used in the kernel. This has two disadvantages:
assembler isn't that portable, and the loop has to be calibrated.

I took a look at the nanosleep() implementation in the kernel, and found
that it is possible to get very small delays, but only if I set the
scheduling type to SCHED_RR or SCHED_FIFO.

Here are my questions:

- why are small delays only possible up to 2 msec? what if I needed a
delay of say 5msec? I can't get it?

- how dangerous is it to run a process with SCHED_RR? As far as I
understood the nanosleep man page, it _is_ dangerous (if the process
gets stuck in an endless loop, you can't even kill it if you don't have
a shell which has a higher static priority than the stuck process
itself).

- is it possible to switch between different scheduling modes? I cound
run the program with normal SCHED_OTHER, and switch to SCHED_RR whenever
I need to write data to the parallel port? Does this make sense?

- what's the reason why these small delays is not possible with
SCHED_OTHER?


TIA,
Michael

--
netWorks Vox: +43 316 692396
Michael Reinelt Fax: +43 316 692343
Geisslergasse 4 GSM: +43 676 3079941
A-8045 Graz, Austria e-mail: [email protected]


2001-03-09 20:05:42

by George Anzinger

[permalink] [raw]
Subject: Re: nanosleep question

Michael Reinelt wrote:
>
> Hi,
>
> I've got a question regarding the nanosleep() system call.
>
> I'm writing a little tool called lcd4linux
> (http://lcd4linux.sourceforge.net), where I have to drive displays
> connected to the parallel port. I'm doing this in userland, using
> outb().
>
> Some of this displays require quite short delays (e.g. 40 microseconds),
> which cannot be done with normal nanosleep() because of the 10 msec
> timer resolution.
>
> At the moment I implemented by own delay loop using a small assembler
> loop similar to the one used in the kernel. This has two disadvantages:
> assembler isn't that portable, and the loop has to be calibrated.

Why not use C? As long as you calibrate it, it should do just fine. On
the other hand, since you are looping anyway, why not loop on a system
time of day call and have the loop exit when you have the required time
in hand. These calls have microsecond resolution.
>
> I took a look at the nanosleep() implementation in the kernel, and found
> that it is possible to get very small delays, but only if I set the
> scheduling type to SCHED_RR or SCHED_FIFO.
>
> Here are my questions:
>
> - why are small delays only possible up to 2 msec? what if I needed a
> delay of say 5msec? I can't get it?

The system does these delays by looping in the task. I.e. NO one else
gets to use the time. I, for one, would like to see this go away. See
: http://sourceforge.net/projects/high-res-timers/
In any case the limit is to put "some" bound on the "time out" from
doing useful work.

If you want other times, you can always make more than one call to
nanosleep.
>
> - how dangerous is it to run a process with SCHED_RR? As far as I
> understood the nanosleep man page, it _is_ dangerous (if the process
> gets stuck in an endless loop, you can't even kill it if you don't have
> a shell which has a higher static priority than the stuck process
> itself).

That is the nature of real time. You could code your task to insure
that the father process was of higher priority. This, of course,
assumes that you can continue to communicate with that task via, e.g. X
which is usually running SCHED_OTHER. In other words, to keep control,
you need to have all the tasks in the communication loop at higher (or
at least equal for SCHED_RR) priority than the bad guy.
>
> - is it possible to switch between different scheduling modes? I cound
> run the program with normal SCHED_OTHER, and switch to SCHED_RR whenever
> I need to write data to the parallel port? Does this make sense?

Depends. It is certainly possible. The question is: Can your task
stand the loss of the processor to another task? This is what happens
at normal SCHED_OTHER priority.
>
> - what's the reason why these small delays is not possible with
> SCHED_OTHER?

Just a guess, but I would say because SCHED_OTHER tasks should not be so
time critical.

George

2001-03-10 07:20:21

by Michael Reinelt

[permalink] [raw]
Subject: Re: nanosleep question

george anzinger wrote:
>
> Michael Reinelt wrote:
> >
> > At the moment I implemented by own delay loop using a small assembler
> > loop similar to the one used in the kernel. This has two disadvantages:
> > assembler isn't that portable, and the loop has to be calibrated.
>
> Why not use C? As long as you calibrate it, it should do just fine.
Because the compiler might optimize it away.

> On
> the other hand, since you are looping anyway, why not loop on a system
> time of day call and have the loop exit when you have the required time
> in hand. These calls have microsecond resolution.
I'm afraid they don't (at least with kernel 2.0, I didn't try this with
2.4). They have microsecond resolution, but increment only every 1/HZ.

Someone gave me a hint to loop on rdtsc. I will look into this.

> > - why are small delays only possible up to 2 msec? what if I needed a
> > delay of say 5msec? I can't get it?
>
> If you want other times, you can always make more than one call to
> nanosleep.
Good point!

> The question is: Can your task
> stand the loss of the processor to another task? This is what happens
> at normal SCHED_OTHER priority.

Yes, it can. My delays are 'minimal' values, if it takes longer, there's
no problem apart from the speed of the display update. I have to wait 40
microsecs after every character I send to the display, which makes 3.2
milliseconds for a complete update of a 20x4 display. If every delay
would be 10 msec, the whole update would last 0.8 seconds (which is
unusable).

bye, Michael

--
netWorks Vox: +43 316 692396
Michael Reinelt Fax: +43 316 692343
Geisslergasse 4 GSM: +43 676 3079941
A-8045 Graz, Austria e-mail: [email protected]

2001-03-10 10:06:52

by George Anzinger

[permalink] [raw]
Subject: Re: nanosleep question

Michael Reinelt wrote:
>
> george anzinger wrote:
> >
> > Michael Reinelt wrote:
> > >
> > > At the moment I implemented by own delay loop using a small assembler
> > > loop similar to the one used in the kernel. This has two disadvantages:
> > > assembler isn't that portable, and the loop has to be calibrated.
> >
> > Why not use C? As long as you calibrate it, it should do just fine.
> Because the compiler might optimize it away.

Not if you use volatile on the data type.
>
> > On
> > the other hand, since you are looping anyway, why not loop on a system
> > time of day call and have the loop exit when you have the required time
> > in hand. These calls have microsecond resolution.
> I'm afraid they don't (at least with kernel 2.0, I didn't try this with
> 2.4).

Gosh, I started with 2.2.14 and it does full microsecond resolution.

They have microsecond resolution, but increment only every 1/HZ.
>
> Someone gave me a hint to loop on rdtsc. I will look into this.

This ticks at 1/"cpu MHz", which can be found by: "cat /proc/cpuinfo"
>
> > > - why are small delays only possible up to 2 msec? what if I needed a
> > > delay of say 5msec? I can't get it?
> >
> > If you want other times, you can always make more than one call to
> > nanosleep.
> Good point!

~snip~

George

2001-03-11 11:22:00

by Michael Reinelt

[permalink] [raw]
Subject: Re: nanosleep question

george anzinger wrote:
> > > > At the moment I implemented by own delay loop using a small assembler
> > > > loop similar to the one used in the kernel. This has two disadvantages:
> > > > assembler isn't that portable, and the loop has to be calibrated.
> > >
> > > Why not use C? As long as you calibrate it, it should do just fine.
> > Because the compiler might optimize it away.
>
> Not if you use volatile on the data type.
I did a lost of testing and experimenting, and found the assembler loop
the best solution (it has the finest granualrity even on slower
systems).

> > > the other hand, since you are looping anyway, why not loop on a system
> > > time of day call and have the loop exit when you have the required time
> > > in hand. These calls have microsecond resolution.
> > I'm afraid they don't (at least with kernel 2.0, I didn't try this with
> > 2.4).
>
> Gosh, I started with 2.2.14 and it does full microsecond resolution.

Oh! Shame on me! I must have missed something here!

I could swear that this didn't work for me. I tried it yesterday, you
are right, there is microsecond resolution. Even on an old 2.0.38
kernel...

This solves all my problems. I'll loop on gettimeofday().

Thanks a lot!

Michael

--
netWorks Vox: +43 316 692396
Michael Reinelt Fax: +43 316 692343
Geisslergasse 4 GSM: +43 676 3079941
A-8045 Graz, Austria e-mail: [email protected]