[hatari-devel] Higher precision when generating samples -> use nanosleep

Eero Tamminen oak at helsinkinet.fi
Wed Jan 26 20:56:53 CET 2011


On keskiviikko 26 tammikuu 2011, Nicolas Pomarède wrote:
> Regarding Main_WaitOnVbl and the use of SDL_Delay / SDL_GetTicks,
> it's quite possible your kernel is built with a value of HZ set to 100,
> which means a maximum precision of 10 ms.

I think you're confusing what APIs SDL, C-libary and kernel offer and what
kernel internally does. :-)

Kernel counts time used by processes in 100Hz ticks, this value is part of
the user-space API, but internally kernel scheduler can have very different
tick values, from 128Hz (ARM default) to about 1000Hz.

SDL_Delay() API limits its accuracy to 100Hz, it's not an internal SDL
limit.  Kernel offers several APIs which have offer higher accuracy than
that, like nanosleep(), select(), clock_gettime().

> Anyway, I'm convinced the problem is in the fact we only have
> millisecond precision. As you said earlier, at 60 Hz, we get 16.6666 ms
> per VBL, which is truncated to 16 ms (we could round this to 17, it
> would be a little better, but problem would remain).

If SDL on some platform does Vsync() on screen updates and your monitor
refresh rate isn't exactly 60Hz, or you try to emulate 50Hz monitor when in
reality SDL is synching to a 60Hz LCD screen, I think that could be a larger

(Windows specific programs would use DirectX APIs to do Vsync() I think.)

> So, I'm wondering if we should use nanosleep() when available (instead
> of SDL_Delay which is not precise enough)

According to SDL sources, SDL_Delay() and related functions already use 
nanosleep() & clock_gettime() if they're available (at SDL build time). 
They just don't offer that accuracy to programs using these functions.

> nanosleep is defined in POSIX.1-2001, so it should be OK to use under
> Linux and OSX. It seems cygwin is also providing a nanosleep function
> that uses Windows' internal calls, so it should be good for Windows too.
> With nanosleep, we could get a much better granularity.

I think the reason why SDL isn't offering better granularity is that
although some API would have higher accuracy, it doesn't mean that your
program would get scheduled at such intervals.

On my Debian testing i3 machine with 2.6.32 kernel, the scheduler tick is:
	$ grep '^CONFIG_HZ=' /boot/config-$(uname -r)

I.e. on my machine process CPU time slice size is 4ms.

That means that any program/thread using CPU for few ms (on the same CPU),
can add 4ms "random" delays to program timings. If there are multiple such
programs/threads (on same CPU), it will be some multiple of that CPU slice
size.  Even 1000Hz scheduler "tick" could still give n*1ms "random" delays.

Only way to get guaranteed timings is to use real-time scheduling and that 
you really want to use only on programs/threads that been _designed_ to be
real-time i.e. the code guarantees always to use less than certain low
amount of CPU (so that it doesn't completely freeze the system), unlike
Hatari does...

> We could define our own "FineSleep" function and uses the best possible
> alternatives depending on the OS / compilation flags (1st nanosleep,
> then SDL_Delay, active wait on SDL_GetTicks, etc.).
> I think it would fix the VBL precision problem with very few changes to
> Hatari. Any opinion on this ?

I think it's more robust to have code that adapts to unprecise timings.

Hatari sound behaving erratically when any program runs on background
and on platforms which don't have submillisecond accuracy is not really

	- Eero

PS. The 250Hz comes from Debian trying to compromise between
desktop and server systems:

More information about the hatari-devel mailing list