cpuset.h 4.1 KB
Newer Older
lishen's avatar
lishen committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*************************************************************************
 * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
 *
 * See LICENSE.txt for license information
 ************************************************************************/

#ifndef SCCL_CPUSET_H_
#define SCCL_CPUSET_H_

#include "base.h"

namespace sccl {
namespace hardware {
namespace topology {
namespace topo {
// Convert local_cpus, e.g. 0003ff,f0003fff to cpu_set_t

/**
 * 将十六进制字符转换为对应的整数值
 *
 * @param c 输入的十六进制字符(0-9, a-f)
 * @return 返回对应的整数值(0-15),如果输入无效则返回-1
 */
static int hexToInt(char c) {
    int v = c - '0';
    if(v < 0)
        return -1;
    if(v > 9)
        v = 10 + c - 'a';
    if((v < 0) || (v > 15))
        return -1;
    return v;
}

#define CPU_SET_N_U32 (sizeof(cpu_set_t) / sizeof(uint32_t))

/**
 * 将十六进制字符串转换为CPU集合掩码
 *
 * @param str 输入的十六进制字符串,用逗号分隔不同部分
 * @param mask 输出的CPU集合掩码
 * @return scclSuccess 表示转换成功
 *
 * @note 字符串从左到右对应掩码从高到低的32位字
 *       每个字符代表4位十六进制数
 *       遇到非十六进制字符会提前终止转换
 */
static scclResult_t scclStrToCpuset(const char* str, cpu_set_t* mask) {
    uint32_t cpumasks[CPU_SET_N_U32];
    int m       = CPU_SET_N_U32 - 1;
    cpumasks[m] = 0;
    for(int o = 0; o < strlen(str); o++) {
        char c = str[o];
        if(c == ',') {
            m--;
            cpumasks[m] = 0;
        } else {
            int v = hexToInt(c);
            if(v == -1)
                break;
            cpumasks[m] <<= 4;
            cpumasks[m] += v;
        }
    }
    // Copy cpumasks to mask
    for(int a = 0; m < CPU_SET_N_U32; a++, m++) {
        memcpy(((uint32_t*)mask) + a, cpumasks + m, sizeof(uint32_t));
    }
    return scclSuccess;
}

/**
 * 将CPU集合掩码转换为十六进制字符串表示
 *
 * @param mask 输入的CPU集合掩码
 * @param str 输出的字符串缓冲区,用于存储转换结果
 * @return 返回操作结果(scclSuccess表示成功)
 *
 * 转换规则:
 * 1. 将cpu_set_t按字节从高到低转换为十六进制字符串
 * 2. 每4个字节后添加一个逗号分隔符
 * 3. 忽略前导零
 */
static scclResult_t scclCpusetToStr(cpu_set_t* mask, char* str) {
    int c       = 0;
    uint8_t* m8 = (uint8_t*)mask;
    for(int o = sizeof(cpu_set_t) - 1; o >= 0; o--) {
        if(c == 0 && m8[o] == 0)
            continue;
        sprintf(str + c, "%02x", m8[o]);
        c += 2;
        if(o && o % 4 == 0) {
            sprintf(str + c, ",");
            c++;
        }
    }
    str[c] = '\0';
    return scclSuccess;
}

/**
 * 将CPU集合掩码转换为范围字符串表示
 *
 * @param mask 输入的CPU集合掩码
 * @param str  用于存储结果的缓冲区
 * @param len  缓冲区长度
 * @return     返回转换后的字符串指针(即str参数)
 *
 * 该函数将CPU集合掩码转换为可读的范围字符串格式,例如"0-3,5,7-9"。
 * 如果缓冲区空间不足,结果会被截断。空集合会返回空字符串。
 */
static char* scclCpusetToRangeStr(cpu_set_t* mask, char* str, size_t len) {
    int c     = 0;
    int start = -1;
    // Iterate through all possible CPU bits plus one extra position
    for(int cpu = 0; cpu <= CPU_SETSIZE; cpu++) {
        int isSet = (cpu == CPU_SETSIZE) ? 0 : CPU_ISSET(cpu, mask);
        // Start of a new range
        if(isSet && start == -1) {
            start = cpu;
        }
        // End of a range, add comma between ranges
        if(!isSet && start != -1) {
            if(cpu - 1 == start) {
                c += snprintf(str + c, len - c, "%s%d", c ? "," : "", start);
            } else {
                c += snprintf(str + c, len - c, "%s%d-%d", c ? "," : "", start, cpu - 1);
            }
            if(c >= len - 1)
                break;
            start = -1;
        }
    }
    if(c == 0)
        str[0] = '\0';
    return str;
}

} // namespace topo
} // namespace topology
} // namespace hardware
} // namespace sccl
#endif