Messages in this thread | | | Date | Sat, 10 Jul 1999 22:54:21 +0200 | From | Bernd Paysan <> | Subject | Re: Important patch to fix select! |
| |
Steve Underwood wrote: > The whole point is you can't make select _extremely_ accurate, unless the > machine is idle. Any machine activity has the potential to make screen > updates stutter. Stuttering is _very_ bad for the perceived visual quality > of motion. Most visual flow things look far better if you miss the odd > frame update, but get the ones that do occur to happen exactly on time. > That way a short term machine overload causes just a hiccup in the flow. > Select will always cause visually unpleasant jitter, even if its timing is > much better than today's.
Yes, indeed, a good animation (game or whatever) has to take the delay into account that happend between the last and the current frame.
With the current situation in various OSes, a game or other low-frequent real time applications have to take a mix of system calls and busy-waiting to get good timing. For visual effects, the resolution of the OS timers generally is good enough (50 HZ are sufficient), but for sound, it's not. I've written an accurate MIDI player (using busy-waiting), and although the Linux kernel allows MIDI events to schedule at 100 HZ, you hear the difference for some special cases (like pitching a tone in a slope). Certainly you also hear a busy machine, but it isn't that awful on Linux, since the MIDI player gets a quite high dynamic priority.
What I want from an OS (if it can't give me a precise timer), is at least allow a timer+busy waiting strategy.
The first timer that comes in mind is the setitimer timer - just do what the OS has to do in user space. However, timer signals are a bad idea under Unix, since with such a timer, you get EAGAIN all over the place.
So next idea is select(). After all, you might be expecting some data anyway (e.g. on the pipe to X). Select's timeout has two disadvantageous properties: first, it's a delta. All my timer codes use absolute timers, which allows for predictable repetition, and a lot of other fine properties (especially that the timeout doesn't change with delay during process of a timer wait function). But worse, only select's man page does guarantee that it will return in time.
What's my workaround?
First, I measure the actual worst-case delay of select(), that is I call select with a 20 ms timeout (if the machine is idle, that'll return just after a tick occured). Then I call gettimeofday(), select with 1 ms timeout, and gettimeofday() again. Until recently, the time difference was almost 20 ms. The improvement the patch in this thread was to "fix" about gives me almost 10 ms (the current experimental kernel select is conformant with the somewhat contradictionary POSIX description).
What I really want is less than or up to 1 ms - first, because that's what's literally in the select manpage, and second, because that allows me to busy-wait only when busy-waiting *really is necessary*, and no more than that. That's what my patch gives me (in message <Pine.LNX.4.10.9907101418200.6704-200000@granny.paysan.nom>, Subject: [Patch] Re: usleep granularity).
And finally a rant to all CPU designers:
Add a timer source to your CPU! It needs one cyclic counter (one tick per clock, like the TSC, could also be one tick per bus clock; I'm completely agnostig about increment or decrement, but the wrapover must be more than 10 ms), and one compare register. Issue an interrupt when the compare register becomes equal to the timer. And add a "reset all timers" pin/command and a master clock signal to your SMP bus specification. Timers must be in sync!
-- Bernd Paysan "If you want it done right, you have to do it yourself" http://www.jwdt.com/~paysan/
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |