Commit 7777bac6 authored by Shenghou Ma's avatar Shenghou Ma

runtime: use clock_gettime to get ns resolution for time.now & runtime.nanotime

For Linux/{386,arm}, FreeBSD/{386,amd64,arm}, NetBSD/{386,amd64}, OpenBSD/{386,amd64}.
Note: our Darwin implementation already has ns resolution.

Linux/386 (Core i7-2600 @ 3.40GHz, kernel 3.5.2-gentoo)
benchmark       old ns/op    new ns/op    delta
BenchmarkNow          110          118   +7.27%

Linux/ARM (ARM Cortex-A8 @ 800MHz, kernel 2.6.32.28 android)
benchmark       old ns/op    new ns/op    delta
BenchmarkNow          625          542  -13.28%

Linux/ARM (ARM Cortex-A9 @ 1GHz, Pandaboard)
benchmark       old ns/op    new ns/op    delta
BenchmarkNow          992          909   -8.37%

FreeBSD 9-REL-p1/amd64 (Dell R610 Server with Xeon X5650 @ 2.67GHz)
benchmark       old ns/op    new ns/op    delta
BenchmarkNow          699          695   -0.57%

FreeBSD 9-REL-p1/amd64 (Atom D525 @ 1.80GHz)
benchmark       old ns/op    new ns/op    delta
BenchmarkNow         1553         1658   +6.76%

OpenBSD/amd64 (Dell E6410 with i5 CPU M 540 @ 2.53GHz)
benchmark       old ns/op    new ns/op    delta
BenchmarkNow         1262         1236   -2.06%

OpenBSD/i386 (Asus eeePC 701 with Intel Celeron M 900MHz - locked to 631MHz)
benchmark       old ns/op    new ns/op    delta
BenchmarkNow         5089         5043   -0.90%

NetBSD/i386 (VMware VM with Core i5 CPU @ 2.7GHz)
benchmark       old ns/op    new ns/op    delta
BenchmarkNow          277          278   +0.36%

NetBSD/amd64 (VMware VM with Core i5 CPU @ 2.7Ghz)
benchmark       old ns/op    new ns/op    delta
BenchmarkNow          103          105   +1.94%

Thanks Maxim Khitrov, Joel Sing, and Dave Cheney for providing benchmark data.

R=jsing, dave, rsc
CC=golang-dev
https://golang.org/cl/6820120
parent 5b46fc41
...@@ -94,10 +94,10 @@ the <code>UnixConn</code>. ...@@ -94,10 +94,10 @@ the <code>UnixConn</code>.
<h3 id="time">time</h3> <h3 id="time">time</h3>
<p> <p>
On Linux, previous versions of the time package returned times with On FreeBSD, Linux, NetBSD, OS X and OpenBSD, previous versions of the time package
microsecond precision. The Go 1.1 implementation of time on Linux now returns times with returned times with microsecond precision. The Go 1.1 implementation of time on these
nanosecond precision. Code may exist that expects to be able to store systems now returns times with nanosecond precision. Code may exist that expects to be
such a time in an external format with only microsecond precision, able to store such a time in an external format with only microsecond precision,
read it back, and recover exactly the same time instant. read it back, and recover exactly the same time instant.
In Go 1.1 the same time will not be recovered, since the external storage In Go 1.1 the same time will not be recovered, since the external storage
will have discarded nanoseconds. will have discarded nanoseconds.
......
...@@ -116,40 +116,38 @@ TEXT runtime·setitimer(SB), 7, $-4 ...@@ -116,40 +116,38 @@ TEXT runtime·setitimer(SB), 7, $-4
// func now() (sec int64, nsec int32) // func now() (sec int64, nsec int32)
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
MOVL $116, AX MOVL $232, AX
LEAL 12(SP), BX LEAL 12(SP), BX
MOVL BX, 4(SP) MOVL $0, 4(SP)
MOVL $0, 8(SP) MOVL BX, 8(SP)
INT $0x80 INT $0x80
MOVL 12(SP), AX // sec MOVL 12(SP), AX // sec
MOVL 16(SP), BX // usec MOVL 16(SP), BX // nsec
// sec is in AX, usec in BX // sec is in AX, nsec in BX
MOVL AX, sec+0(FP) MOVL AX, sec+0(FP)
MOVL $0, sec+4(FP) MOVL $0, sec+4(FP)
IMULL $1000, BX
MOVL BX, nsec+8(FP) MOVL BX, nsec+8(FP)
RET RET
// int64 nanotime(void) so really // int64 nanotime(void) so really
// void nanotime(int64 *nsec) // void nanotime(int64 *nsec)
TEXT runtime·nanotime(SB), 7, $32 TEXT runtime·nanotime(SB), 7, $32
MOVL $116, AX MOVL $232, AX
LEAL 12(SP), BX LEAL 12(SP), BX
MOVL BX, 4(SP) MOVL $0, 4(SP)
MOVL $0, 8(SP) MOVL BX, 8(SP)
INT $0x80 INT $0x80
MOVL 12(SP), AX // sec MOVL 12(SP), AX // sec
MOVL 16(SP), BX // usec MOVL 16(SP), BX // nsec
// sec is in AX, usec in BX // sec is in AX, nsec in BX
// convert to DX:AX nsec // convert to DX:AX nsec
MOVL $1000000000, CX MOVL $1000000000, CX
MULL CX MULL CX
IMULL $1000, BX
ADDL BX, AX ADDL BX, AX
ADCL $0, DX ADCL $0, DX
MOVL ret+0(FP), DI MOVL ret+0(FP), DI
MOVL AX, 0(DI) MOVL AX, 0(DI)
MOVL DX, 4(DI) MOVL DX, 4(DI)
......
...@@ -94,31 +94,29 @@ TEXT runtime·setitimer(SB), 7, $-8 ...@@ -94,31 +94,29 @@ TEXT runtime·setitimer(SB), 7, $-8
// func now() (sec int64, nsec int32) // func now() (sec int64, nsec int32)
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
MOVL $116, AX MOVL $232, AX
LEAQ 8(SP), DI MOVQ $0, DI
MOVQ $0, SI LEAQ 8(SP), SI
SYSCALL SYSCALL
MOVQ 8(SP), AX // sec MOVQ 8(SP), AX // sec
MOVL 16(SP), DX // usec MOVQ 16(SP), DX // nsec
// sec is in AX, usec in DX // sec is in AX, nsec in DX
MOVQ AX, sec+0(FP) MOVQ AX, sec+0(FP)
IMULQ $1000, DX
MOVL DX, nsec+8(FP) MOVL DX, nsec+8(FP)
RET RET
TEXT runtime·nanotime(SB), 7, $32 TEXT runtime·nanotime(SB), 7, $32
MOVL $116, AX MOVL $232, AX
LEAQ 8(SP), DI MOVQ $0, DI
MOVQ $0, SI LEAQ 8(SP), SI
SYSCALL SYSCALL
MOVQ 8(SP), AX // sec MOVQ 8(SP), AX // sec
MOVL 16(SP), DX // usec MOVQ 16(SP), DX // nsec
// sec is in AX, usec in DX // sec is in AX, nsec in DX
// return nsec in AX // return nsec in AX
IMULQ $1000000000, AX IMULQ $1000000000, AX
IMULQ $1000, DX
ADDQ DX, AX ADDQ DX, AX
RET RET
......
...@@ -86,39 +86,36 @@ TEXT runtime·setitimer(SB), 7, $-8 ...@@ -86,39 +86,36 @@ TEXT runtime·setitimer(SB), 7, $-8
// func now() (sec int64, nsec int32) // func now() (sec int64, nsec int32)
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
MOVW $8(R13), R0 MOVW $0, R0 // CLOCK_REALTIME
MOVW $0, R1 MOVW $8(R13), R1
SWI $116 // gettimeofday SWI $232 // clock_gettime
MOVW 8(R13), R0 // sec.low MOVW 8(R13), R0 // sec.low
MOVW 16(R13), R2 // usec MOVW 12(R13), R1 // sec.high
MOVW 16(R13), R2 // nsec
MOVW R0, 0(FP) MOVW R0, 0(FP)
MOVW $0, R1
MOVW R1, 4(FP) MOVW R1, 4(FP)
MOVW $1000, R3
MUL R3, R2
MOVW R2, 8(FP) MOVW R2, 8(FP)
RET RET
// int64 nanotime(void) so really // int64 nanotime(void) so really
// void nanotime(int64 *nsec) // void nanotime(int64 *nsec)
TEXT runtime·nanotime(SB), 7, $32 TEXT runtime·nanotime(SB), 7, $32
MOVW $8(R13), R0 MOVW $0, R0 // CLOCK_REALTIME
MOVW $0, R1 MOVW $8(R13), R1
SWI $116 // gettimeofday SWI $232 // clock_gettime
MOVW 8(R13), R0 // sec.low MOVW 8(R13), R0 // sec.low
MOVW 16(R13), R2 // usec MOVW 12(R13), R4 // sec.high
MOVW 16(R13), R2 // nsec
MOVW $1000000000, R3 MOVW $1000000000, R3
MULLU R0, R3, (R1, R0) MULLU R0, R3, (R1, R0)
MOVW $1000, R3 MUL R3, R4
MOVW $0, R4
MUL R3, R2
ADD.S R2, R0 ADD.S R2, R0
ADC R4, R1 ADC R4, R1
MOVW 0(FP), R3 MOVW 0(FP), R3
MOVW R0, 0(R3) MOVW R0, 0(R3)
MOVW R1, 4(R3) MOVW R1, 4(R3)
......
...@@ -104,40 +104,38 @@ TEXT runtime·mincore(SB),7,$0-24 ...@@ -104,40 +104,38 @@ TEXT runtime·mincore(SB),7,$0-24
// func now() (sec int64, nsec int32) // func now() (sec int64, nsec int32)
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
MOVL $78, AX // syscall - gettimeofday MOVL $265, AX // syscall - clock_gettime
LEAL 8(SP), BX MOVL $0, BX
MOVL $0, CX LEAL 8(SP), CX
MOVL $0, DX MOVL $0, DX
CALL *runtime·_vdso(SB) CALL *runtime·_vdso(SB)
MOVL 8(SP), AX // sec MOVL 8(SP), AX // sec
MOVL 12(SP), BX // usec MOVL 12(SP), BX // nsec
// sec is in AX, usec in BX // sec is in AX, nsec in BX
MOVL AX, sec+0(FP) MOVL AX, sec+0(FP)
MOVL $0, sec+4(FP) MOVL $0, sec+4(FP)
IMULL $1000, BX
MOVL BX, nsec+8(FP) MOVL BX, nsec+8(FP)
RET RET
// int64 nanotime(void) so really // int64 nanotime(void) so really
// void nanotime(int64 *nsec) // void nanotime(int64 *nsec)
TEXT runtime·nanotime(SB), 7, $32 TEXT runtime·nanotime(SB), 7, $32
MOVL $78, AX // syscall - gettimeofday MOVL $265, AX // syscall - clock_gettime
LEAL 8(SP), BX MOVL $0, BX
MOVL $0, CX LEAL 8(SP), CX
MOVL $0, DX MOVL $0, DX
CALL *runtime·_vdso(SB) CALL *runtime·_vdso(SB)
MOVL 8(SP), AX // sec MOVL 8(SP), AX // sec
MOVL 12(SP), BX // usec MOVL 12(SP), BX // nsec
// sec is in AX, usec in BX // sec is in AX, nsec in BX
// convert to DX:AX nsec // convert to DX:AX nsec
MOVL $1000000000, CX MOVL $1000000000, CX
MULL CX MULL CX
IMULL $1000, BX
ADDL BX, AX ADDL BX, AX
ADCL $0, DX ADCL $0, DX
MOVL ret+0(FP), DI MOVL ret+0(FP), DI
MOVL AX, 0(DI) MOVL AX, 0(DI)
MOVL DX, 4(DI) MOVL DX, 4(DI)
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define SYS_select (SYS_BASE + 142) // newselect #define SYS_select (SYS_BASE + 142) // newselect
#define SYS_ugetrlimit (SYS_BASE + 191) #define SYS_ugetrlimit (SYS_BASE + 191)
#define SYS_sched_getaffinity (SYS_BASE + 242) #define SYS_sched_getaffinity (SYS_BASE + 242)
#define SYS_clock_gettime (SYS_BASE + 263)
#define ARM_BASE (SYS_BASE + 0x0f0000) #define ARM_BASE (SYS_BASE + 0x0f0000)
#define SYS_ARM_cacheflush (ARM_BASE + 2) #define SYS_ARM_cacheflush (ARM_BASE + 2)
...@@ -155,41 +156,37 @@ TEXT runtime·mincore(SB),7,$0 ...@@ -155,41 +156,37 @@ TEXT runtime·mincore(SB),7,$0
RET RET
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
MOVW $8(R13), R0 // timeval MOVW $0, R0 // CLOCK_REALTIME
MOVW $0, R1 // zone MOVW $8(R13), R1 // timespec
MOVW $SYS_gettimeofday, R7 MOVW $SYS_clock_gettime, R7
SWI $0 SWI $0
MOVW 8(R13), R0 // sec MOVW 8(R13), R0 // sec
MOVW 12(R13), R2 // usec MOVW 12(R13), R2 // nsec
MOVW R0, 0(FP) MOVW R0, 0(FP)
MOVW $0, R1 MOVW $0, R1
MOVW R1, 4(FP) MOVW R1, 4(FP)
MOVW $1000, R3
MUL R3, R2
MOVW R2, 8(FP) MOVW R2, 8(FP)
RET RET
// int64 nanotime(void) so really // int64 nanotime(void) so really
// void nanotime(int64 *nsec) // void nanotime(int64 *nsec)
TEXT runtime·nanotime(SB),7,$32 TEXT runtime·nanotime(SB),7,$32
MOVW $8(R13), R0 // timeval MOVW $0, R0 // CLOCK_REALTIME
MOVW $0, R1 // zone MOVW $8(R13), R1 // timespec
MOVW $SYS_gettimeofday, R7 MOVW $SYS_clock_gettime, R7
SWI $0 SWI $0
MOVW 8(R13), R0 // sec MOVW 8(R13), R0 // sec
MOVW 12(R13), R2 // usec MOVW 12(R13), R2 // nsec
MOVW $1000000000, R3 MOVW $1000000000, R3
MULLU R0, R3, (R1, R0) MULLU R0, R3, (R1, R0)
MOVW $1000, R3
MOVW $0, R4 MOVW $0, R4
MUL R3, R2
ADD.S R2, R0 ADD.S R2, R0
ADC R4, R1 ADC R4, R1
MOVW 0(FP), R3 MOVW 0(FP), R3
MOVW R0, 0(R3) MOVW R0, 0(R3)
MOVW R1, 4(R3) MOVW R1, 4(R3)
......
...@@ -98,9 +98,9 @@ TEXT runtime·setitimer(SB),7,$-4 ...@@ -98,9 +98,9 @@ TEXT runtime·setitimer(SB),7,$-4
// func now() (sec int64, nsec int32) // func now() (sec int64, nsec int32)
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
LEAL 12(SP), BX LEAL 12(SP), BX
MOVL BX, 4(SP) // arg 1 - tp MOVL $0, 4(SP) // arg 1 - clock_id
MOVL $0, 8(SP) // arg 2 - tzp MOVL BX, 8(SP) // arg 2 - tp
MOVL $418, AX // sys_gettimeofday MOVL $427, AX // sys_clock_gettime
INT $0x80 INT $0x80
MOVL 12(SP), AX // sec - l32 MOVL 12(SP), AX // sec - l32
...@@ -108,8 +108,7 @@ TEXT time·now(SB), 7, $32 ...@@ -108,8 +108,7 @@ TEXT time·now(SB), 7, $32
MOVL 16(SP), AX // sec - h32 MOVL 16(SP), AX // sec - h32
MOVL AX, sec+4(FP) MOVL AX, sec+4(FP)
MOVL 20(SP), BX // usec - should not exceed 999999 MOVL 20(SP), BX // nsec
IMULL $1000, BX
MOVL BX, nsec+8(FP) MOVL BX, nsec+8(FP)
RET RET
...@@ -117,9 +116,9 @@ TEXT time·now(SB), 7, $32 ...@@ -117,9 +116,9 @@ TEXT time·now(SB), 7, $32
// void nanotime(int64 *nsec) // void nanotime(int64 *nsec)
TEXT runtime·nanotime(SB),7,$32 TEXT runtime·nanotime(SB),7,$32
LEAL 12(SP), BX LEAL 12(SP), BX
MOVL BX, 4(SP) // arg 1 - tp MOVL $0, 4(SP) // arg 1 - clock_id
MOVL $0, 8(SP) // arg 2 - tzp MOVL BX, 8(SP) // arg 2 - tp
MOVL $418, AX // sys_gettimeofday MOVL $427, AX // sys_clock_gettime
INT $0x80 INT $0x80
MOVL 16(SP), CX // sec - h32 MOVL 16(SP), CX // sec - h32
...@@ -129,8 +128,7 @@ TEXT runtime·nanotime(SB),7,$32 ...@@ -129,8 +128,7 @@ TEXT runtime·nanotime(SB),7,$32
MOVL $1000000000, BX MOVL $1000000000, BX
MULL BX // result in dx:ax MULL BX // result in dx:ax
MOVL 20(SP), BX // usec MOVL 20(SP), BX // nsec
IMULL $1000, BX
ADDL BX, AX ADDL BX, AX
ADCL CX, DX // add high bits with carry ADCL CX, DX // add high bits with carry
......
...@@ -122,31 +122,29 @@ TEXT runtime·setitimer(SB),7,$-8 ...@@ -122,31 +122,29 @@ TEXT runtime·setitimer(SB),7,$-8
// func now() (sec int64, nsec int32) // func now() (sec int64, nsec int32)
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
LEAQ 8(SP), DI // arg 1 - tp MOVQ $0, DI // arg 1 - clock_id
MOVQ $0, SI // arg 2 - tzp LEAQ 8(SP), SI // arg 2 - tp
MOVL $418, AX // sys_gettimeofday MOVL $427, AX // sys_clock_gettime
SYSCALL SYSCALL
MOVQ 8(SP), AX // sec MOVQ 8(SP), AX // sec
MOVL 16(SP), DX // usec MOVL 16(SP), DX // nsec
// sec is in AX, usec in DX // sec is in AX, nsec in DX
MOVQ AX, sec+0(FP) MOVQ AX, sec+0(FP)
IMULQ $1000, DX
MOVL DX, nsec+8(FP) MOVL DX, nsec+8(FP)
RET RET
TEXT runtime·nanotime(SB),7,$32 TEXT runtime·nanotime(SB),7,$32
LEAQ 8(SP), DI // arg 1 - tp MOVQ $0, DI // arg 1 - clock_id
MOVQ $0, SI // arg 2 - tzp LEAQ 8(SP), SI // arg 2 - tp
MOVL $418, AX // sys_gettimeofday MOVL $427, AX // sys_clock_gettime
SYSCALL SYSCALL
MOVQ 8(SP), AX // sec MOVQ 8(SP), AX // sec
MOVL 16(SP), DX // usec MOVL 16(SP), DX // nsec
// sec is in AX, usec in DX // sec is in AX, nsec in DX
// return nsec in AX // return nsec in AX
IMULQ $1000000000, AX IMULQ $1000000000, AX
IMULQ $1000, DX
ADDQ DX, AX ADDQ DX, AX
RET RET
......
...@@ -98,40 +98,38 @@ TEXT runtime·setitimer(SB),7,$-4 ...@@ -98,40 +98,38 @@ TEXT runtime·setitimer(SB),7,$-4
// func now() (sec int64, nsec int32) // func now() (sec int64, nsec int32)
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
MOVL $116, AX MOVL $232, AX
LEAL 12(SP), BX LEAL 12(SP), BX
MOVL BX, 4(SP) MOVL $0, 4(SP)
MOVL $0, 8(SP) MOVL BX, 8(SP)
INT $0x80 INT $0x80
MOVL 12(SP), AX // sec MOVL 12(SP), AX // sec
MOVL 16(SP), BX // usec MOVL 16(SP), BX // nsec
// sec is in AX, usec in BX // sec is in AX, nsec in BX
MOVL AX, sec+0(FP) MOVL AX, sec+0(FP)
MOVL $0, sec+4(FP) MOVL $0, sec+4(FP)
IMULL $1000, BX
MOVL BX, nsec+8(FP) MOVL BX, nsec+8(FP)
RET RET
// int64 nanotime(void) so really // int64 nanotime(void) so really
// void nanotime(int64 *nsec) // void nanotime(int64 *nsec)
TEXT runtime·nanotime(SB),7,$32 TEXT runtime·nanotime(SB),7,$32
MOVL $116, AX MOVL $232, AX
LEAL 12(SP), BX LEAL 12(SP), BX
MOVL BX, 4(SP) MOVL $0, 4(SP)
MOVL $0, 8(SP) MOVL BX, 8(SP)
INT $0x80 INT $0x80
MOVL 12(SP), AX // sec MOVL 12(SP), AX // sec
MOVL 16(SP), BX // usec MOVL 16(SP), BX // nsec
// sec is in AX, usec in BX // sec is in AX, nsec in BX
// convert to DX:AX nsec // convert to DX:AX nsec
MOVL $1000000000, CX MOVL $1000000000, CX
MULL CX MULL CX
IMULL $1000, BX
ADDL BX, AX ADDL BX, AX
ADCL $0, DX ADCL $0, DX
MOVL ret+0(FP), DI MOVL ret+0(FP), DI
MOVL AX, 0(DI) MOVL AX, 0(DI)
MOVL DX, 4(DI) MOVL DX, 4(DI)
......
...@@ -130,31 +130,29 @@ TEXT runtime·setitimer(SB),7,$-8 ...@@ -130,31 +130,29 @@ TEXT runtime·setitimer(SB),7,$-8
// func now() (sec int64, nsec int32) // func now() (sec int64, nsec int32)
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
LEAQ 8(SP), DI // arg 1 - tp MOVQ $0, DI // arg 1 - clock_id
MOVQ $0, SI // arg 2 - tzp LEAQ 8(SP), SI // arg 2 - tp
MOVL $116, AX // sys_gettimeofday MOVL $232, AX // sys_clock_gettime
SYSCALL SYSCALL
MOVQ 8(SP), AX // sec MOVL 8(SP), AX // sec
MOVL 16(SP), DX // usec MOVQ 16(SP), DX // nsec
// sec is in AX, usec in DX // sec is in AX, nsec in DX
MOVQ AX, sec+0(FP) MOVQ AX, sec+0(FP)
IMULQ $1000, DX
MOVL DX, nsec+8(FP) MOVL DX, nsec+8(FP)
RET RET
TEXT runtime·nanotime(SB),7,$32 TEXT runtime·nanotime(SB),7,$32
LEAQ 8(SP), DI // arg 1 - tp MOVQ $0, DI // arg 1 - clock_id
MOVQ $0, SI // arg 2 - tzp LEAQ 8(SP), SI // arg 2 - tp
MOVL $116, AX // sys_gettimeofday MOVL $232, AX // sys_clock_gettime
SYSCALL SYSCALL
MOVQ 8(SP), AX // sec MOVL 8(SP), AX // sec
MOVL 16(SP), DX // usec MOVQ 16(SP), DX // nsec
// sec is in AX, usec in DX // sec is in AX, nsec in DX
// return nsec in AX // return nsec in AX
IMULQ $1000000000, AX IMULQ $1000000000, AX
IMULQ $1000, DX
ADDQ DX, AX ADDQ DX, AX
RET RET
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment