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