]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: delete timediv
authorRuss Cox <rsc@golang.org>
Wed, 29 Oct 2025 17:37:52 +0000 (13:37 -0400)
committerGopher Robot <gobot@golang.org>
Thu, 30 Oct 2025 16:55:06 +0000 (09:55 -0700)
Now that the compiler handles constant 64-bit divisions
without function calls on 32-bit systems, we no longer need
to maintain and test a bad custom implementation of 64-bit division.

Change-Id: If28807ad4f86507267ae69bc8f0b09ec18e98b66
Reviewed-on: https://go-review.googlesource.com/c/go/+/716463
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
15 files changed:
src/runtime/defs1_netbsd_386.go
src/runtime/defs1_netbsd_arm.go
src/runtime/defs_freebsd_386.go
src/runtime/defs_freebsd_arm.go
src/runtime/defs_linux_386.go
src/runtime/defs_linux_arm.go
src/runtime/defs_linux_mipsx.go
src/runtime/defs_openbsd_386.go
src/runtime/defs_openbsd_arm.go
src/runtime/export_test.go
src/runtime/os_dragonfly.go
src/runtime/os_plan9.go
src/runtime/os_windows.go
src/runtime/runtime1.go
src/runtime/runtime_test.go

index 16c55def92693b32758f0586c2682cfd7dde147b..cb4d6f1cf141a5170e21ba0bb37f334a487650f0 100644 (file)
@@ -121,7 +121,8 @@ type timespec struct {
 
 //go:nosplit
 func (ts *timespec) setNsec(ns int64) {
-       ts.tv_sec = int64(timediv(ns, 1e9, &ts.tv_nsec))
+       ts.tv_sec = int64(ns / 1e9)
+       ts.tv_nsec = int32(ns % 1e9)
 }
 
 type timeval struct {
index 77a59d4a05bfbddbb86e59bbbd5895310b5b1429..d31fcd471d9096e900a3ccb93939d8d32559a9de 100644 (file)
@@ -123,7 +123,8 @@ type timespec struct {
 
 //go:nosplit
 func (ts *timespec) setNsec(ns int64) {
-       ts.tv_sec = int64(timediv(ns, 1e9, &ts.tv_nsec))
+       ts.tv_sec = int64(ns / 1e9)
+       ts.tv_nsec = int32(ns % 1e9)
 }
 
 type timeval struct {
index 42a0faf74dcc0d7b7b4dbf1c9d5671b7eeb82d48..20ac643ad7a8621d513d12efcec5a376c27904b4 100644 (file)
@@ -210,7 +210,8 @@ type timespec struct {
 
 //go:nosplit
 func (ts *timespec) setNsec(ns int64) {
-       ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
+       ts.tv_sec = int32(ns / 1e9)
+       ts.tv_nsec = int32(ns % 1e9)
 }
 
 type timeval struct {
index dbb54da51bd2e5813dc45a5741ad10ad37cf9aaf..cf61fcade5630d897b6d8a422744a78ac2973c66 100644 (file)
@@ -182,7 +182,8 @@ type timespec struct {
 
 //go:nosplit
 func (ts *timespec) setNsec(ns int64) {
-       ts.tv_sec = int64(timediv(ns, 1e9, &ts.tv_nsec))
+       ts.tv_sec = int64(ns / 1e9)
+       ts.tv_nsec = int32(ns % 1e9)
 }
 
 type timeval struct {
index c6c7d7d6d880c0a6105831adc2b30d5256a7c042..d1875954f3109f56853bf898ea5ff98e3be61527 100644 (file)
@@ -146,7 +146,8 @@ type timespec32 struct {
 
 //go:nosplit
 func (ts *timespec32) setNsec(ns int64) {
-       ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
+       ts.tv_sec = int32(ns / 1e9)
+       ts.tv_nsec = int32(ns % 1e9)
 }
 
 type timespec struct {
@@ -156,9 +157,8 @@ type timespec struct {
 
 //go:nosplit
 func (ts *timespec) setNsec(ns int64) {
-       var newNS int32
-       ts.tv_sec = int64(timediv(ns, 1e9, &newNS))
-       ts.tv_nsec = int64(newNS)
+       ts.tv_sec = int64(ns / 1e9)
+       ts.tv_nsec = int64(ns % 1e9)
 }
 
 type timeval struct {
index ff879fad89faa1418e3dff612534cb99c2d06108..94577fc597175185aa1836cc06e28f17e42e8289 100644 (file)
@@ -105,7 +105,8 @@ type timespec32 struct {
 
 //go:nosplit
 func (ts *timespec32) setNsec(ns int64) {
-       ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
+       ts.tv_sec = int32(ns / 1e9)
+       ts.tv_nsec = int32(ns % 1e9)
 }
 
 type timespec struct {
@@ -115,9 +116,8 @@ type timespec struct {
 
 //go:nosplit
 func (ts *timespec) setNsec(ns int64) {
-       var newNS int32
-       ts.tv_sec = int64(timediv(ns, 1e9, &newNS))
-       ts.tv_nsec = int64(newNS)
+       ts.tv_sec = int64(ns / 1e9)
+       ts.tv_nsec = int64(ns % 1e9)
 }
 
 type stackt struct {
index 5b10b910dbebf29dfb0995d56bbc10bea6eacf34..5a446e0595f59f57b711e82e7a6077e6a9a9cd00 100644 (file)
@@ -103,7 +103,8 @@ type timespec32 struct {
 
 //go:nosplit
 func (ts *timespec32) setNsec(ns int64) {
-       ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
+       ts.tv_sec = int32(ns / 1e9)
+       ts.tv_nsec = int32(ns % 1e9)
 }
 
 type timespec struct {
@@ -113,9 +114,8 @@ type timespec struct {
 
 //go:nosplit
 func (ts *timespec) setNsec(ns int64) {
-       var newNS int32
-       ts.tv_sec = int64(timediv(ns, 1e9, &newNS))
-       ts.tv_nsec = int64(newNS)
+       ts.tv_sec = int64(ns / 1e9)
+       ts.tv_nsec = int64(ns % 1e9)
 }
 
 type timeval struct {
index 996745f6f8ed8516e0a2d669b49dfd98b2af2657..c77b5e16cb6b5440be09739e45adc225ceac1e04 100644 (file)
@@ -147,7 +147,8 @@ type timespec struct {
 
 //go:nosplit
 func (ts *timespec) setNsec(ns int64) {
-       ts.tv_sec = int64(timediv(ns, 1e9, &ts.tv_nsec))
+       ts.tv_sec = int64(ns / 1e9)
+       ts.tv_nsec = int32(ns % 1e9)
 }
 
 type timeval struct {
index cdda6b4ad1a850d1050ac7e9cb8e3408e397f77c..5393ea4eebaf30bc325aa21b7bb81b863315dd33 100644 (file)
@@ -152,7 +152,8 @@ type timespec struct {
 
 //go:nosplit
 func (ts *timespec) setNsec(ns int64) {
-       ts.tv_sec = int64(timediv(ns, 1e9, &ts.tv_nsec))
+       ts.tv_sec = int64(ns / 1e9)
+       ts.tv_nsec = int32(ns % 1e9)
 }
 
 type timeval struct {
index 9f2fcacc30ee5cdbdf9f186205e9d28252968097..d6fce72bf001fcc6b7b77f39dd2f4c338fc1938c 100644 (file)
@@ -1472,8 +1472,6 @@ func Releasem() {
        releasem(getg().m)
 }
 
-var Timediv = timediv
-
 type PIController struct {
        piController
 }
index fbbee64fd3847fe4e98987eb7f6b8299afc28a3b..c34af7f072ab34c1dd14b11fbda15db3eae853b7 100644 (file)
@@ -113,7 +113,7 @@ func futexsleep1(addr *uint32, val uint32, ns int64) {
                // The timeout is specified in microseconds - ensure that we
                // do not end up dividing to zero, which would put us to sleep
                // indefinitely...
-               timeout = timediv(ns, 1000, nil)
+               timeout = int32(ns / 1000)
                if timeout == 0 {
                        timeout = 1
                }
index 72a86579854b5ce929f68886f389a5c1099deaf3..80c101f1a18c6f22925611623a2ed93d6af86d0a 100644 (file)
@@ -486,7 +486,7 @@ func semacreate(mp *m) {
 func semasleep(ns int64) int {
        gp := getg()
        if ns >= 0 {
-               ms := timediv(ns, 1000000, nil)
+               ms := int32(ns / 1000000)
                if ms == 0 {
                        ms = 1
                }
index 7610802e0f7be86922b8a11ab6222433ffb4d1aa..2ae625580df920976077f82577e5260e7e80e3e0 100644 (file)
@@ -664,7 +664,7 @@ func semasleep(ns int64) int32 {
                start := nanotime()
                elapsed := int64(0)
                for {
-                       ms := int64(timediv(ns-elapsed, 1000000, nil))
+                       ms := (ns - elapsed) / 1000000
                        if ms == 0 {
                                ms = 1
                        }
index 3ec5c44ebd843813bf3b0bbe388ffc392222f077..43e4c1423629baf99e74437ad3e59328fb2177dd 100644 (file)
@@ -212,10 +212,6 @@ func check() {
                throw("bad unsafe.Sizeof y1")
        }
 
-       if timediv(12345*1000000000+54321, 1000000000, &e) != 12345 || e != 54321 {
-               throw("bad timediv")
-       }
-
        var z uint32
        z = 1
        if !atomic.Cas(&z, 1, 2) {
@@ -593,35 +589,6 @@ func setTraceback(level string) {
        atomic.Store(&traceback_cache, t)
 }
 
-// Poor mans 64-bit division.
-// This is a very special function, do not use it if you are not sure what you are doing.
-// int64 division is lowered into _divv() call on 386, which does not fit into nosplit functions.
-// Handles overflow in a time-specific manner.
-// This keeps us within no-split stack limits on 32-bit processors.
-//
-//go:nosplit
-func timediv(v int64, div int32, rem *int32) int32 {
-       res := int32(0)
-       for bit := 30; bit >= 0; bit-- {
-               if v >= int64(div)<<uint(bit) {
-                       v = v - (int64(div) << uint(bit))
-                       // Before this for loop, res was 0, thus all these
-                       // power of 2 increments are now just bitsets.
-                       res |= 1 << uint(bit)
-               }
-       }
-       if v >= int64(div) {
-               if rem != nil {
-                       *rem = 0
-               }
-               return 0x7fffffff
-       }
-       if rem != nil {
-               *rem = int32(v)
-       }
-       return res
-}
-
 // Helpers for Go. Must be NOSPLIT, must only call NOSPLIT functions, and must not block.
 
 //go:nosplit
index 6c628f8903cb8bc3009ae1a06a1f7a60d3415c2c..c1c63e3ceaf90c50774ffc76a9563e8fc9b512ac 100644 (file)
@@ -6,7 +6,6 @@ package runtime_test
 
 import (
        "flag"
-       "fmt"
        "internal/asan"
        "internal/cpu"
        "internal/msan"
@@ -498,81 +497,6 @@ func TestVersion(t *testing.T) {
        }
 }
 
-func TestTimediv(t *testing.T) {
-       for _, tc := range []struct {
-               num int64
-               div int32
-               ret int32
-               rem int32
-       }{
-               {
-                       num: 8,
-                       div: 2,
-                       ret: 4,
-                       rem: 0,
-               },
-               {
-                       num: 9,
-                       div: 2,
-                       ret: 4,
-                       rem: 1,
-               },
-               {
-                       // Used by runtime.check.
-                       num: 12345*1000000000 + 54321,
-                       div: 1000000000,
-                       ret: 12345,
-                       rem: 54321,
-               },
-               {
-                       num: 1<<32 - 1,
-                       div: 2,
-                       ret: 1<<31 - 1, // no overflow.
-                       rem: 1,
-               },
-               {
-                       num: 1 << 32,
-                       div: 2,
-                       ret: 1<<31 - 1, // overflow.
-                       rem: 0,
-               },
-               {
-                       num: 1 << 40,
-                       div: 2,
-                       ret: 1<<31 - 1, // overflow.
-                       rem: 0,
-               },
-               {
-                       num: 1<<40 + 1,
-                       div: 1 << 10,
-                       ret: 1 << 30,
-                       rem: 1,
-               },
-       } {
-               name := fmt.Sprintf("%d div %d", tc.num, tc.div)
-               t.Run(name, func(t *testing.T) {
-                       // Double check that the inputs make sense using
-                       // standard 64-bit division.
-                       ret64 := tc.num / int64(tc.div)
-                       rem64 := tc.num % int64(tc.div)
-                       if ret64 != int64(int32(ret64)) {
-                               // Simulate timediv overflow value.
-                               ret64 = 1<<31 - 1
-                               rem64 = 0
-                       }
-                       if ret64 != int64(tc.ret) {
-                               t.Errorf("%d / %d got ret %d rem %d want ret %d rem %d", tc.num, tc.div, ret64, rem64, tc.ret, tc.rem)
-                       }
-
-                       var rem int32
-                       ret := Timediv(tc.num, tc.div, &rem)
-                       if ret != tc.ret || rem != tc.rem {
-                               t.Errorf("timediv %d / %d got ret %d rem %d want ret %d rem %d", tc.num, tc.div, ret, rem, tc.ret, tc.rem)
-                       }
-               })
-       }
-}
-
 func BenchmarkProcYield(b *testing.B) {
        benchN := func(n uint32) func(*testing.B) {
                return func(b *testing.B) {