5 Star 0 Fork 1

src-openEuler/sigar

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
bz714249-1-cpu-count.patch 6.89 KB
一键复制 编辑 原始数据 按行查看 历史
maminjie 提交于 2020-09-04 11:54 . package init
commit cae27197baf656ae0d7734913d8714995a787ee4
Date: Wed Aug 17 15:35:15 2011 +0200
Correct reporting of number of CPU cores on Linux
There are a number of problems with the implementation of
sigar_cpu_info_list_get() on Linux:
* The call sysconf(_SC_NPROCESSORS_CONF) returns the number of processors
in the system, not the number of cores (i.e. in a hyperthreaded
system, sigar_cpu_total_count() gives the number of threads, not cores).
* It turns out that the CPUINFO instruction on x86 is not a reliable way of
getting the number of cores, or even the number of threads (which is what
sigar_cpu_core_count() is actually trying to read).
* core_rollup ignores all but one processor per socket, on the assumption
that entries in /proc/cpuinfo appear grouped by socket. This assumption
is not correct.
* The get_cpuinfo_max_freq() function retrieves data corresponding to the
wrong processor in the presence of the core_rollup option (although the
practical effect is cancelled out by the previous issue, purely by
coincidence).
The solution is to obtain all information required about the processors
from the kernel via the /proc/cpuinfo file. This allows us to return the
actual number of cores, rather than threads, in the cores_per_socket and
total_cores variables. It also allows us to return the correct number of
sockets in the system, which was broken by a combination of the first two
issues above. Theoretically, all of this would work even in an asymmetric
system with different numbers of cores in each socket. It should work even
if the processors listed in /proc/cpuinfo are in arbitrary order, even in
the presence of the core_rollup option.
diff --git a/src/os/linux/linux_sigar.c b/src/os/linux/linux_sigar.c
index 0e4283f..e65abd6 100644
--- a/src/os/linux/linux_sigar.c
+++ b/src/os/linux/linux_sigar.c
@@ -46,6 +46,13 @@
#define PROC_PARTITIONS PROC_FS_ROOT "partitions"
#define PROC_DISKSTATS PROC_FS_ROOT "diskstats"
+typedef struct {
+ sigar_cpu_info_t cpu;
+ int socket;
+ int core;
+ int processor;
+} processor_info_t;
+
/*
* /proc/self/stat fields:
* 1 - pid
@@ -1499,16 +1506,15 @@ static SIGAR_INLINE void cpu_info_strcpy(char *ptr, char *buf, int len)
}
}
-static int get_cpu_info(sigar_t *sigar, sigar_cpu_info_t *info,
+static int get_cpu_info(sigar_t *sigar, processor_info_t *proc,
FILE *fp)
{
char buffer[BUFSIZ], *ptr;
+ sigar_cpu_info_t *info = &proc->cpu;
int found = 0;
- /* UML vm wont have "cpu MHz" or "cache size" fields */
- info->mhz = 0;
- info->cache_size = 0;
+ memset(proc, 0, sizeof(*proc));
#ifdef __powerpc64__
SIGAR_SSTRCPY(info->vendor, "IBM");
@@ -1520,6 +1526,10 @@ static int get_cpu_info(sigar_t *sigar, sigar_cpu_info_t *info,
if (strnEQ(ptr, "processor", 9)) {
found = 1;
}
+ else if (strnEQ(ptr, "physical id", 11)) {
+ ptr = cpu_info_strval(ptr);
+ proc->socket = sigar_strtoul(ptr);
+ }
break;
case 'v':
/* "vendor_id" or "vendor" */
@@ -1555,6 +1565,14 @@ static int get_cpu_info(sigar_t *sigar, sigar_cpu_info_t *info,
ptr = cpu_info_strval(ptr);
info->cache_size = sigar_strtoul(ptr);
}
+ else if (strnEQ(ptr, "core id", 7)) {
+ ptr = cpu_info_strval(ptr);
+ proc->core = sigar_strtoul(ptr);
+ }
+ else if (strnEQ(ptr, "cpu cores", 9)) {
+ ptr = cpu_info_strval(ptr);
+ info->cores_per_socket = sigar_strtoul(ptr);
+ }
#ifdef __powerpc64__
/* each /proc/cpuinfo entry looks like so:
* processor : 0
@@ -1618,11 +1636,55 @@ static void get_cpuinfo_min_freq(sigar_cpu_info_t *cpu_info, int num)
}
}
+typedef struct {
+ size_t size;
+ sigar_uint32_t *data;
+} bitmap_t;
+
+static int bitmap_check(sigar_t *sigar, bitmap_t *bitmap, unsigned int index)
+{
+ int ret = 0;
+ size_t i = index / 32;
+ if (i >= bitmap->size) {
+ void *new_data;
+ size_t old_size = bitmap->size;
+
+ bitmap->size *= 2;
+ if (i >= bitmap->size) {
+ bitmap->size = i + 1;
+ }
+
+ new_data = realloc(bitmap->data,
+ bitmap->size * sizeof(sigar_uint32_t));
+
+ if (new_data) {
+ bitmap->data = new_data;
+ memset(&bitmap->data[old_size], 0,
+ (bitmap->size - old_size) * sizeof(sigar_uint32_t));
+ } else {
+ // Out of memory. This could result in counting a single socket
+ // multiple times if the physical id is huge.
+ sigar_log_printf(sigar, SIGAR_LOG_WARN,
+ "Cannot allocate CPU socket bitmap");
+ return 0;
+ }
+ } else {
+ ret = (bitmap->data[i] & (1 << (index % 32))) != 0;
+ }
+
+ bitmap->data[i] |= 1 << (index % 32);
+
+ return ret;
+}
+
int sigar_cpu_info_list_get(sigar_t *sigar,
sigar_cpu_info_list_t *cpu_infos)
{
FILE *fp;
int core_rollup = sigar_cpu_core_rollup(sigar), i=0;
+ processor_info_t processor;
+ int total_sockets = 0, total_cores = 0;
+ bitmap_t sockets_found = {};
if (!(fp = fopen(PROC_FS_ROOT "cpuinfo", "r"))) {
return errno;
@@ -1631,26 +1693,33 @@ int sigar_cpu_info_list_get(sigar_t *sigar,
(void)sigar_cpu_total_count(sigar);
sigar_cpu_info_list_create(cpu_infos);
- while (get_cpu_info(sigar, &cpu_infos->data[cpu_infos->number], fp)) {
+ while (get_cpu_info(sigar, &processor, fp)) {
sigar_cpu_info_t *info;
- if (core_rollup && (i++ % sigar->lcpu)) {
- continue; /* fold logical processors */
+ if (!bitmap_check(sigar, &sockets_found, processor.socket)) {
+ total_sockets++;
+ total_cores += processor.cpu.cores_per_socket;
+ } else if (core_rollup) {
+ continue;
}
info = &cpu_infos->data[cpu_infos->number];
- get_cpuinfo_max_freq(info, cpu_infos->number);
- get_cpuinfo_min_freq(info, cpu_infos->number);
- info->total_cores = sigar->ncpu;
- info->cores_per_socket = sigar->lcpu;
- info->total_sockets = sigar_cpu_socket_count(sigar);
+ memcpy(info, &processor.cpu, sizeof(*info));
+ get_cpuinfo_max_freq(info, processor.processor);
+ get_cpuinfo_min_freq(info, processor.processor);
++cpu_infos->number;
SIGAR_CPU_INFO_LIST_GROW(cpu_infos);
}
fclose(fp);
+ free(sockets_found.data);
+
+ for (i = 0; i < cpu_infos->number; i++) {
+ cpu_infos->data[i].total_cores = total_cores;
+ cpu_infos->data[i].total_sockets = total_sockets;
+ }
return SIGAR_OK;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/src-openeuler/sigar.git
git@gitee.com:src-openeuler/sigar.git
src-openeuler
sigar
sigar
master

搜索帮助