Bug 183 - Stopwatch.ElapsedTicks sometimes returns negative value on WinXP
Summary: Stopwatch.ElapsedTicks sometimes returns negative value on WinXP
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: General ()
Version: unspecified
Hardware: PC Windows
: Highest normal
Target Milestone: ---
Assignee: Paolo Molaro
URL:
Depends on:
Blocks:
 
Reported: 2011-08-04 20:18 UTC by Miguel de Icaza [MSFT]
Modified: 2011-12-08 04:02 UTC (History)
4 users (show)

Tags: trident
Is this bug a regression?: ---
Last known good build:


Attachments
sample test case (2.51 KB, application/x-zip-compressed)
2011-08-04 20:18 UTC, Miguel de Icaza [MSFT]
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Miguel de Icaza [MSFT] 2011-08-04 20:18:21 UTC
Created attachment 70 [details]
sample test case

After 1 to 3 hours this will produce a negative value on Windows XP SP3
Comment 1 Remi Lefebvre 2011-12-06 14:01:03 UTC
I've spent the last couple days tracking what I believe is the source of this bug.

Basically, the time calculations in mono_100ns_ticks overflows on machines where the high-precision counter frequency is really high.

Here we have a lot of Dell Precision 390 machines on which QueryPerformanceFrequency returns 2394170000. Their timers all break within 6 to 12 minutes.

The fault is in mono/utils/mono-time.c:

#define MTICKS_PER_SEC 10000000
gint64
mono_100ns_ticks (void)
{
	static LARGE_INTEGER freq;
	LARGE_INTEGER value;

	if (!freq.QuadPart && !QueryPerformanceFrequency (&freq))
		return mono_100ns_datetime ();
	QueryPerformanceCounter (&value);
	return value.QuadPart * MTICKS_PER_SEC / freq.QuadPart;
}

Here, at the specified frequency, it takes 385 seconds to overflow. On my main machine the frequency is 2337929, so this is 5 to 10 days, but this is just as bad.

This issue is extremely severe since it causes all Timers to be scheduled improperly. This has the potential to break other time sensitive services as well.

I have noticed this issue on Unity 3.2.0f4 (which uses mono 2.6 + fixes) but looking at the latest mono repository nothing seems to have changed in that regard.

Hope that helps!

Cheers,
Remi
Comment 2 Paolo Molaro 2011-12-07 09:04:01 UTC
This should be fixed in git.
Thanks!
Comment 3 Remi Lefebvre 2011-12-07 11:18:11 UTC
Paolo,

I fear you did not quite grasp the nature of the issue.

The problem has to do with the range of frequencies we can expect from the performance counter. The machine that caused me trouble has a counter frequency of 2394170000 Hz. That's the rate at which 'value' grows. Multiplying that by 10 000 000 leaves you with only 6-12 minutes before the multiplication overflows, depending on the initial value. Multiplying the difference with the start_time only makes that more predictable. (cur_time - start_time) will still grow at the same rate. The counter now overflows at _exactly_ 385.24s.

I get a feeling that frequencies that high are not very common (or the bug would have been fixed a while ago) but if you don't want your timers to die after a couple of days, better give this some thoughts before claiming it fixed.

Cheers,
Remi
Comment 4 Paolo Molaro 2011-12-08 04:02:29 UTC
The multiplication was meant to be done with floating point numbers, complete fix in git.