atomic.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright 2024 The Libc Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build linux && (amd64 || arm64 || loong64 || ppc64le || s390x || riscv64 || 386 || arm)
  5. package libc // import "modernc.org/libc"
  6. import (
  7. "math"
  8. mbits "math/bits"
  9. "sync/atomic"
  10. "unsafe"
  11. )
  12. func a_store_8(addr uintptr, val int8) int8 {
  13. *(*int8)(unsafe.Pointer(addr)) = val
  14. return val
  15. }
  16. func a_load_8(addr uintptr) (val int8) {
  17. return *(*int8)(unsafe.Pointer(addr))
  18. }
  19. func a_load_16(addr uintptr) (val int16) {
  20. if addr&1 != 0 {
  21. panic("unaligned atomic access")
  22. }
  23. return *(*int16)(unsafe.Pointer(addr))
  24. }
  25. func a_store_16(addr uintptr, val uint16) {
  26. if addr&1 != 0 {
  27. panic("unaligned atomic access")
  28. }
  29. *(*uint16)(unsafe.Pointer(addr)) = val
  30. }
  31. // static inline int a_ctz_64(uint64_t x)
  32. func _a_ctz_64(tls *TLS, x uint64) int32 {
  33. return int32(mbits.TrailingZeros64(x))
  34. }
  35. func AtomicAddFloat32(addr *float32, delta float32) (new float32) {
  36. v := AtomicLoadFloat32(addr) + delta
  37. AtomicStoreFloat32(addr, v)
  38. return v
  39. }
  40. func AtomicLoadFloat32(addr *float32) (val float32) {
  41. return math.Float32frombits(atomic.LoadUint32((*uint32)(unsafe.Pointer(addr))))
  42. }
  43. func AtomicStoreFloat32(addr *float32, val float32) {
  44. atomic.StoreUint32((*uint32)(unsafe.Pointer(addr)), math.Float32bits(val))
  45. }
  46. func AtomicAddFloat64(addr *float64, delta float64) (new float64) {
  47. v := AtomicLoadFloat64(addr) + delta
  48. AtomicStoreFloat64(addr, v)
  49. return v
  50. }
  51. func AtomicLoadFloat64(addr *float64) (val float64) {
  52. return math.Float64frombits(atomic.LoadUint64((*uint64)(unsafe.Pointer(addr))))
  53. }
  54. func AtomicStoreFloat64(addr *float64, val float64) {
  55. atomic.StoreUint64((*uint64)(unsafe.Pointer(addr)), math.Float64bits(val))
  56. }
  57. func AtomicAddInt32(addr *int32, delta int32) (new int32) { return atomic.AddInt32(addr, delta) }
  58. func AtomicAddInt64(addr *int64, delta int64) (new int64) { return atomic.AddInt64(addr, delta) }
  59. func AtomicAddUint32(addr *uint32, delta uint32) (new uint32) { return atomic.AddUint32(addr, delta) }
  60. func AtomicAddUint64(addr *uint64, delta uint64) (new uint64) { return atomic.AddUint64(addr, delta) }
  61. func AtomicAddUintptr(addr *uintptr, delta uintptr) (new uintptr) {
  62. return atomic.AddUintptr(addr, delta)
  63. }
  64. func AtomicLoadInt32(addr *int32) (val int32) { return atomic.LoadInt32(addr) }
  65. func AtomicLoadInt64(addr *int64) (val int64) { return atomic.LoadInt64(addr) }
  66. func AtomicLoadUint32(addr *uint32) (val uint32) { return atomic.LoadUint32(addr) }
  67. func AtomicLoadUint64(addr *uint64) (val uint64) { return atomic.LoadUint64(addr) }
  68. func AtomicLoadUintptr(addr *uintptr) (val uintptr) { return atomic.LoadUintptr(addr) }
  69. func AtomicStoreInt32(addr *int32, val int32) { atomic.StoreInt32(addr, val) }
  70. func AtomicStoreUint32(addr *uint32, val uint32) { atomic.StoreUint32(addr, val) }
  71. func AtomicStoreUint64(addr *uint64, val uint64) { atomic.StoreUint64(addr, val) }
  72. func AtomicStoreUintptr(addr *uintptr, val uintptr) { atomic.StoreUintptr(addr, val) }
  73. func AtomicStoreInt64(addr *int64, val int64) { atomic.StoreInt64(addr, val) }