Page 1 of 1

gettimeofday() inaccuracy

Posted: Sat Mar 17, 2012 7:32 am
by ObsidianX
Hey folks,

I'm in search of a microsecond- or nanosecond-accurate timer for a project but the microsecond field returned from gettimeofday() is completely bogus. As a test I wrote a simple loop that calls gettimeofday() 100 times and prints the results each time before quitting.

Here's what it looks like in Windows (truncated for brevity, MinGW used):

Code: Select all

1331965376; 300935
1331965376; 301935
1331965376; 302935
1331965376; 303935
1331965376; 304935
1331965376; 305935
This is what it looks like when ran on both a physical Wii and in the Dolphin emulator with any of the CPU options:

Code: Select all

1331930967; 454
1331930967; 192
1331930967; 30
1331930967; 304
1331930967; 416
1331930967; 154
They are both in the order that they were executed. The Wii version doesn't just fail but it also bounces around with seemingly random numbers in the microsecond slot.

Is there anything that I can do either to fix gettimeofday() or replace it with another high-granularity timer?

Thanks!
-ObsidianX

Re: gettimeofday() inaccuracy

Posted: Thu Mar 22, 2012 12:54 am
by ObsidianX
For the record, after much Google'ing around I finally found that if I use gettime() and diff_usec(start_time, current_time) I can get an elapsed time in microseconds.
There are various diff_ functions for different time measurements available.
All are found in <ogc/lwp_watchdog.h>

Re: gettimeofday() inaccuracy

Posted: Sun Apr 01, 2012 1:52 pm
by tueidj
It looks like __libogc_gettod_r() in timesupp.c should be using tick_to_microsecs() instead of tick_microsecs().

Re: gettimeofday() inaccuracy

Posted: Sat Dec 13, 2014 1:46 pm
by Oibaf
tueidj wrote:It looks like __libogc_gettod_r() in timesupp.c should be using tick_to_microsecs() instead of tick_microsecs().
The function to be used in __libogc_gettod_r should be tick_microsecs() since tv_usec indicates the number of nanoseconds expired in the current second whilst ticks_to_microsecs() reports the total number of microsecs.

Anyhow there are two considerations:

1) The tick_microsecs() as well tick_nanosecs() macros of libogc are wrong:

In lwp_watchdog.h they are defined as

#define tick_microsecs(ticks) ((((u64)(ticks)*8)%(u64)(TB_TIMER_CLOCK/125)))
#define tick_nanosecs(ticks) ((((u64)(ticks)*8000)%(u64)(TB_TIMER_CLOCK/125)))

TB_TIMER_CLOCK/125 is 486. It means that the gives the rest of 486 that's wrong.

The correct functions should be:

#define tick_microsecs(ticks) ((((u64)(ticks)*8)/(u64)(TB_TIMER_CLOCK/125))%1000000)
#define tick_nanosecs(ticks) ((((u64)(ticks)*8000)/(u64)(TB_TIMER_CLOCK/125))%1000000000)

2) Also the use of tick_nanosecs() is not appropriate for __libogc_gettod_r. Indeed gettimeoftheday() should return the number of seconds since 00:00 hours, Jan 1, 1970 UTC whilst ticks functions represent the time elapsed from the WII switch on.

In timesupp.c there is another bug. The function clock_gettime() define tv_nsec as ticks_to_nanosecs(gettick()).
It would be more appropriate to use:

tp->tv_nsec = tick_nanosecs(gettick());

as in __libogc_gettod_r with the considerations made above for gettimeofday.