util.go raw
1 package xsync
2
3 import (
4 "math/bits"
5 "runtime"
6 _ "unsafe"
7 )
8
9 // test-only assert()-like flag
10 var assertionsEnabled = false
11
12 const (
13 // cacheLineSize is used in paddings to prevent false sharing;
14 // 64B are used instead of 128B as a compromise between
15 // memory footprint and performance; 128B usage may give ~30%
16 // improvement on NUMA machines.
17 cacheLineSize = 64
18 )
19
20 // nextPowOf2 computes the next highest power of 2 of 32-bit v.
21 // Source: https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
22 func nextPowOf2(v uint32) uint32 {
23 if v == 0 {
24 return 1
25 }
26 v--
27 v |= v >> 1
28 v |= v >> 2
29 v |= v >> 4
30 v |= v >> 8
31 v |= v >> 16
32 v++
33 return v
34 }
35
36 func parallelism() uint32 {
37 maxProcs := uint32(runtime.GOMAXPROCS(0))
38 numCores := uint32(runtime.NumCPU())
39 if maxProcs < numCores {
40 return maxProcs
41 }
42 return numCores
43 }
44
45 //go:noescape
46 //go:linkname runtime_fastrand runtime.fastrand
47 func runtime_fastrand() uint32
48
49 func broadcast(b uint8) uint64 {
50 return 0x101010101010101 * uint64(b)
51 }
52
53 func firstMarkedByteIndex(w uint64) int {
54 return bits.TrailingZeros64(w) >> 3
55 }
56
57 // SWAR byte search: may produce false positives, e.g. for 0x0100,
58 // so make sure to double-check bytes found by this function.
59 func markZeroBytes(w uint64) uint64 {
60 return ((w - 0x0101010101010101) & (^w) & 0x8080808080808080)
61 }
62
63 func setByte(w uint64, b uint8, idx int) uint64 {
64 shift := idx << 3
65 return (w &^ (0xff << shift)) | (uint64(b) << shift)
66 }
67