github.com/go-xe2/third@v1.0.3/golang.org/x/sys/unix/affinity_linux.go (about) 1 // Copyright 2018 The Go 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 5 // CPU affinity functions 6 7 package unix 8 9 import ( 10 "unsafe" 11 ) 12 13 const cpuSetSize int = _CPU_SETSIZE / _NCPUBITS 14 15 // CPUSet represents a CPU affinity mask. 16 type CPUSet [cpuSetSize]cpuMask 17 18 func schedAffinity(trap uintptr, pid int, set *CPUSet) error { 19 _, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(*set)), uintptr(unsafe.Pointer(set))) 20 if e != 0 { 21 return errnoErr(e) 22 } 23 return nil 24 } 25 26 // SchedGetaffinity gets the CPU affinity mask of the thread specified by pid. 27 // If pid is 0 the calling thread is used. 28 func SchedGetaffinity(pid int, set *CPUSet) error { 29 return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set) 30 } 31 32 // SchedSetaffinity sets the CPU affinity mask of the thread specified by pid. 33 // If pid is 0 the calling thread is used. 34 func SchedSetaffinity(pid int, set *CPUSet) error { 35 return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set) 36 } 37 38 // Zero clears the set s, so that it contains no CPUs. 39 func (s *CPUSet) Zero() { 40 for i := range s { 41 s[i] = 0 42 } 43 } 44 45 func cpuBitsIndex(cpu int) int { 46 return cpu / _NCPUBITS 47 } 48 49 func cpuBitsMask(cpu int) cpuMask { 50 return cpuMask(1 << (uint(cpu) % _NCPUBITS)) 51 } 52 53 // Set adds cpu to the set s. 54 func (s *CPUSet) Set(cpu int) { 55 i := cpuBitsIndex(cpu) 56 if i < len(s) { 57 s[i] |= cpuBitsMask(cpu) 58 } 59 } 60 61 // Clear removes cpu from the set s. 62 func (s *CPUSet) Clear(cpu int) { 63 i := cpuBitsIndex(cpu) 64 if i < len(s) { 65 s[i] &^= cpuBitsMask(cpu) 66 } 67 } 68 69 // IsSet reports whether cpu is in the set s. 70 func (s *CPUSet) IsSet(cpu int) bool { 71 i := cpuBitsIndex(cpu) 72 if i < len(s) { 73 return s[i]&cpuBitsMask(cpu) != 0 74 } 75 return false 76 } 77 78 // Count returns the number of CPUs in the set s. 79 func (s *CPUSet) Count() int { 80 c := 0 81 for _, b := range s { 82 c += onesCount64(uint64(b)) 83 } 84 return c 85 } 86 87 // onesCount64 is a copy of Go 1.9's math/bits.OnesCount64. 88 // Once this package can require Go 1.9, we can delete this 89 // and update the caller to use bits.OnesCount64. 90 func onesCount64(x uint64) int { 91 const m0 = 0x5555555555555555 // 01010101 ... 92 const m1 = 0x3333333333333333 // 00110011 ... 93 const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ... 94 const m3 = 0x00ff00ff00ff00ff // etc. 95 const m4 = 0x0000ffff0000ffff 96 97 // Implementation: Parallel summing of adjacent bits. 98 // See "Hacker's Delight", Chap. 5: Counting Bits. 99 // The following pattern shows the general approach: 100 // 101 // x = x>>1&(m0&m) + x&(m0&m) 102 // x = x>>2&(m1&m) + x&(m1&m) 103 // x = x>>4&(m2&m) + x&(m2&m) 104 // x = x>>8&(m3&m) + x&(m3&m) 105 // x = x>>16&(m4&m) + x&(m4&m) 106 // x = x>>32&(m5&m) + x&(m5&m) 107 // return int(x) 108 // 109 // Masking (& operations) can be left away when there's no 110 // danger that a field's sum will carry over into the next 111 // field: Since the result cannot be > 64, 8 bits is enough 112 // and we can ignore the masks for the shifts by 8 and up. 113 // Per "Hacker's Delight", the first line can be simplified 114 // more, but it saves at best one instruction, so we leave 115 // it alone for clarity. 116 const m = 1<<64 - 1 117 x = x>>1&(m0&m) + x&(m0&m) 118 x = x>>2&(m1&m) + x&(m1&m) 119 x = (x>>4 + x) & (m2 & m) 120 x += x >> 8 121 x += x >> 16 122 x += x >> 32 123 return int(x) & (1<<7 - 1) 124 }