* Copyright (c) 2020 Huawei Technologies Co., Ltd.
* A-Tune is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Create: 2020-04-28
*/
package cpumask
import (
"strconv"
"gitee.com/openeuler/A-Tune/common/utils"
)
const cpumaskNum = 10
const oneMaskBits = 64
type Cpumask struct {
Masks [cpumaskNum]uint64
}
func (mask *Cpumask) Init() {
for i := 0; i < cpumaskNum; i++ {
mask.Masks[i] = 0
}
}
func (mask *Cpumask) And(dst *Cpumask) {
for i := 0; i < cpumaskNum; i++ {
mask.Masks[i] &= dst.Masks[i]
}
}
func (mask *Cpumask) Or(dst *Cpumask) {
for i := 0; i < cpumaskNum; i++ {
mask.Masks[i] |= dst.Masks[i]
}
}
func (mask *Cpumask) IsEqual(dst *Cpumask) bool {
for i := 0; i < cpumaskNum; i++ {
if mask.Masks[i] != dst.Masks[i] {
return false
}
}
return true
}
func (mask *Cpumask) Set(nbit int) {
maskIndex := nbit / oneMaskBits
var oneMask = uint64(1) << uint(nbit%oneMaskBits)
if maskIndex >= cpumaskNum || maskIndex < 0 {
return
}
mask.Masks[maskIndex] |= oneMask
}
func (mask *Cpumask) Clear(nbit int) {
maskIndex := nbit / oneMaskBits
var oneMask = uint64(1) << uint(nbit%oneMaskBits)
if maskIndex >= cpumaskNum || maskIndex < 0 {
return
}
mask.Masks[maskIndex] &= ^oneMask
}
func (mask *Cpumask) Copy(dst *Cpumask) {
for i := 0; i < cpumaskNum; i++ {
mask.Masks[i] = dst.Masks[i]
}
}
func (mask *Cpumask) ParseString(str string) error {
var err error
const CharsPerUint64 = 16
mask.Init()
for maskIndex := 0; maskIndex < cpumaskNum; maskIndex++ {
endIndex := len(str) - maskIndex*CharsPerUint64
startIndex := endIndex - CharsPerUint64
if startIndex < 0 {
startIndex = 0
}
oneMaskStr := str[startIndex:endIndex]
mask.Masks[maskIndex], err = strconv.ParseUint(oneMaskStr, utils.HexBase, utils.Uint64Bits)
if err != nil {
return err
}
if startIndex == 0 {
break
}
}
return nil
}
func oneMaskWeight(mask uint64) int {
weight := 0
for mask > 0 {
weight++
mask = mask & (mask - 1)
}
return weight
}
func (mask *Cpumask) Weight() int {
weight := 0
for i := 0; i < cpumaskNum; i++ {
weight += oneMaskWeight(mask.Masks[i])
}
return weight
}
func lowBit(mask uint64) int {
n := 0
if mask&0xffffffff == 0 {
mask = mask >> 32
n += 32
}
if mask&0xffff == 0 {
mask = mask >> 16
n += 16
}
if mask&0xff == 0 {
mask = mask >> 8
n += 8
}
if mask&0xf == 0 {
mask = mask >> 4
n += 4
}
if mask&0x3 == 0 {
mask = mask >> 2
n += 2
}
if mask&0x1 == 0 {
mask = mask >> 1
n++
}
if mask&0x1 == 0 {
return -1
}
return n
}
func (mask *Cpumask) Foreach(startBit int) int {
startIndex := (startBit + 1) / oneMaskBits
firstMask := mask.Masks[startIndex]
firstMask &= ^((uint64(1) << uint64((startBit+1)%oneMaskBits)) - 1)
leftbit := lowBit(firstMask)
if leftbit != -1 {
return startIndex*oneMaskBits + leftbit
}
for startIndex++; startIndex < cpumaskNum; startIndex++ {
leftbit = lowBit(mask.Masks[startIndex])
if leftbit != -1 {
return startIndex*oneMaskBits + leftbit
}
}
return -1
}