inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/atomicbitops/aligned_32bit_unsafe.go (about) 1 // Copyright 2021 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //go:build arm || mips || mipsle || 386 16 // +build arm mips mipsle 386 17 18 package atomicbitops 19 20 import ( 21 "sync/atomic" 22 "unsafe" 23 ) 24 25 // AlignedAtomicInt64 is an atomic int64 that is guaranteed to be 64-bit 26 // aligned, even on 32-bit systems. 27 // 28 // Per https://golang.org/pkg/sync/atomic/#pkg-note-BUG: 29 // 30 // "On ARM, 386, and 32-bit MIPS, it is the caller's responsibility to arrange 31 // for 64-bit alignment of 64-bit words accessed atomically. The first word in 32 // a variable or in an allocated struct, array, or slice can be relied upon to 33 // be 64-bit aligned." 34 // 35 // +stateify savable 36 type AlignedAtomicInt64 struct { 37 value int64 38 value32 int32 39 } 40 41 func (aa *AlignedAtomicInt64) ptr() *int64 { 42 // On 32-bit systems, aa.value is guaranteed to be 32-bit aligned. It means 43 // that in the 12-byte aa.value, there are guaranteed to be 8 contiguous bytes 44 // with 64-bit alignment. 45 return (*int64)(unsafe.Pointer((uintptr(unsafe.Pointer(&aa.value)) + 4) &^ 7)) 46 } 47 48 // Load is analagous to atomic.LoadInt64. 49 func (aa *AlignedAtomicInt64) Load() int64 { 50 return atomic.LoadInt64(aa.ptr()) 51 } 52 53 // Store is analagous to atomic.StoreInt64. 54 func (aa *AlignedAtomicInt64) Store(v int64) { 55 atomic.StoreInt64(aa.ptr(), v) 56 } 57 58 // Add is analagous to atomic.AddInt64. 59 func (aa *AlignedAtomicInt64) Add(v int64) int64 { 60 return atomic.AddInt64(aa.ptr(), v) 61 } 62 63 // AlignedAtomicUint64 is an atomic uint64 that is guaranteed to be 64-bit 64 // aligned, even on 32-bit systems. 65 // 66 // Per https://golang.org/pkg/sync/atomic/#pkg-note-BUG: 67 // 68 // "On ARM, 386, and 32-bit MIPS, it is the caller's responsibility to arrange 69 // for 64-bit alignment of 64-bit words accessed atomically. The first word in 70 // a variable or in an allocated struct, array, or slice can be relied upon to 71 // be 64-bit aligned." 72 // 73 // +stateify savable 74 type AlignedAtomicUint64 struct { 75 value uint64 76 value32 uint32 77 } 78 79 func (aa *AlignedAtomicUint64) ptr() *uint64 { 80 // On 32-bit systems, aa.value is guaranteed to be 32-bit aligned. It means 81 // that in the 12-byte aa.value, there are guaranteed to be 8 contiguous bytes 82 // with 64-bit alignment. 83 return (*uint64)(unsafe.Pointer((uintptr(unsafe.Pointer(&aa.value)) + 4) &^ 7)) 84 } 85 86 // Load is analagous to atomic.LoadUint64. 87 func (aa *AlignedAtomicUint64) Load() uint64 { 88 return atomic.LoadUint64(aa.ptr()) 89 } 90 91 // Store is analagous to atomic.StoreUint64. 92 func (aa *AlignedAtomicUint64) Store(v uint64) { 93 atomic.StoreUint64(aa.ptr(), v) 94 } 95 96 // Add is analagous to atomic.AddUint64. 97 func (aa *AlignedAtomicUint64) Add(v uint64) uint64 { 98 return atomic.AddUint64(aa.ptr(), v) 99 }