github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sync/seqatomic/generic_seqatomic_unsafe.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 // Package seqatomic doesn't exist. This file must be instantiated using the 7 // go_template_instance rule in tools/go_generics/defs.bzl. 8 package seqatomic 9 10 import ( 11 "unsafe" 12 13 "github.com/SagerNet/gvisor/pkg/gohacks" 14 "github.com/SagerNet/gvisor/pkg/sync" 15 ) 16 17 // Value is a required type parameter. 18 type Value struct{} 19 20 // SeqAtomicLoad returns a copy of *ptr, ensuring that the read does not race 21 // with any writer critical sections in seq. 22 // 23 //go:nosplit 24 func SeqAtomicLoad(seq *sync.SeqCount, ptr *Value) Value { 25 for { 26 if val, ok := SeqAtomicTryLoad(seq, seq.BeginRead(), ptr); ok { 27 return val 28 } 29 } 30 } 31 32 // SeqAtomicTryLoad returns a copy of *ptr while in a reader critical section 33 // in seq initiated by a call to seq.BeginRead() that returned epoch. If the 34 // read would race with a writer critical section, SeqAtomicTryLoad returns 35 // (unspecified, false). 36 // 37 //go:nosplit 38 func SeqAtomicTryLoad(seq *sync.SeqCount, epoch sync.SeqCountEpoch, ptr *Value) (val Value, ok bool) { 39 if sync.RaceEnabled { 40 // runtime.RaceDisable() doesn't actually stop the race detector, so it 41 // can't help us here. Instead, call runtime.memmove directly, which is 42 // not instrumented by the race detector. 43 gohacks.Memmove(unsafe.Pointer(&val), unsafe.Pointer(ptr), unsafe.Sizeof(val)) 44 } else { 45 // This is ~40% faster for short reads than going through memmove. 46 val = *ptr 47 } 48 ok = seq.ReadOk(epoch) 49 return 50 }