|
|
@@ -7,7 +7,6 @@
|
|
|
package unix
|
|
|
|
|
|
import (
|
|
|
- "math/bits"
|
|
|
"unsafe"
|
|
|
)
|
|
|
|
|
|
@@ -80,7 +79,46 @@ func (s *CPUSet) IsSet(cpu int) bool {
|
|
|
func (s *CPUSet) Count() int {
|
|
|
c := 0
|
|
|
for _, b := range s {
|
|
|
- c += bits.OnesCount64(uint64(b))
|
|
|
+ c += onesCount64(uint64(b))
|
|
|
}
|
|
|
return c
|
|
|
}
|
|
|
+
|
|
|
+// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
|
|
|
+// Once this package can require Go 1.9, we can delete this
|
|
|
+// and update the caller to use bits.OnesCount64.
|
|
|
+func onesCount64(x uint64) int {
|
|
|
+ const m0 = 0x5555555555555555 // 01010101 ...
|
|
|
+ const m1 = 0x3333333333333333 // 00110011 ...
|
|
|
+ const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
|
|
|
+ const m3 = 0x00ff00ff00ff00ff // etc.
|
|
|
+ const m4 = 0x0000ffff0000ffff
|
|
|
+
|
|
|
+ // Implementation: Parallel summing of adjacent bits.
|
|
|
+ // See "Hacker's Delight", Chap. 5: Counting Bits.
|
|
|
+ // The following pattern shows the general approach:
|
|
|
+ //
|
|
|
+ // x = x>>1&(m0&m) + x&(m0&m)
|
|
|
+ // x = x>>2&(m1&m) + x&(m1&m)
|
|
|
+ // x = x>>4&(m2&m) + x&(m2&m)
|
|
|
+ // x = x>>8&(m3&m) + x&(m3&m)
|
|
|
+ // x = x>>16&(m4&m) + x&(m4&m)
|
|
|
+ // x = x>>32&(m5&m) + x&(m5&m)
|
|
|
+ // return int(x)
|
|
|
+ //
|
|
|
+ // Masking (& operations) can be left away when there's no
|
|
|
+ // danger that a field's sum will carry over into the next
|
|
|
+ // field: Since the result cannot be > 64, 8 bits is enough
|
|
|
+ // and we can ignore the masks for the shifts by 8 and up.
|
|
|
+ // Per "Hacker's Delight", the first line can be simplified
|
|
|
+ // more, but it saves at best one instruction, so we leave
|
|
|
+ // it alone for clarity.
|
|
|
+ const m = 1<<64 - 1
|
|
|
+ x = x>>1&(m0&m) + x&(m0&m)
|
|
|
+ x = x>>2&(m1&m) + x&(m1&m)
|
|
|
+ x = (x>>4 + x) & (m2 & m)
|
|
|
+ x += x >> 8
|
|
|
+ x += x >> 16
|
|
|
+ x += x >> 32
|
|
|
+ return int(x) & (1<<7 - 1)
|
|
|
+}
|