summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2022-07-29 10:58:29 +0800
committerGitHub <[email protected]>2022-07-29 10:58:29 +0800
commitd554a535538a83a4b071e4113ad96afe7bd9a694 (patch)
treeffdd35c1bfa291cc29f2a7296406d5b7ff85b505
parente60aa2dd105a14da59e1fedbcdbf3bc4adb7ba36 (diff)
parent4fc14288cfe6b2ecd0164ffb1b4dd4669adbd72d (diff)
Merge pull request #2613 from xmake-io/cpuinfo
add cpuinfo
-rw-r--r--.github/workflows/freebsd.yml2
-rw-r--r--core/src/xmake/os/cpuinfo.c203
-rw-r--r--core/src/xmake/os/meminfo.c1
-rw-r--r--tests/modules/os/cpuinfo.lua7
-rw-r--r--tests/modules/os/meminfo.lua6
-rw-r--r--xmake/core/base/cpu.lua30
-rw-r--r--xmake/core/base/memory.lua8
7 files changed, 253 insertions, 4 deletions
diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml
index 0cd61b130..805c5266a 100644
--- a/.github/workflows/freebsd.yml
+++ b/.github/workflows/freebsd.yml
@@ -20,7 +20,7 @@ jobs:
submodules: true
- name: Tests
- uses: vmactions/[email protected]
+ uses: vmactions/freebsd-vm@v0
with:
usesh: true
mem: 4096
diff --git a/core/src/xmake/os/cpuinfo.c b/core/src/xmake/os/cpuinfo.c
index bec9aff2c..49f6e27a4 100644
--- a/core/src/xmake/os/cpuinfo.c
+++ b/core/src/xmake/os/cpuinfo.c
@@ -29,6 +29,201 @@
* includes
*/
#include "prefix.h"
+#if defined(TB_CONFIG_OS_MACOSX)
+# include <sys/sysctl.h>
+# include <sys/types.h>
+# include <mach/mach.h>
+# include <mach/processor_info.h>
+# include <mach/mach_host.h>
+#elif defined(TB_CONFIG_OS_WINDOWS)
+# include <windows.h>
+#elif defined(TB_CONFIG_OS_LINUX)
+# include <stdio.h>
+#elif defined(TB_CONFIG_OS_BSD)
+# include <stdio.h>
+# include <string.h>
+# include <sys/types.h>
+# include <sys/sysctl.h>
+# include <unistd.h>
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private implementation
+ */
+#if defined(TB_CONFIG_OS_WINDOWS)
+static tb_uint64_t xm_os_cpuinfo_subtract_times(FILETIME const* one, FILETIME const* two)
+{
+ LARGE_INTEGER a, b;
+ a.LowPart = one->dwLowDateTime;
+ a.HighPart = one->dwHighDateTime;
+
+ b.LowPart = two->dwLowDateTime;
+ b.HighPart = two->dwHighDateTime;
+
+ return (tb_uint64_t)(a.QuadPart - b.QuadPart);
+}
+#endif
+
+static tb_float_t xm_os_cpuinfo_usagerate()
+{
+#if defined(TB_CONFIG_OS_MACOSX)
+ tb_float_t usagerate = 0;
+ natural_t cpu_count = 0;
+ processor_info_array_t cpuinfo;
+ mach_msg_type_number_t cpuinfo_count;
+ static tb_hong_t s_time = 0;
+ if (tb_mclock() - s_time > 1000 && host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpu_count, &cpuinfo, &cpuinfo_count) == KERN_SUCCESS)
+ {
+ static processor_info_array_t s_cpuinfo_prev = tb_null;
+ static mach_msg_type_number_t s_cpuinfo_count_prev = 0;
+ for (tb_int_t i = 0; i < cpu_count; ++i)
+ {
+ tb_int_t use, total;
+ if (s_cpuinfo_prev)
+ {
+ use = (cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] - s_cpuinfo_prev[(CPU_STATE_MAX * i) + CPU_STATE_USER])
+ + (cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] - s_cpuinfo_prev[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM])
+ + (cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE] - s_cpuinfo_prev[(CPU_STATE_MAX * i) + CPU_STATE_NICE]);
+ total = use + (cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE] - s_cpuinfo_prev[(CPU_STATE_MAX * i) + CPU_STATE_IDLE]);
+ }
+ else
+ {
+ use = cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] + cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] + cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE];
+ total = use + cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE];
+ }
+ usagerate += total > 0? ((tb_float_t)use / (tb_float_t)total) : 0;
+ }
+ if (s_cpuinfo_prev)
+ vm_deallocate(mach_task_self(), (vm_address_t)s_cpuinfo_prev, sizeof(integer_t) * s_cpuinfo_count_prev);
+ s_time = tb_mclock();
+ s_cpuinfo_prev = cpuinfo;
+ s_cpuinfo_count_prev = cpuinfo_count;
+ }
+ return cpu_count > 0? usagerate / cpu_count : 0;
+#elif defined(TB_CONFIG_OS_WINDOWS)
+ // kernel include idle_time
+ tb_float_t usagerate = 0;
+ FILETIME idle, kernel, user;
+ if (GetSystemTimes(&idle, &kernel, &user))
+ {
+ static FILETIME idle_prev = {0};
+ static FILETIME kernel_prev = {0};
+ static FILETIME user_prev = {0};
+
+ if (idle_prev.dwLowDateTime != 0 && idle_prev.dwHighDateTime != 0)
+ {
+ tb_uint64_t idle_diff = xm_os_cpuinfo_subtract_times(&idle, &idle_prev);
+ tb_uint64_t kernel_diff = xm_os_cpuinfo_subtract_times(&kernel, &kernel_prev);
+ tb_uint64_t user_diff = xm_os_cpuinfo_subtract_times(&user, &user_prev);
+
+ // kernel_time - idle_time = kernel_time, because kernel include idle_time
+ tb_uint64_t sys_total = kernel_diff + user_diff;
+ tb_uint64_t kernel_total = kernel_diff - idle_diff;
+
+ // sometimes kernel_time > idle_time
+ if (sys_total > 0)
+ usagerate = (tb_float_t)((tb_double_t)(kernel_total + user_diff) / sys_total);
+ }
+
+ idle_prev = idle;
+ kernel_prev = kernel;
+ user_prev = user;
+ }
+ return usagerate;
+#elif defined(TB_CONFIG_OS_LINUX)
+ tb_float_t usagerate = 0;
+ if (tb_file_info("/proc/stat", tb_null))
+ {
+ tb_bool_t ok = tb_false;
+ FILE* fp = fopen("/proc/stat", "r");
+ if (fp)
+ {
+ tb_char_t line[8192];
+ static tb_int64_t total_prev = 0;
+ static tb_int64_t active_prev = 0;
+ while (!feof(fp))
+ {
+ /* cpu 548760 0 867417 102226682 12430 0 9089 0 0 0
+ * cpu0 136863 0 218110 25632388 2706 0 2328 0 0 0
+ * cpu1 148383 0 213941 25627686 3925 0 2129 0 0 0
+ *
+ * The meanings of the columns are as follows, from left to right:
+ *
+ * user: normal processes executing in user mode
+ * nice: niced processes executing in user mode
+ * system: processes executing in kernel mode
+ * idle: twiddling thumbs
+ * iowait: waiting for I/O to complete
+ * irq: servicing interrupts
+ * softirq: servicing softirqs
+ * steal
+ * guest
+ * guest_nice
+ */
+ if (fgets(line, sizeof(line), fp) && !tb_strncmp(line, "cpu ", 4))
+ {
+ tb_int64_t user, nice, sys, idle, iowait, irq, softirq, steal, guest, guest_nice;
+ if (10 == sscanf(line, "cpu %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
+ &user, &nice, &sys, &idle, &iowait, &irq, &softirq, &steal, &guest, &guest_nice))
+ {
+ tb_int64_t active = user + nice + sys + irq + softirq + steal + guest + guest_nice;
+ tb_int64_t total = user + nice + sys + idle + iowait + irq + softirq + steal + guest + guest_nice;
+ if (total_prev > 0 && active_prev > 0)
+ {
+ tb_int64_t total_diff = total - total_prev;
+ tb_int64_t active_diff = active - active_prev;
+ if (total_diff > 0)
+ usagerate = (tb_float_t)((tb_double_t)active_diff / total_diff);
+ }
+ total_prev = total;
+ active_prev = active;
+ }
+ break;
+ }
+ }
+ fclose(fp);
+ }
+ }
+ return usagerate;
+#elif defined(TB_CONFIG_OS_BSD)
+# define CP_USER 0
+# define CP_NICE 1
+# define CP_SYS 2
+# define CP_INTR 3
+# define CP_IDLE 4
+# define CPUSTATES 5
+
+ static tb_int64_t total_prev = 0;
+ static tb_int64_t active_prev = 0;
+
+ tb_float_t usagerate = 0;
+ long states[CPUSTATES] = {0};
+ size_t states_size = sizeof(states);
+ if (sysctlbyname("kern.cp_time", &states, &states_size, tb_null, 0) == 0)
+ {
+ tb_long_t user = states[CP_USER];
+ tb_long_t nice = states[CP_NICE];
+ tb_long_t sys = states[CP_SYS];
+ tb_long_t intr = states[CP_INTR];
+ tb_long_t idle = states[CP_IDLE];
+
+ tb_int64_t active = user + nice + sys + intr;
+ tb_int64_t total = user + nice + sys + idle + intr;
+ if (total_prev > 0 && active_prev > 0)
+ {
+ tb_int64_t total_diff = total - total_prev;
+ tb_int64_t active_diff = active - active_prev;
+ if (total_diff > 0)
+ usagerate = (tb_float_t)((tb_double_t)active_diff / total_diff);
+ }
+ total_prev = total;
+ active_prev = active;
+ }
+ return usagerate;
+#else
+ return 0;
+#endif
+}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
@@ -54,5 +249,13 @@ tb_int_t xm_os_cpuinfo(lua_State* lua)
lua_pushinteger(lua, ncpu > 0? ncpu : 1);
lua_settable(lua, -3);
+ // get cpu usage rate
+ tb_float_t usagerate = xm_os_cpuinfo_usagerate();
+ if (usagerate >= 0)
+ {
+ lua_pushstring(lua, "usagerate");
+ lua_pushnumber(lua, usagerate);
+ lua_settable(lua, -3);
+ }
return 1;
}
diff --git a/core/src/xmake/os/meminfo.c b/core/src/xmake/os/meminfo.c
index b679e5aee..cd9ace234 100644
--- a/core/src/xmake/os/meminfo.c
+++ b/core/src/xmake/os/meminfo.c
@@ -36,6 +36,7 @@
# include <mach-o/dyld.h>
# include <mach-o/nlist.h>
#elif defined(TB_CONFIG_OS_LINUX)
+# include <stdio.h>
# include <sys/sysinfo.h>
#elif defined(TB_CONFIG_OS_WINDOWS)
# include <windows.h>
diff --git a/tests/modules/os/cpuinfo.lua b/tests/modules/os/cpuinfo.lua
new file mode 100644
index 000000000..dfb04350c
--- /dev/null
+++ b/tests/modules/os/cpuinfo.lua
@@ -0,0 +1,7 @@
+function main()
+ print(os.cpuinfo())
+ while true do
+ print("total: %d%%", math.floor(os.cpuinfo("usagerate") * 100))
+ os.sleep(1000)
+ end
+end
diff --git a/tests/modules/os/meminfo.lua b/tests/modules/os/meminfo.lua
new file mode 100644
index 000000000..e42d4350f
--- /dev/null
+++ b/tests/modules/os/meminfo.lua
@@ -0,0 +1,6 @@
+function main()
+ while true do
+ print("%d%%", math.floor(os.meminfo("usagerate") * 100))
+ os.sleep(1000)
+ end
+end
diff --git a/xmake/core/base/cpu.lua b/xmake/core/base/cpu.lua
index a09aea4c9..aff0ee952 100644
--- a/xmake/core/base/cpu.lua
+++ b/xmake/core/base/cpu.lua
@@ -259,6 +259,22 @@ function cpu._info()
return cpuinfo
end
+-- get cpu stats info
+function cpu._statinfo(name)
+ local stats = cpu._STATS
+ local stime = cpu._STIME
+ if stats == nil or stime == nil or os.time() - stime > 1 then -- cache 1s
+ stats = os._cpuinfo()
+ cpu._STATS = stats
+ cpu._STIME = os.time()
+ end
+ if name then
+ return stats[name]
+ else
+ return stats
+ end
+end
+
-- get vendor id
function cpu.vendor()
return cpu._info().vendor_id
@@ -316,7 +332,12 @@ end
-- get cpu number
function cpu.number()
- return os._cpuinfo().ncpu
+ return cpu._statinfo("ncpu")
+end
+
+-- get cpu usage rate
+function cpu.usagerate()
+ return cpu._statinfo("usagerate")
end
-- get cpu info
@@ -328,8 +349,13 @@ function cpu.info(name)
cpuinfo.march = cpu.march()
cpuinfo.ncpu = cpu.number()
cpuinfo.features = cpu.features()
+ cpuinfo.usagerate = cpu.usagerate()
cpuinfo.model_name = cpu.model_name()
- return name and cpuinfo[name] or cpuinfo
+ if name then
+ return cpuinfo[name]
+ else
+ return cpuinfo
+ end
end
-- return module
diff --git a/xmake/core/base/memory.lua b/xmake/core/base/memory.lua
index 3bd00813d..27b7331d6 100644
--- a/xmake/core/base/memory.lua
+++ b/xmake/core/base/memory.lua
@@ -32,11 +32,17 @@ function memory.info(name)
meminfo = os._meminfo()
if meminfo.totalsize and meminfo.availsize then
meminfo.usagerate = (meminfo.totalsize - meminfo.availsize) / meminfo.totalsize
+ else
+ meminfo.usagerate = 0
end
memory._MEMINFO = meminfo
memory._MEMTIME = os.time()
end
- return name and meminfo[name] or meminfo
+ if name then
+ return meminfo[name]
+ else
+ return meminfo
+ end
end
-- return module