2010-02-27 09:52:15

by Rafał Miłecki

[permalink] [raw]
Subject: schedule (wait_event) vs. while

In radeon engine reclocking code I need to do some calculations and
then wait for VBLANK interrupt. Right after VBLANK interrupt will
happen I need to reclock ASAP.

Interrupts are received by another context and I need some quite fast
synchronization.

1) Schedule solution:
reclocking() {
calculations();
radeon->vblank_sync = 0;
wait_event_timeout(radeon->wq, radeon->vblank_sync, timeout);
reclock();
}
i-handler() { radeon->vblank_sync = 1; }

2) While solution:
reclocking() {
calculations();
del_timer(radeon->fake_vblank);
radeon->vblank_sync = 0;
mod_timer(radeon->fake_vblank, 10ms);
while(!radeon->vblank_sync);
reclock();
}
i-handler() { radeon->vblank_sync = 1; }
fake-handler() { radeon->vblank_sync = 1; }

Of course first one is much cleaner but internally wait_event_timeout
uses schedule_timeout(). Now according to LDD3:
> Once a process releases the processor with schedule, there are no guarantees that the process will get the processor back anytime soon. Therefore, calling schedule in this manner is not a safe solution to the driver’s needs, in addition to being bad for the computing system as a whole. If you test jitsched while running load50, you can see that the delay associated to each line is extended by a few seconds, because other processes are using the CPU when the timeout expires.

I can not afford any delays because VBLANK is so short timeframe. Is
there any better solution?

--
Rafał


2010-02-27 20:11:43

by Roland Dreier

[permalink] [raw]
Subject: Re: schedule (wait_event) vs. while

> In radeon engine reclocking code I need to do some calculations and
> then wait for VBLANK interrupt. Right after VBLANK interrupt will
> happen I need to reclock ASAP.
>
> Interrupts are received by another context and I need some quite fast
> synchronization.
>
> 1) Schedule solution:
> reclocking() {
> calculations();
> radeon->vblank_sync = 0;
> wait_event_timeout(radeon->wq, radeon->vblank_sync, timeout);
> reclock();
> }
> i-handler() { radeon->vblank_sync = 1; }

What does reclock() involve? Is there any reason you can't do it in the
interrupt handler? (quite possibly it needs to sleep or something)

If you can do it in the interrupt handler, then your reclocking()
function could do the calculations, stash the result somewhere, and set
a flag that tells the interrupt handler to do the reclock(). Then you
could use a completion to have reclocking() wait until the reclock() was
actually done (the latency of that completion doesn't matter, since
you're not doing any actual work after the completion).

If you do need to wait for process context, then one possibility would
be to do reclocking() from a high-priority kernel thread. Then the wake
up latency should be low (but maybe not low enough). Or you could
convert the interrupt handler to use the new threaded interrupt support,
to get into a process context as fast as possible.

If you reall need to busy-wait, then

> reclocking() {
> calculations();
> del_timer(radeon->fake_vblank);
> radeon->vblank_sync = 0;
> mod_timer(radeon->fake_vblank, 10ms);
> while(!radeon->vblank_sync);
> reclock();
> }
> i-handler() { radeon->vblank_sync = 1; }
> fake-handler() { radeon->vblank_sync = 1; }

There's no need for the fake_vblank timer -- just keep track of the time
when you start busy-waiting and then exit the loop when 10ms passes.

- R.
--
Roland Dreier <[email protected]>
For corporate legal information go to:
http://www.cisco.com/web/about/doing_business/legal/cri/index.html