diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index ccdf465ffbba872f3f140f8479365c4ca3becf67..e36ec08a5b0232656bd3f45b61ba2079d0da813f 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -67,8 +67,6 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { regabiSupported = true } - haveThreads := goarch != "wasm" - // Older versions (anything before V16) of dsymutil don't handle // the .debug_rnglists section in DWARF5. See // https://github.com/golang/go/issues/26379#issuecomment-2677068742 @@ -85,7 +83,6 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { RegabiArgs: regabiSupported, AliasTypeParams: true, SwissMap: true, - SpinbitMutex: haveThreads, SyncHashTrieMap: true, Dwarf5: dwarf5Supported, } diff --git a/src/internal/goexperiment/exp_spinbitmutex_off.go b/src/internal/goexperiment/exp_spinbitmutex_off.go deleted file mode 100644 index 776b0dc77ff914190ff30632086e5ac7dae0d245..0000000000000000000000000000000000000000 --- a/src/internal/goexperiment/exp_spinbitmutex_off.go +++ /dev/null @@ -1,8 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build !goexperiment.spinbitmutex - -package goexperiment - -const SpinbitMutex = false -const SpinbitMutexInt = 0 diff --git a/src/internal/goexperiment/exp_spinbitmutex_on.go b/src/internal/goexperiment/exp_spinbitmutex_on.go deleted file mode 100644 index 8468030c769e38ca802788fd9c89dbb4e6bb27cc..0000000000000000000000000000000000000000 --- a/src/internal/goexperiment/exp_spinbitmutex_on.go +++ /dev/null @@ -1,8 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build goexperiment.spinbitmutex - -package goexperiment - -const SpinbitMutex = true -const SpinbitMutexInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index 271fdc2b3cfae8222a0dd5523cf6902c4f9d78d2..0961764bee672140ec09b14df0d97c336e7b1d7b 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -115,10 +115,6 @@ type Flags struct { // SwissMap enables the SwissTable-based map implementation. SwissMap bool - // SpinbitMutex enables the new "spinbit" mutex implementation on supported - // platforms. See https://go.dev/issue/68578. - SpinbitMutex bool - // SyncHashTrieMap enables the HashTrieMap sync.Map implementation. SyncHashTrieMap bool diff --git a/src/runtime/lock_futex_tristate.go b/src/runtime/lock_futex_tristate.go deleted file mode 100644 index b7df18c86c04a2f3e76ecdc1d1724c3af2302a50..0000000000000000000000000000000000000000 --- a/src/runtime/lock_futex_tristate.go +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (dragonfly || freebsd || linux) && !goexperiment.spinbitmutex - -package runtime - -import ( - "internal/runtime/atomic" -) - -// This implementation depends on OS-specific implementations of -// -// futexsleep(addr *uint32, val uint32, ns int64) -// Atomically, -// if *addr == val { sleep } -// Might be woken up spuriously; that's allowed. -// Don't sleep longer than ns; ns < 0 means forever. -// -// futexwakeup(addr *uint32, cnt uint32) -// If any procs are sleeping on addr, wake up at most cnt. - -const ( - mutex_unlocked = 0 - mutex_locked = 1 - mutex_sleeping = 2 - - active_spin = 4 - active_spin_cnt = 30 - passive_spin = 1 -) - -// Possible lock states are mutex_unlocked, mutex_locked and mutex_sleeping. -// mutex_sleeping means that there is presumably at least one sleeping thread. -// Note that there can be spinning threads during all states - they do not -// affect mutex's state. - -type mWaitList struct{} - -func lockVerifyMSize() {} - -func mutexContended(l *mutex) bool { - return atomic.Load(key32(&l.key)) > mutex_locked -} - -func lock(l *mutex) { - lockWithRank(l, getLockRank(l)) -} - -func lock2(l *mutex) { - gp := getg() - - if gp.m.locks < 0 { - throw("runtime·lock: lock count") - } - gp.m.locks++ - - // Speculative grab for lock. - v := atomic.Xchg(key32(&l.key), mutex_locked) - if v == mutex_unlocked { - return - } - - // wait is either MUTEX_LOCKED or MUTEX_SLEEPING - // depending on whether there is a thread sleeping - // on this mutex. If we ever change l->key from - // MUTEX_SLEEPING to some other value, we must be - // careful to change it back to MUTEX_SLEEPING before - // returning, to ensure that the sleeping thread gets - // its wakeup call. - wait := v - - timer := &lockTimer{lock: l} - timer.begin() - // On uniprocessors, no point spinning. - // On multiprocessors, spin for ACTIVE_SPIN attempts. - spin := 0 - if ncpu > 1 { - spin = active_spin - } - for { - // Try for lock, spinning. - for i := 0; i < spin; i++ { - for l.key == mutex_unlocked { - if atomic.Cas(key32(&l.key), mutex_unlocked, wait) { - timer.end() - return - } - } - procyield(active_spin_cnt) - } - - // Try for lock, rescheduling. - for i := 0; i < passive_spin; i++ { - for l.key == mutex_unlocked { - if atomic.Cas(key32(&l.key), mutex_unlocked, wait) { - timer.end() - return - } - } - osyield() - } - - // Sleep. - v = atomic.Xchg(key32(&l.key), mutex_sleeping) - if v == mutex_unlocked { - timer.end() - return - } - wait = mutex_sleeping - futexsleep(key32(&l.key), mutex_sleeping, -1) - } -} - -func unlock(l *mutex) { - unlockWithRank(l) -} - -func unlock2(l *mutex) { - v := atomic.Xchg(key32(&l.key), mutex_unlocked) - if v == mutex_unlocked { - throw("unlock of unlocked lock") - } - if v == mutex_sleeping { - futexwakeup(key32(&l.key), 1) - } - - gp := getg() - gp.m.mLockProfile.recordUnlock(l) - gp.m.locks-- - if gp.m.locks < 0 { - throw("runtime·unlock: lock count") - } - if gp.m.locks == 0 && gp.preempt { // restore the preemption request in case we've cleared it in newstack - gp.stackguard0 = stackPreempt - } -} diff --git a/src/runtime/lock_sema_tristate.go b/src/runtime/lock_sema_tristate.go deleted file mode 100644 index 4375791d46fb8e443370c7fa91f117606733d3b6..0000000000000000000000000000000000000000 --- a/src/runtime/lock_sema_tristate.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (aix || darwin || netbsd || openbsd || plan9 || solaris || windows) && !goexperiment.spinbitmutex - -package runtime - -import ( - "internal/runtime/atomic" - "unsafe" -) - -// This implementation depends on OS-specific implementations of -// -// func semacreate(mp *m) -// Create a semaphore for mp, if it does not already have one. -// -// func semasleep(ns int64) int32 -// If ns < 0, acquire m's semaphore and return 0. -// If ns >= 0, try to acquire m's semaphore for at most ns nanoseconds. -// Return 0 if the semaphore was acquired, -1 if interrupted or timed out. -// -// func semawakeup(mp *m) -// Wake up mp, which is or will soon be sleeping on its semaphore. -const ( - active_spin = 4 - active_spin_cnt = 30 - passive_spin = 1 -) - -// mWaitList is part of the M struct, and holds the list of Ms that are waiting -// for a particular runtime.mutex. -// -// When an M is unable to immediately obtain a lock, it adds itself to the list -// of Ms waiting for the lock. It does that via this struct's next field, -// forming a singly-linked list with the mutex's key field pointing to the head -// of the list. -type mWaitList struct { - next muintptr // next m waiting for lock -} - -func lockVerifyMSize() {} - -func mutexContended(l *mutex) bool { - return atomic.Loaduintptr(&l.key) > locked -} - -func lock(l *mutex) { - lockWithRank(l, getLockRank(l)) -} - -func lock2(l *mutex) { - gp := getg() - if gp.m.locks < 0 { - throw("runtime·lock: lock count") - } - gp.m.locks++ - - // Speculative grab for lock. - if atomic.Casuintptr(&l.key, 0, locked) { - return - } - semacreate(gp.m) - - timer := &lockTimer{lock: l} - timer.begin() - // On uniprocessor's, no point spinning. - // On multiprocessors, spin for ACTIVE_SPIN attempts. - spin := 0 - if ncpu > 1 { - spin = active_spin - } -Loop: - for i := 0; ; i++ { - v := atomic.Loaduintptr(&l.key) - if v&locked == 0 { - // Unlocked. Try to lock. - if atomic.Casuintptr(&l.key, v, v|locked) { - timer.end() - return - } - i = 0 - } - if i < spin { - procyield(active_spin_cnt) - } else if i < spin+passive_spin { - osyield() - } else { - // Someone else has it. - // l.key points to a linked list of M's waiting - // for this lock, chained through m.mWaitList.next. - // Queue this M. - for { - gp.m.mWaitList.next = muintptr(v &^ locked) - if atomic.Casuintptr(&l.key, v, uintptr(unsafe.Pointer(gp.m))|locked) { - break - } - v = atomic.Loaduintptr(&l.key) - if v&locked == 0 { - continue Loop - } - } - if v&locked != 0 { - // Queued. Wait. - semasleep(-1) - i = 0 - } - } - } -} - -func unlock(l *mutex) { - unlockWithRank(l) -} - -// We might not be holding a p in this code. -// -//go:nowritebarrier -func unlock2(l *mutex) { - gp := getg() - var mp *m - for { - v := atomic.Loaduintptr(&l.key) - if v == locked { - if atomic.Casuintptr(&l.key, locked, 0) { - break - } - } else { - // Other M's are waiting for the lock. - // Dequeue an M. - mp = muintptr(v &^ locked).ptr() - if atomic.Casuintptr(&l.key, v, uintptr(mp.mWaitList.next)) { - // Dequeued an M. Wake it. - semawakeup(mp) // no use of mp after this point; it's awake - break - } - } - } - gp.m.mLockProfile.recordUnlock(l) - gp.m.locks-- - if gp.m.locks < 0 { - throw("runtime·unlock: lock count") - } - if gp.m.locks == 0 && gp.preempt { // restore the preemption request in case we've cleared it in newstack - gp.stackguard0 = stackPreempt - } -} diff --git a/src/runtime/lock_spinbit.go b/src/runtime/lock_spinbit.go index 7b7bc651ad95897dd134cf6c0764bd108460487d..9bca4bd8243c5ba1485172421fd54124d23c162f 100644 --- a/src/runtime/lock_spinbit.go +++ b/src/runtime/lock_spinbit.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || plan9 || solaris || windows) && goexperiment.spinbitmutex +//go:build !wasm package runtime diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 27d14b890bd654708d7f630c4621c1e34fe738f3..f7371c450bd93c5007b0bc4a80d0a38856bde67e 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -8,7 +8,6 @@ import ( "internal/abi" "internal/chacha8rand" "internal/goarch" - "internal/goexperiment" "internal/runtime/atomic" "internal/runtime/sys" "unsafe" @@ -628,9 +627,9 @@ type mPadded struct { // Size the runtime.m structure so it fits in the 2048-byte size class, and // not in the next-smallest (1792-byte) size class. That leaves the 11 low - // bits of muintptr values available for flags, as required for - // GOEXPERIMENT=spinbitmutex. - _ [goexperiment.SpinbitMutexInt * (2048 - mallocHeaderSize - mRedZoneSize - unsafe.Sizeof(m{}))]byte + // bits of muintptr values available for flags, as required by + // lock_spinbit.go. + _ [(1 - goarch.IsWasm) * (2048 - mallocHeaderSize - mRedZoneSize - unsafe.Sizeof(m{}))]byte } type p struct {