[Vm-dev] Time primHighResClock truncated to 32 bits in 64 bits VMs.

David T. Lewis lewis at mail.msen.com
Thu Dec 28 16:56:50 UTC 2017

On Thu, Dec 28, 2017 at 09:32:46AM -0300, Juan Vuletich wrote:
> Hi Folks,
> In 32 bit Cog VMs, `Time primHighResClock` answers LargePositiveInteger, 
> presumably up to 64 bits. This would mean a rollover in 167 years on a 
> 3.5GHz machine.
> But on 64 bit Cog and Stack Spur VMs, it answers a SmallInteger that is 
> truncated to 32 bits. This means a rollover in about one second.
> I guesss this is a bug. Answering a SmallInteger, truncating the CPU 64 
> bit counter to 60 bits would be ok. I think it makes sense to restrict 
> answer to SmallInteger to avoid allocation, and a rollover every 41 
> years is not too much :)
> Thanks,
> -- 
> Juan Vuletich
> www.cuis-smalltalk.org
> https://github.com/Cuis-Smalltalk/Cuis-Smalltalk-Dev
> @JuanVuletich

Attached is the #primHighResClock accessor for Squeak/Pharo users.

I don't see anything obviously wrong with the primitive, although maybe it
involves the handling of positive64BitIntegerFor: in the 64-bit VM.

The primitive is:

	"Return the value of the high resolution clock if this system has any. The exact frequency of the high res clock is undefined specifically so that we can use processor dependent instructions (like RDTSC). The only use for the high res clock is for profiling where we can allocate time based on sub-msec resolution of the high res clock. If no high-resolution counter is available, the platform should return zero."
	<export: true>
	self pop: 1.
	self push: (self positive64BitIntegerFor: self ioHighResClock).

And the platform support code does this:

  /* return the value of the high performance counter */
  sqLong value = 0;
#if defined(__GNUC__) && ( defined(i386) || defined(__i386) || defined(__i386__)  \
                        || defined(i486) || defined(__i486) || defined (__i486__) \
                        || defined(intel) || defined(x86) || defined(i86pc) )
    __asm__ __volatile__ ("rdtsc" : "=A"(value));
#elif defined(__arm__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
        /* tpr - do nothing for now; needs input from eliot to decide further */
# error "no high res clock defined"
  return value;

-------------- next part --------------
'From Cuis 5.0 of 7 November 2016 [latest update: #3206] on 2 January 1901 at 12:00:00 am'!

!Time class methodsFor: 'primitives' stamp: 'jmv 5/25/2014 21:41'!
	"Primitive. Answer the value of the high resolution clock if this computer has one.
	Usually, this should be the highest resolution value available, for example on Intel
	it will be the value of the time stamp counter register.
	Answer is (at least usually) a LargePositiveInteger.
	Implemented on Cog, but not in standard interpreter VMs."
	Time primHighResClock
	On Cog on OS-X and Windows, it seems to give sub nano second ticks!!

	Run a 100 msec busy loop to figure out the ticks per msec

	| t0 ticksPerMSec |
	t0 := Time millisecondClockValue + 2.
	[Time millisecondClockValue >= t0] whileFalse.
	ticksPerMSec := Time primHighResClock.
	[Time millisecondClockValue >= (t0 + 100)] whileFalse.
	ticksPerMSec := (Time primHighResClock - ticksPerMSec) 
			// (Time millisecondClockValue - t0).
"Not really a clock, but a timer or ticker"
	<primitive: 'primitiveHighResClock'>
	^0! !

More information about the Vm-dev mailing list