gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/atomicbitops/atomicbitops_noasm.go (about)

     1  // Copyright 2018 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 !amd64 && !arm64
    16  // +build !amd64,!arm64
    17  
    18  package atomicbitops
    19  
    20  import "sync/atomic"
    21  
    22  //go:nosplit
    23  func AndUint32(addr *Uint32, val uint32) {
    24  	for {
    25  		o := addr.Load()
    26  		n := o & val
    27  		if atomic.CompareAndSwapUint32(&addr.value, o, n) {
    28  			break
    29  		}
    30  	}
    31  }
    32  
    33  //go:nosplit
    34  func OrUint32(addr *Uint32, val uint32) {
    35  	for {
    36  		o := addr.Load()
    37  		n := o | val
    38  		if atomic.CompareAndSwapUint32(&addr.value, o, n) {
    39  			break
    40  		}
    41  	}
    42  }
    43  
    44  //go:nosplit
    45  func XorUint32(addr *Uint32, val uint32) {
    46  	for {
    47  		o := addr.Load()
    48  		n := o ^ val
    49  		if atomic.CompareAndSwapUint32(&addr.value, o, n) {
    50  			break
    51  		}
    52  	}
    53  }
    54  
    55  //go:nosplit
    56  func CompareAndSwapUint32(addr *Uint32, old, new uint32) (prev uint32) {
    57  	for {
    58  		prev = addr.Load()
    59  		if prev != old {
    60  			return
    61  		}
    62  		if atomic.CompareAndSwapUint32(&addr.value, old, new) {
    63  			return
    64  		}
    65  	}
    66  }
    67  
    68  //go:nosplit
    69  func AndUint64(addr *Uint64, val uint64) {
    70  	for {
    71  		o := atomic.LoadUint64(addr.ptr())
    72  		n := o & val
    73  		if atomic.CompareAndSwapUint64(addr.ptr(), o, n) {
    74  			break
    75  		}
    76  	}
    77  }
    78  
    79  //go:nosplit
    80  func OrUint64(addr *Uint64, val uint64) {
    81  	for {
    82  		o := atomic.LoadUint64(addr.ptr())
    83  		n := o | val
    84  		if atomic.CompareAndSwapUint64(addr.ptr(), o, n) {
    85  			break
    86  		}
    87  	}
    88  }
    89  
    90  //go:nosplit
    91  func XorUint64(addr *Uint64, val uint64) {
    92  	for {
    93  		o := atomic.LoadUint64(addr.ptr())
    94  		n := o ^ val
    95  		if atomic.CompareAndSwapUint64(addr.ptr(), o, n) {
    96  			break
    97  		}
    98  	}
    99  }
   100  
   101  //go:nosplit
   102  func CompareAndSwapUint64(addr *Uint64, old, new uint64) (prev uint64) {
   103  	for {
   104  		prev = atomic.LoadUint64(addr.ptr())
   105  		if prev != old {
   106  			return
   107  		}
   108  		if atomic.CompareAndSwapUint64(addr.ptr(), old, new) {
   109  			return
   110  		}
   111  	}
   112  }