diff options
Diffstat (limited to 'vendor/github.com/bytedance/sonic/loader/stubs.go')
-rw-r--r-- | vendor/github.com/bytedance/sonic/loader/stubs.go | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/vendor/github.com/bytedance/sonic/loader/stubs.go b/vendor/github.com/bytedance/sonic/loader/stubs.go index 8377649b7..80f8de836 100644 --- a/vendor/github.com/bytedance/sonic/loader/stubs.go +++ b/vendor/github.com/bytedance/sonic/loader/stubs.go @@ -17,7 +17,8 @@ package loader import ( - `sync` + "sync/atomic" + "unsafe" _ `unsafe` ) @@ -25,16 +26,35 @@ import ( //goland:noinspection GoUnusedGlobalVariable var lastmoduledatap *moduledata -var moduledataMux sync.Mutex - func registerModule(mod *moduledata) { - moduledataMux.Lock() - lastmoduledatap.next = mod - lastmoduledatap = mod - moduledataMux.Unlock() + registerModuleLockFree(&lastmoduledatap, mod) } //go:linkname moduledataverify1 runtime.moduledataverify1 func moduledataverify1(_ *moduledata) +func registerModuleLockFree(tail **moduledata, mod *moduledata) { + for { + oldTail := loadModule(tail) + if casModule(tail, oldTail, mod) { + storeModule(&oldTail.next, mod) + break + } + } +} + +func loadModule(p **moduledata) *moduledata { + return (*moduledata)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) +} +func storeModule(p **moduledata, value *moduledata) { + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(value)) +} + +func casModule(p **moduledata, oldValue *moduledata, newValue *moduledata) bool { + return atomic.CompareAndSwapPointer( + (*unsafe.Pointer)(unsafe.Pointer(p)), + unsafe.Pointer(oldValue), + unsafe.Pointer(newValue), + ) +} |