Skip to content

Commit d4cdb08

Browse files
endersonmaialneto
authored andcommitted
add luacpu module
1 parent 8944dc3 commit d4cdb08

File tree

4 files changed

+199
-2
lines changed

4 files changed

+199
-2
lines changed

Kbuild

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,5 @@ obj-$(CONFIG_LUNATIK_CRYPTO_SKCIPHER) += lib/luacrypto_skcipher.o
5252
obj-$(CONFIG_LUNATIK_CRYPTO_AEAD) += lib/luacrypto_aead.o
5353
obj-$(CONFIG_LUNATIK_CRYPTO_RNG) += lib/luacrypto_rng.o
5454
obj-$(CONFIG_LUNATIK_CRYPTO_COMP) += lib/luacrypto_comp.o
55+
obj-$(CONFIG_LUNATIK_CPU) += lib/luacpu.o
5556

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ all: lunatik_sym.h
3030
CONFIG_LUNATIK_NETFILTER=m CONFIG_LUNATIK_COMPLETION=m \
3131
CONFIG_LUNATIK_CRYPTO_SHASH=m CONFIG_LUNATIK_CRYPTO_SKCIPHER=m \
3232
CONFIG_LUNATIK_CRYPTO_AEAD=m CONFIG_LUNATIK_CRYPTO_RNG=m \
33-
CONFIG_LUNATIK_CRYPTO_COMP=m
33+
CONFIG_LUNATIK_CRYPTO_COMP=m CONFIG_LUNATIK_CPU=m
3434

3535
clean:
3636
${MAKE} -C ${MODULES_BUILD_PATH} M=${PWD} clean

bin/lunatik

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ local lunatik = {
1010
modules = {"lunatik", "luadevice", "lualinux", "luanotifier", "luasocket", "luarcu",
1111
"luathread", "luafib", "luadata", "luaprobe", "luasyscall", "luaxdp", "luafifo", "luaxtable",
1212
"luanetfilter", "luacompletion", "luacrypto_shash", "luacrypto_skcipher", "luacrypto_aead",
13-
"luacrypto_rng", "luacrypto_comp", "lunatik_run"}
13+
"luacrypto_rng", "luacrypto_comp", "luacpu", "lunatik_run"},
1414
}
1515

1616
function lunatik.prompt()

lib/luacpu.c

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* SPDX-FileCopyrightText: (c) 2025 Enderson Maia <[email protected]
3+
* SPDX-License-Identifier: MIT OR GPL-2.0-only
4+
*/
5+
6+
/***
7+
* Linux CPU Lua interface.
8+
*
9+
* This module provides access to Linux's CPU abstractions.
10+
*
11+
* @module cpu
12+
*/
13+
14+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15+
#include <linux/module.h>
16+
#include <linux/cpumask.h>
17+
#include <linux/kernel_stat.h>
18+
19+
#include <lua.h>
20+
#include <lualib.h>
21+
#include <lauxlib.h>
22+
23+
#include <lunatik.h>
24+
25+
#define LUACPU_NUM(name) \
26+
static int luacpu_num_##name(lua_State *L) { \
27+
lua_pushinteger(L, (lua_Integer)num_##name##_cpus()); \
28+
return 1; \
29+
}
30+
31+
/***
32+
* Returns the possible CPUs in the system.
33+
*
34+
* @function num_possible
35+
* @treturn integer The number of possible CPUs in the system
36+
*/
37+
LUACPU_NUM(possible)
38+
39+
/***
40+
* Returns the possible CPUs in the system.
41+
*
42+
* @function num_possible
43+
* @treturn integer The number of possible CPUs in the system
44+
*/
45+
LUACPU_NUM(present)
46+
47+
/***
48+
* Returns the possible CPUs in the system.
49+
*
50+
* @function num_possible
51+
* @treturn integer The number of possible CPUs in the system
52+
*/
53+
LUACPU_NUM(online)
54+
55+
/***
56+
* Macro to set CPU statistics in Lua table.
57+
* @param L Lua state
58+
* @param idx Index of the table in the Lua stack
59+
* @param kcs Kernel CPU statistics structure (kernel_cpustat)
60+
* @param name Field name in the Lua table
61+
* @param NAME Corresponding C enum name for CPU time
62+
*/
63+
#define luacpu_setstat(L, idx, kcs, name, NAME) \
64+
do { \
65+
lua_pushinteger(L, (lua_Integer)kcs.cpustat[CPUTIME_##NAME]); \
66+
lua_setfield(L, idx - 1, #name); \
67+
} while (0)
68+
69+
/***
70+
* Gets CPU statistics for a specific CPU.
71+
* Fetches kernel CPU statistics including user, nice, system, idle, iowait,
72+
* irq, softirq, steal, guest, guest_nice and forceidle times.
73+
*
74+
* @function stats
75+
* @tparam integer cpu The CPU number (0-based) to query.
76+
* @treturn table A table containing CPU time statistics with the following fields:
77+
* @tfield integer user Time spent in user mode
78+
* @tfield integer nice Time spent in user mode with low priority (nice)
79+
* @tfield integer system Time spent in system mode
80+
* @tfield integer idle Time spent in idle task
81+
* @tfield integer iowait Time waiting for I/O to complete
82+
* @tfield integer irq Time servicing hardware interrupts
83+
* @tfield integer softirq Time servicing software interrupts
84+
* @tfield integer steal Time stolen by other operating systems (virtualized environment)
85+
* @tfield integer guest Time spent running a virtual CPU for guest OS
86+
* @tfield integer guest_nice Time spent running a niced guest
87+
* @tfield integer forceidle Time spent in forced idle (if CONFIG_SCHED_CORE is enabled)
88+
* @raise Error if CPU is offline
89+
* @usage
90+
* local cpu0 = cpu.stats(0)
91+
* print("CPU 0 user time:", cpu0.user)
92+
* print("CPU 0 idle time:", cpu0.idle)
93+
*/
94+
static int luacpu_stats(lua_State *L)
95+
{
96+
unsigned int cpu = luaL_checkinteger(L, 1);
97+
struct kernel_cpustat kcs;
98+
99+
luaL_argcheck(L, cpu_online(cpu), 1, "CPU is offline");
100+
101+
kcpustat_cpu_fetch(&kcs, cpu);
102+
103+
lua_createtable(L, 0, NR_STATS);
104+
105+
luacpu_setstat(L, -1, kcs, user, USER);
106+
luacpu_setstat(L, -1, kcs, nice, NICE);
107+
luacpu_setstat(L, -1, kcs, system, SYSTEM);
108+
luacpu_setstat(L, -1, kcs, idle, IDLE);
109+
luacpu_setstat(L, -1, kcs, iowait, IOWAIT);
110+
luacpu_setstat(L, -1, kcs, irq, IRQ);
111+
luacpu_setstat(L, -1, kcs, softirq, SOFTIRQ);
112+
luacpu_setstat(L, -1, kcs, steal, STEAL);
113+
luacpu_setstat(L, -1, kcs, guest, GUEST);
114+
luacpu_setstat(L, -1, kcs, guest_nice, GUEST_NICE);
115+
#ifdef CONFIG_SCHED_CORE
116+
luacpu_setstat(L, -1, kcs, forceidle, FORCEIDLE);
117+
#endif
118+
return 1;
119+
}
120+
121+
#define LUACPU_FOREACH(name) \
122+
static int luacpu_foreach_##name(lua_State *L) { \
123+
unsigned int cpu; \
124+
luaL_checktype(L, 1, LUA_TFUNCTION); \
125+
for_each_##name##_cpu(cpu) { \
126+
lua_pushvalue(L, 1); \
127+
lua_pushinteger(L, cpu); \
128+
lua_call(L, 1, 0); \
129+
} \
130+
return 0; \
131+
};
132+
133+
/***
134+
* Iterates over all possible CPUs and calls a function for each.
135+
*
136+
* @function foreach_possible
137+
* @tparam function callback Function to call for each possible CPU
138+
* @usage
139+
* cpu.foreach_possible(function(cpu_num)
140+
* print("CPU", cpu.stats(cpu_num))
141+
* end)
142+
*/
143+
LUACPU_FOREACH(possible)
144+
145+
/***
146+
* Iterates over all present CPUs and calls a function for each.
147+
*
148+
* @function foreach_present
149+
* @tparam function callback Function to call for each present CPU
150+
* @usage
151+
* cpu.foreach_present(function(cpu_num)
152+
* print("CPU", cpu.stats(cpu_num))
153+
* end)
154+
*/
155+
LUACPU_FOREACH(present)
156+
157+
/***
158+
* Iterates over all online CPUs and calls a function for each.
159+
*
160+
* @function foreach_online
161+
* @tparam function callback Function to call for each online CPU
162+
* @usage
163+
* cpu.foreach_online(function(cpu_num)
164+
* print("CPU", cpu.stats(cpu_num))
165+
* end)
166+
*/
167+
LUACPU_FOREACH(online)
168+
169+
static const luaL_Reg luacpu_lib[] = {
170+
{"num_possible", luacpu_num_possible},
171+
{"num_present", luacpu_num_present},
172+
{"num_online", luacpu_num_online},
173+
{"stats", luacpu_stats},
174+
{"foreach_possible", luacpu_foreach_possible},
175+
{"foreach_present", luacpu_foreach_present},
176+
{"foreach_online", luacpu_foreach_online},
177+
{NULL, NULL}
178+
};
179+
180+
LUNATIK_NEWLIB(cpu, luacpu_lib, NULL, NULL);
181+
182+
static int __init luacpu_init(void)
183+
{
184+
return 0;
185+
}
186+
187+
static void __exit luacpu_exit(void)
188+
{
189+
}
190+
191+
module_init(luacpu_init);
192+
module_exit(luacpu_exit);
193+
MODULE_LICENSE("Dual MIT/GPL");
194+
MODULE_AUTHOR("Enderson Maia <[email protected]");
195+
MODULE_DESCRIPTION("Lunatik interface to Linux's CPU abstractions.");
196+

0 commit comments

Comments
 (0)