about summary refs log tree commit diff
path: root/vendor/modernc.org/libc/atomic.go
blob: 66b554625d68cff23142e3cfb80ba2f3e83749fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Copyright 2024 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build linux && (amd64 || arm64 || loong64)

package libc // import "modernc.org/libc"

import (
	"math"
	mbits "math/bits"
	"sync/atomic"
	"unsafe"
)

func a_store_8(addr uintptr, val int8) int8 {
	*(*int8)(unsafe.Pointer(addr)) = val
	return val
}

func a_load_8(addr uintptr) (val int8) {
	return *(*int8)(unsafe.Pointer(addr))
}

func a_load_16(addr uintptr) (val int16) {
	if addr&1 != 0 {
		panic("unaligned atomic access")
	}

	return *(*int16)(unsafe.Pointer(addr))
}

func a_store_16(addr uintptr, val uint16) {
	if addr&1 != 0 {
		panic("unaligned atomic access")
	}

	*(*uint16)(unsafe.Pointer(addr)) = val
}

// static inline int a_ctz_l(unsigned long x)
func _a_ctz_l(tls *TLS, x ulong) int32 {
	if unsafe.Sizeof(x) == 8 {
		return int32(mbits.TrailingZeros64(x))
	}

	return int32(mbits.TrailingZeros32(uint32(x)))
}

// static inline int a_ctz_64(uint64_t x)
func _a_ctz_64(tls *TLS, x uint64) int32 {
	return int32(mbits.TrailingZeros64(x))
}

func AtomicAddFloat32(addr *float32, delta float32) (new float32) {
	v := AtomicLoadFloat32(addr) + delta
	AtomicStoreFloat32(addr, v)
	return v
}

func AtomicLoadFloat32(addr *float32) (val float32) {
	return math.Float32frombits(atomic.LoadUint32((*uint32)(unsafe.Pointer(addr))))
}

func AtomicStoreFloat32(addr *float32, val float32) {
	atomic.StoreUint32((*uint32)(unsafe.Pointer(addr)), math.Float32bits(val))
}

func AtomicAddFloat64(addr *float64, delta float64) (new float64) {
	v := AtomicLoadFloat64(addr) + delta
	AtomicStoreFloat64(addr, v)
	return v
}

func AtomicLoadFloat64(addr *float64) (val float64) {
	return math.Float64frombits(atomic.LoadUint64((*uint64)(unsafe.Pointer(addr))))
}

func AtomicStoreFloat64(addr *float64, val float64) {
	atomic.StoreUint64((*uint64)(unsafe.Pointer(addr)), math.Float64bits(val))
}

func AtomicAddInt32(addr *int32, delta int32) (new int32) { return atomic.AddInt32(addr, delta) }

func AtomicAddInt64(addr *int64, delta int64) (new int64) { return atomic.AddInt64(addr, delta) }

func AtomicAddUint32(addr *uint32, delta uint32) (new uint32) { return atomic.AddUint32(addr, delta) }

func AtomicAddUint64(addr *uint64, delta uint64) (new uint64) { return atomic.AddUint64(addr, delta) }

func AtomicAddUintptr(addr *uintptr, delta uintptr) (new uintptr) {
	return atomic.AddUintptr(addr, delta)

}

func AtomicLoadInt32(addr *int32) (val int32) { return atomic.LoadInt32(addr) }

func AtomicLoadInt64(addr *int64) (val int64) { return atomic.LoadInt64(addr) }

func AtomicLoadUint32(addr *uint32) (val uint32) { return atomic.LoadUint32(addr) }

func AtomicLoadUint64(addr *uint64) (val uint64) { return atomic.LoadUint64(addr) }

func AtomicLoadUintptr(addr *uintptr) (val uintptr) { return atomic.LoadUintptr(addr) }

func AtomicStoreInt32(addr *int32, val int32) { atomic.StoreInt32(addr, val) }

func AtomicStoreUint32(addr *uint32, val uint32) { atomic.StoreUint32(addr, val) }

func AtomicStoreUint64(addr *uint64, val uint64) { atomic.StoreUint64(addr, val) }

func AtomicStoreUintptr(addr *uintptr, val uintptr) { atomic.StoreUintptr(addr, val) }

func AtomicStoreInt64(addr *int64, val int64) { atomic.StoreInt64(addr, val) }