* timing code in 2.6.1
@ 2004-01-16 16:51 Richard B. Johnson
2004-01-16 23:31 ` Andrew Morton
0 siblings, 1 reply; 5+ messages in thread
From: Richard B. Johnson @ 2004-01-16 16:51 UTC (permalink / raw)
To: Linux kernel
Some drivers are being re-written for 2.6++. The following
construct seems to work for "waiting for an event" in
the kernel modules.
// No locks are being held
tim = jiffies + EVENT_TIMEOUT;
while(!event() && time_before(jiffies, tim))
schedule_timeout(0);
Is there anything wrong?
Do I have to execute "set_current_state(TASK_INTERRUPTIBLE)" before?
Do I have to execute "set_current_state(TASK_RUNNING)" after?
I don't want to have to change this again so I really need to
know. For instance, if I execute "set_current_state(TASK_INTERRUPTIBLE)"
in version 2.4.24, it didn't hurt anything. In 2.6.1, there are
conditions where schedule_timeout(0) doesn't return if another
task is spinning "while(1) ; ". This is NotGood(tm).
Cheers,
Dick Johnson
Penguin : Linux version 2.4.24 on an i686 machine (797.90 BogoMips).
Note 96.31% of all statistics are fiction.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: timing code in 2.6.1
2004-01-16 16:51 timing code in 2.6.1 Richard B. Johnson
@ 2004-01-16 23:31 ` Andrew Morton
2004-01-19 14:11 ` Richard B. Johnson
0 siblings, 1 reply; 5+ messages in thread
From: Andrew Morton @ 2004-01-16 23:31 UTC (permalink / raw)
To: root; +Cc: linux-kernel
"Richard B. Johnson" <root@chaos.analogic.com> wrote:
>
>
> Some drivers are being re-written for 2.6++. The following
> construct seems to work for "waiting for an event" in
> the kernel modules.
>
> // No locks are being held
> tim = jiffies + EVENT_TIMEOUT;
> while(!event() && time_before(jiffies, tim))
> schedule_timeout(0);
>
> Is there anything wrong?
This is not a good thing to be doing. You should add this task to a
waitqueue and then sleep. Make the code which causes event() to come true
deliver a wake_up to that waitqueue. There are many examples of this in
the kernel.
If the hardware only supports polling then gee, you'd be best off spinning
for a few microseconds then fall into a schedule_timeout(1) polling loop.
Or something like that. Or make the hardware designer write the damn
driver.
> Do I have to execute "set_current_state(TASK_INTERRUPTIBLE)" before?
> Do I have to execute "set_current_state(TASK_RUNNING)" after?
>
> I don't want to have to change this again so I really need to
> know. For instance, if I execute "set_current_state(TASK_INTERRUPTIBLE)"
> in version 2.4.24, it didn't hurt anything. In 2.6.1, there are
> conditions where schedule_timeout(0) doesn't return if another
> task is spinning "while(1) ; ". This is NotGood(tm).
As you have it, you may as well be calling schedule() inside that loop.
You _have_ to be in state TASK_RUNNING, else you'll sleep forever.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: timing code in 2.6.1
2004-01-16 23:31 ` Andrew Morton
@ 2004-01-19 14:11 ` Richard B. Johnson
2004-01-20 9:59 ` George Anzinger
2004-01-22 2:26 ` Jamie Lokier
0 siblings, 2 replies; 5+ messages in thread
From: Richard B. Johnson @ 2004-01-19 14:11 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel
On Fri, 16 Jan 2004, Andrew Morton wrote:
> "Richard B. Johnson" <root@chaos.analogic.com> wrote:
> >
> >
> > Some drivers are being re-written for 2.6++. The following
> > construct seems to work for "waiting for an event" in
> > the kernel modules.
> >
> > // No locks are being held
> > tim = jiffies + EVENT_TIMEOUT;
> > while(!event() && time_before(jiffies, tim))
> > schedule_timeout(0);
> >
> > Is there anything wrong?
>
> This is not a good thing to be doing. You should add this task to a
> waitqueue and then sleep. Make the code which causes event() to come true
> deliver a wake_up to that waitqueue. There are many examples of this in
> the kernel.
>
Huh? The code that causes "event()" needs to get the CPU occasionally
to check for the event. The hardware doesn't produce an interrupt
upon that event.
> If the hardware only supports polling then gee, you'd be best off spinning
> for a few microseconds then fall into a schedule_timeout(1) polling loop.
> Or something like that. Or make the hardware designer write the damn
> driver.
The poll will almost never be true when first called. Spinning and
wasting CPU cycles that can be used by another task isn't a good
idea.
The hardware designer has designed the hardware according to
the requirements dictated by a government agency (the FDA).
There was no requirement to make interface code simple. The
interface code must check for multiple failure modes during
every specific operation. Both the hardware and software
check for these modes so that no single failure can cause
injury to a patient. This is SOP for medical equipment.
In the specific case, we operate a patient table. The operator
presses an UP and DOWN button. These will produce interrupts.
When an UP button is hit, thousands of interrupts are generated.
This is because it is a mechanical operation. The same is true
for the DOWN button. These events are filtered to determine
the true intervals for "UP", "NOTHING", and "DOWN". When the
"UP" button is pressed, the CPU servos position information
from another driver and motor speed to to move the table to
the commanded position. If the button is pressed for a short
period of time, the table moves slowly. If it is pressed for
a longer period, it moves quickly. It must accellerate according
to a schedule and decellerate according to a schedule so that
patients that weigh 350 lbs and patients that weigh 45 lbs are
accellerated and decellerated at the same rate.
When the table is being moved, 12 different parameters are
monitored. At least two parameters are actually calculated
and filtered to predict where the patient will be if the
button is released.
So, this cannot be dismissed as "get the hardware designer
to write the same driver..."
Writing software often requires knowing about the whole sustem.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.24 on an i686 machine (797.90 BogoMips).
Note 96.31% of all statistics are fiction.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: timing code in 2.6.1
2004-01-19 14:11 ` Richard B. Johnson
@ 2004-01-20 9:59 ` George Anzinger
2004-01-22 2:26 ` Jamie Lokier
1 sibling, 0 replies; 5+ messages in thread
From: George Anzinger @ 2004-01-20 9:59 UTC (permalink / raw)
To: root; +Cc: Andrew Morton, linux-kernel
Richard B. Johnson wrote:
> On Fri, 16 Jan 2004, Andrew Morton wrote:
>
>
>>"Richard B. Johnson" <root@chaos.analogic.com> wrote:
>>
>>>
>>>Some drivers are being re-written for 2.6++. The following
>>>construct seems to work for "waiting for an event" in
>>>the kernel modules.
>>>
>>> // No locks are being held
>>> tim = jiffies + EVENT_TIMEOUT;
>>> while(!event() && time_before(jiffies, tim))
>>> schedule_timeout(0);
>>>
>>>Is there anything wrong?
>>
>>This is not a good thing to be doing. You should add this task to a
>>waitqueue and then sleep. Make the code which causes event() to come true
>>deliver a wake_up to that waitqueue. There are many examples of this in
>>the kernel.
>>
>
>
> Huh? The code that causes "event()" needs to get the CPU occasionally
> to check for the event. The hardware doesn't produce an interrupt
> upon that event.
THAT is where the hardware designer went wrong. An interrupt is really the best
way for hardware to notify the cpu of an event. Details may then be read from
hardware registers, if needed.
The request of a 0 timeout is really asking for a timeout on the last jiffie. I
suspect that relying on this to actually not happen until the next jiffie is NOT
a good thing. I am not aware of any spec that says that is what it should do
and I am aware of timer patchs that will run the timer immeadiatly. A request
for 1 jiffie will do the same thing in the current kernel AND under that patch.
That thing being, by the way, is to wait for the next jiffie which will be any
time from ~0 to 1 jiffie.
>
Lots of words, which did not explain why an interrupt was not used to signal the
event, deleted :)
--
George Anzinger george@mvista.com
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: timing code in 2.6.1
2004-01-19 14:11 ` Richard B. Johnson
2004-01-20 9:59 ` George Anzinger
@ 2004-01-22 2:26 ` Jamie Lokier
1 sibling, 0 replies; 5+ messages in thread
From: Jamie Lokier @ 2004-01-22 2:26 UTC (permalink / raw)
To: Richard B. Johnson; +Cc: linux-kernel
Richard B. Johnson wrote:
> > > Some drivers are being re-written for 2.6++. The following
> > > construct seems to work for "waiting for an event" in
> > > the kernel modules.
> > >
> > > // No locks are being held
> > > tim = jiffies + EVENT_TIMEOUT;
> > > while(!event() && time_before(jiffies, tim))
> > > schedule_timeout(0);
> > >
> > > Is there anything wrong?
Yes.
1. The call to schedule_timeout(0) returns immediately, so you
might as well have an empty loop body.
See this from schedule_timeout's documentation:
The routine will return immediately unless
the current task state has been set (see set_current_state()).
You need to call set_current_state(TASK_INTERRUPTIBLE) or
set_current_state(TASK_UNINTERRUPTIBLE) inside the loop prior to
calling schedule_timeout.
2. With some experimental timer patches, schedule_timeout(0) could
return immediately. You should call schedule_timeout(1) instead to
ensure at least some kind of yielding the CPU, assuming that's what
you intended.
It would be much better to work out how often you have to poll
the event() function, and use that time interval as the argument
to schedule_timeout().
For example if you know you need to poll approximately every
20ms, write schedule_timeout(HZ/50).
Some additional advice:
You are polling for an event. If the event test is not complex, the
highest performance way to do it is to create a periodic timer and
have that check for the event, and use a waitqueue to wake the
sleeping task. What you are doing is much simpler to write, though.
> Huh? The code that causes "event()" needs to get the CPU occasionally
> to check for the event. The hardware doesn't produce an interrupt
> upon that event.
>
> The hardware designer has designed the hardware according to
> the requirements dictated by a government agency (the FDA).
> There was no requirement to make interface code simple. The
> interface code must check for multiple failure modes during
> every specific operation. Both the hardware and software
> check for these modes so that no single failure can cause
> injury to a patient. This is SOP for medical equipment.
When you call schedule_timeout(0), the scheduler _could_ delay your
process for an arbitrarily long time, unless you have set an
appropriate SCHED_FIFO or SCHED_RR policy.
For medical equipment which affects patient safety, usually _maximum_
polling intervals are required so that a dangerous operation is
aborted within a fixed time limit.
schedule_timeout(0) only guarantees a _minimum_ polling interval.
Please ensure you are doing this right.
> In the specific case, we operate a patient table. The operator
> presses an UP and DOWN button. These will produce interrupts.
> When an UP button is hit, thousands of interrupts are generated.
The hardware generates interrupts for button events but doesn't
produce interrupts for the periodic sampling that is monitoring the
table movement, is that right?
> This is because it is a mechanical operation. The same is true
> for the DOWN button. These events are filtered to determine
> the true intervals for "UP", "NOTHING", and "DOWN". When the
> "UP" button is pressed, the CPU servos position information
> from another driver and motor speed to to move the table to
> the commanded position. If the button is pressed for a short
> period of time, the table moves slowly. If it is pressed for
> a longer period, it moves quickly. It must accellerate according
> to a schedule and decellerate according to a schedule so that
> patients that weigh 350 lbs and patients that weigh 45 lbs are
> accellerated and decellerated at the same rate.
>
> When the table is being moved, 12 different parameters are
> monitored. At least two parameters are actually calculated
> and filtered to predict where the patient will be if the
> button is released.
If you are periodically monitoring and filtering parameters, it seems
very likely that you need accurate and consistent time intervals
between each measurement, to ensure patient safety.
-- Jamie
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2004-01-22 2:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-01-16 16:51 timing code in 2.6.1 Richard B. Johnson
2004-01-16 23:31 ` Andrew Morton
2004-01-19 14:11 ` Richard B. Johnson
2004-01-20 9:59 ` George Anzinger
2004-01-22 2:26 ` Jamie Lokier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox