mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 18:44:01 +00:00
procstat&sysstat
This commit is contained in:
@@ -385,6 +385,7 @@ set(RAMDISK_ROOT_APPS)
|
|||||||
set(USER_SHELL_COMMAND_APPS
|
set(USER_SHELL_COMMAND_APPS
|
||||||
help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield
|
help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield
|
||||||
bg fg jobs kill ps top
|
bg fg jobs kill ps top
|
||||||
|
procstat sysstat
|
||||||
shutdown restart exit clear ansi ansitest wavplay fastfetch memstat fsstat taskstat userstat
|
shutdown restart exit clear ansi ansitest wavplay fastfetch memstat fsstat taskstat userstat
|
||||||
shstat stats tty dmesg kbdstat mkdir touch write append cp mv rm kdbg
|
shstat stats tty dmesg kbdstat mkdir touch write append cp mv rm kdbg
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ static int ush_cmd_help(void) {
|
|||||||
ush_writeln(" spawn <path|name> [args...] / bg <path|name> [args...]");
|
ush_writeln(" spawn <path|name> [args...] / bg <path|name> [args...]");
|
||||||
ush_writeln(" wait <pid> / fg [pid]");
|
ush_writeln(" wait <pid> / fg [pid]");
|
||||||
ush_writeln(" kill <pid> [signal]");
|
ush_writeln(" kill <pid> [signal]");
|
||||||
ush_writeln(" jobs [-a] / ps [-a] [-u] / top [--once] [-n loops] [-d ticks]");
|
ush_writeln(" jobs [-a] / ps [-a] [-u] / procstat [pid|self] [-a]");
|
||||||
|
ush_writeln(" top [--once] [-n loops] [-d ticks] / sysstat [-a] [-n N]");
|
||||||
ush_writeln(" kdbg sym <addr> / kdbg bt <rbp> <rip> / kdbg regs");
|
ush_writeln(" kdbg sym <addr> / kdbg bt <rbp> <rip> / kdbg regs");
|
||||||
ush_writeln(" sleep <ticks>");
|
ush_writeln(" sleep <ticks>");
|
||||||
ush_writeln(" spin (busy loop test for Alt+Ctrl+C)");
|
ush_writeln(" spin (busy loop test for Alt+Ctrl+C)");
|
||||||
|
|||||||
244
cleonos/c/apps/procstat_main.c
Normal file
244
cleonos/c/apps/procstat_main.c
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
#include "cmd_runtime.h"
|
||||||
|
|
||||||
|
static const char *ush_procstat_state_name(u64 state) {
|
||||||
|
if (state == CLEONOS_PROC_STATE_PENDING) {
|
||||||
|
return "PEND";
|
||||||
|
}
|
||||||
|
if (state == CLEONOS_PROC_STATE_RUNNING) {
|
||||||
|
return "RUN ";
|
||||||
|
}
|
||||||
|
if (state == CLEONOS_PROC_STATE_STOPPED) {
|
||||||
|
return "STOP";
|
||||||
|
}
|
||||||
|
if (state == CLEONOS_PROC_STATE_EXITED) {
|
||||||
|
return "EXIT";
|
||||||
|
}
|
||||||
|
return "UNKN";
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_procstat_next_token(const char **io_cursor, char *out, u64 out_size) {
|
||||||
|
const char *p;
|
||||||
|
u64 n = 0ULL;
|
||||||
|
|
||||||
|
if (io_cursor == (const char **)0 || out == (char *)0 || out_size == 0ULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[0] = '\0';
|
||||||
|
p = *io_cursor;
|
||||||
|
|
||||||
|
if (p == (const char *)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*p != '\0' && ush_is_space(*p) != 0) {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == '\0') {
|
||||||
|
*io_cursor = p;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*p != '\0' && ush_is_space(*p) == 0) {
|
||||||
|
if (n + 1ULL < out_size) {
|
||||||
|
out[n++] = *p;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[n] = '\0';
|
||||||
|
*io_cursor = p;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_procstat_print_line(const cleonos_proc_snapshot *snap) {
|
||||||
|
if (snap == (const cleonos_proc_snapshot *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_write("PID=");
|
||||||
|
ush_write_hex_u64(snap->pid);
|
||||||
|
ush_write(" ST=");
|
||||||
|
ush_write(ush_procstat_state_name(snap->state));
|
||||||
|
ush_write(" TTY=");
|
||||||
|
ush_write_hex_u64(snap->tty_index);
|
||||||
|
ush_write(" RT=");
|
||||||
|
ush_write_hex_u64(snap->runtime_ticks);
|
||||||
|
ush_write(" MEM=");
|
||||||
|
ush_write_hex_u64(snap->mem_bytes);
|
||||||
|
ush_write(" SIG=");
|
||||||
|
ush_write_hex_u64(snap->last_signal);
|
||||||
|
ush_write(" PATH=");
|
||||||
|
ush_writeln(snap->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_procstat_print_detail(const cleonos_proc_snapshot *snap) {
|
||||||
|
if (snap == (const cleonos_proc_snapshot *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_writeln("procstat:");
|
||||||
|
ush_print_kv_hex(" PID", snap->pid);
|
||||||
|
ush_print_kv_hex(" PPID", snap->ppid);
|
||||||
|
ush_write(" STATE: ");
|
||||||
|
ush_write(ush_procstat_state_name(snap->state));
|
||||||
|
ush_write_char('\n');
|
||||||
|
ush_print_kv_hex(" STATE_ID", snap->state);
|
||||||
|
ush_print_kv_hex(" TTY", snap->tty_index);
|
||||||
|
ush_print_kv_hex(" STARTED_TICK", snap->started_tick);
|
||||||
|
ush_print_kv_hex(" EXITED_TICK", snap->exited_tick);
|
||||||
|
ush_print_kv_hex(" RUNTIME_TICKS", snap->runtime_ticks);
|
||||||
|
ush_print_kv_hex(" MEM_BYTES", snap->mem_bytes);
|
||||||
|
ush_print_kv_hex(" EXIT_STATUS", snap->exit_status);
|
||||||
|
ush_print_kv_hex(" LAST_SIGNAL", snap->last_signal);
|
||||||
|
ush_print_kv_hex(" LAST_FAULT_VECTOR", snap->last_fault_vector);
|
||||||
|
ush_print_kv_hex(" LAST_FAULT_ERROR", snap->last_fault_error);
|
||||||
|
ush_print_kv_hex(" LAST_FAULT_RIP", snap->last_fault_rip);
|
||||||
|
ush_write(" PATH: ");
|
||||||
|
ush_writeln(snap->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_procstat_parse_args(const char *arg, u64 *out_pid, int *out_has_pid, int *out_include_exited) {
|
||||||
|
const char *cursor = arg;
|
||||||
|
char token[USH_PATH_MAX];
|
||||||
|
u64 parsed_pid = 0ULL;
|
||||||
|
int has_pid = 0;
|
||||||
|
int include_exited = 0;
|
||||||
|
|
||||||
|
if (out_pid == (u64 *)0 || out_has_pid == (int *)0 || out_include_exited == (int *)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ush_procstat_next_token(&cursor, token, (u64)sizeof(token)) != 0) {
|
||||||
|
if (ush_streq(token, "-a") != 0 || ush_streq(token, "--all") != 0) {
|
||||||
|
include_exited = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_streq(token, "self") != 0) {
|
||||||
|
if (has_pid != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
parsed_pid = cleonos_sys_getpid();
|
||||||
|
has_pid = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_parse_u64_dec(token, &parsed_pid) != 0 && parsed_pid != 0ULL) {
|
||||||
|
if (has_pid != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
has_pid = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_pid = parsed_pid;
|
||||||
|
*out_has_pid = has_pid;
|
||||||
|
*out_include_exited = include_exited;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_cmd_procstat(const char *arg) {
|
||||||
|
u64 target_pid = 0ULL;
|
||||||
|
int has_pid = 0;
|
||||||
|
int include_exited = 0;
|
||||||
|
|
||||||
|
if (ush_procstat_parse_args(arg, &target_pid, &has_pid, &include_exited) == 0) {
|
||||||
|
ush_writeln("procstat: usage procstat [pid|self] [-a|--all]");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_pid != 0) {
|
||||||
|
cleonos_proc_snapshot snap;
|
||||||
|
|
||||||
|
if (cleonos_sys_proc_snapshot(target_pid, &snap, (u64)sizeof(snap)) == 0ULL) {
|
||||||
|
ush_writeln("procstat: pid not found");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_procstat_print_detail(&snap);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
u64 proc_count = cleonos_sys_proc_count();
|
||||||
|
u64 i;
|
||||||
|
u64 shown = 0ULL;
|
||||||
|
|
||||||
|
ush_writeln("procstat:");
|
||||||
|
|
||||||
|
for (i = 0ULL; i < proc_count; i++) {
|
||||||
|
u64 pid = 0ULL;
|
||||||
|
cleonos_proc_snapshot snap;
|
||||||
|
|
||||||
|
if (cleonos_sys_proc_pid_at(i, &pid) == 0ULL || pid == 0ULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleonos_sys_proc_snapshot(pid, &snap, (u64)sizeof(snap)) == 0ULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include_exited == 0 && snap.state == CLEONOS_PROC_STATE_EXITED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_procstat_print_line(&snap);
|
||||||
|
shown++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shown == 0ULL) {
|
||||||
|
ush_writeln("(no process)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cleonos_app_main(void) {
|
||||||
|
ush_cmd_ctx ctx;
|
||||||
|
ush_cmd_ret ret;
|
||||||
|
ush_state sh;
|
||||||
|
char initial_cwd[USH_PATH_MAX];
|
||||||
|
int has_context = 0;
|
||||||
|
int success = 0;
|
||||||
|
const char *arg = "";
|
||||||
|
|
||||||
|
ush_zero(&ctx, (u64)sizeof(ctx));
|
||||||
|
ush_zero(&ret, (u64)sizeof(ret));
|
||||||
|
ush_init_state(&sh);
|
||||||
|
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
|
||||||
|
|
||||||
|
if (ush_command_ctx_read(&ctx) != 0) {
|
||||||
|
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "procstat") != 0) {
|
||||||
|
has_context = 1;
|
||||||
|
arg = ctx.arg;
|
||||||
|
if (ctx.cwd[0] == '/') {
|
||||||
|
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
|
||||||
|
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
success = ush_cmd_procstat(arg);
|
||||||
|
|
||||||
|
if (has_context != 0) {
|
||||||
|
if (ush_streq(sh.cwd, initial_cwd) == 0) {
|
||||||
|
ret.flags |= USH_CMD_RET_FLAG_CWD;
|
||||||
|
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sh.exit_requested != 0) {
|
||||||
|
ret.flags |= USH_CMD_RET_FLAG_EXIT;
|
||||||
|
ret.exit_code = sh.exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)ush_command_ret_write(&ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (success != 0) ? 0 : 1;
|
||||||
|
}
|
||||||
@@ -155,7 +155,8 @@ static int ush_cmd_help(void) {
|
|||||||
ush_writeln(" spawn <path|name> [args...] / bg <path|name> [args...]");
|
ush_writeln(" spawn <path|name> [args...] / bg <path|name> [args...]");
|
||||||
ush_writeln(" wait <pid> / fg [pid]");
|
ush_writeln(" wait <pid> / fg [pid]");
|
||||||
ush_writeln(" kill <pid> [signal]");
|
ush_writeln(" kill <pid> [signal]");
|
||||||
ush_writeln(" jobs [-a] / ps [-a] [-u] / top [--once] [-n loops] [-d ticks]");
|
ush_writeln(" jobs [-a] / ps [-a] [-u] / procstat [pid|self] [-a]");
|
||||||
|
ush_writeln(" top [--once] [-n loops] [-d ticks] / sysstat [-a] [-n N]");
|
||||||
ush_writeln(" kdbg sym <addr> / kdbg bt <rbp> <rip> / kdbg regs");
|
ush_writeln(" kdbg sym <addr> / kdbg bt <rbp> <rip> / kdbg regs");
|
||||||
ush_writeln(" sleep <ticks>");
|
ush_writeln(" sleep <ticks>");
|
||||||
ush_writeln(" yield");
|
ush_writeln(" yield");
|
||||||
|
|||||||
311
cleonos/c/apps/sysstat_main.c
Normal file
311
cleonos/c/apps/sysstat_main.c
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
#include "cmd_runtime.h"
|
||||||
|
|
||||||
|
#define USH_SYSSTAT_MAX_IDS (CLEONOS_SYSCALL_STATS_RECENT_ID + 1ULL)
|
||||||
|
#define USH_SYSSTAT_DEFAULT_TOP 12ULL
|
||||||
|
|
||||||
|
typedef struct ush_sysstat_entry {
|
||||||
|
u64 id;
|
||||||
|
u64 recent;
|
||||||
|
u64 total;
|
||||||
|
const char *name;
|
||||||
|
} ush_sysstat_entry;
|
||||||
|
|
||||||
|
static const char *ush_sysstat_name_for_id(u64 id) {
|
||||||
|
switch (id) {
|
||||||
|
case CLEONOS_SYSCALL_LOG_WRITE: return "LOG_WRITE";
|
||||||
|
case CLEONOS_SYSCALL_TIMER_TICKS: return "TIMER_TICKS";
|
||||||
|
case CLEONOS_SYSCALL_TASK_COUNT: return "TASK_COUNT";
|
||||||
|
case CLEONOS_SYSCALL_CUR_TASK: return "CUR_TASK";
|
||||||
|
case CLEONOS_SYSCALL_SERVICE_COUNT: return "SERVICE_COUNT";
|
||||||
|
case CLEONOS_SYSCALL_SERVICE_READY_COUNT: return "SERVICE_READY";
|
||||||
|
case CLEONOS_SYSCALL_CONTEXT_SWITCHES: return "CONTEXT_SWITCH";
|
||||||
|
case CLEONOS_SYSCALL_KELF_COUNT: return "KELF_COUNT";
|
||||||
|
case CLEONOS_SYSCALL_KELF_RUNS: return "KELF_RUNS";
|
||||||
|
case CLEONOS_SYSCALL_FS_NODE_COUNT: return "FS_NODE_COUNT";
|
||||||
|
case CLEONOS_SYSCALL_FS_CHILD_COUNT: return "FS_CHILD_COUNT";
|
||||||
|
case CLEONOS_SYSCALL_FS_GET_CHILD_NAME: return "FS_CHILD_NAME";
|
||||||
|
case CLEONOS_SYSCALL_FS_READ: return "FS_READ";
|
||||||
|
case CLEONOS_SYSCALL_EXEC_PATH: return "EXEC_PATH";
|
||||||
|
case CLEONOS_SYSCALL_EXEC_REQUESTS: return "EXEC_REQUESTS";
|
||||||
|
case CLEONOS_SYSCALL_EXEC_SUCCESS: return "EXEC_SUCCESS";
|
||||||
|
case CLEONOS_SYSCALL_USER_SHELL_READY: return "USER_SHELL_READY";
|
||||||
|
case CLEONOS_SYSCALL_USER_EXEC_REQUESTED: return "USER_EXEC_REQ";
|
||||||
|
case CLEONOS_SYSCALL_USER_LAUNCH_TRIES: return "USER_LAUNCH_TRY";
|
||||||
|
case CLEONOS_SYSCALL_USER_LAUNCH_OK: return "USER_LAUNCH_OK";
|
||||||
|
case CLEONOS_SYSCALL_USER_LAUNCH_FAIL: return "USER_LAUNCH_FAIL";
|
||||||
|
case CLEONOS_SYSCALL_TTY_COUNT: return "TTY_COUNT";
|
||||||
|
case CLEONOS_SYSCALL_TTY_ACTIVE: return "TTY_ACTIVE";
|
||||||
|
case CLEONOS_SYSCALL_TTY_SWITCH: return "TTY_SWITCH";
|
||||||
|
case CLEONOS_SYSCALL_TTY_WRITE: return "TTY_WRITE";
|
||||||
|
case CLEONOS_SYSCALL_TTY_WRITE_CHAR: return "TTY_WRITE_CHAR";
|
||||||
|
case CLEONOS_SYSCALL_KBD_GET_CHAR: return "KBD_GET_CHAR";
|
||||||
|
case CLEONOS_SYSCALL_FS_STAT_TYPE: return "FS_STAT_TYPE";
|
||||||
|
case CLEONOS_SYSCALL_FS_STAT_SIZE: return "FS_STAT_SIZE";
|
||||||
|
case CLEONOS_SYSCALL_FS_MKDIR: return "FS_MKDIR";
|
||||||
|
case CLEONOS_SYSCALL_FS_WRITE: return "FS_WRITE";
|
||||||
|
case CLEONOS_SYSCALL_FS_APPEND: return "FS_APPEND";
|
||||||
|
case CLEONOS_SYSCALL_FS_REMOVE: return "FS_REMOVE";
|
||||||
|
case CLEONOS_SYSCALL_LOG_JOURNAL_COUNT: return "LOG_JCOUNT";
|
||||||
|
case CLEONOS_SYSCALL_LOG_JOURNAL_READ: return "LOG_JREAD";
|
||||||
|
case CLEONOS_SYSCALL_KBD_BUFFERED: return "KBD_BUFFERED";
|
||||||
|
case CLEONOS_SYSCALL_KBD_PUSHED: return "KBD_PUSHED";
|
||||||
|
case CLEONOS_SYSCALL_KBD_POPPED: return "KBD_POPPED";
|
||||||
|
case CLEONOS_SYSCALL_KBD_DROPPED: return "KBD_DROPPED";
|
||||||
|
case CLEONOS_SYSCALL_KBD_HOTKEY_SWITCHES: return "KBD_HOTKEYS";
|
||||||
|
case CLEONOS_SYSCALL_GETPID: return "GETPID";
|
||||||
|
case CLEONOS_SYSCALL_SPAWN_PATH: return "SPAWN_PATH";
|
||||||
|
case CLEONOS_SYSCALL_WAITPID: return "WAITPID";
|
||||||
|
case CLEONOS_SYSCALL_EXIT: return "EXIT";
|
||||||
|
case CLEONOS_SYSCALL_SLEEP_TICKS: return "SLEEP_TICKS";
|
||||||
|
case CLEONOS_SYSCALL_YIELD: return "YIELD";
|
||||||
|
case CLEONOS_SYSCALL_SHUTDOWN: return "SHUTDOWN";
|
||||||
|
case CLEONOS_SYSCALL_RESTART: return "RESTART";
|
||||||
|
case CLEONOS_SYSCALL_AUDIO_AVAILABLE: return "AUDIO_AVAIL";
|
||||||
|
case CLEONOS_SYSCALL_AUDIO_PLAY_TONE: return "AUDIO_TONE";
|
||||||
|
case CLEONOS_SYSCALL_AUDIO_STOP: return "AUDIO_STOP";
|
||||||
|
case CLEONOS_SYSCALL_EXEC_PATHV: return "EXEC_PATHV";
|
||||||
|
case CLEONOS_SYSCALL_SPAWN_PATHV: return "SPAWN_PATHV";
|
||||||
|
case CLEONOS_SYSCALL_PROC_ARGC: return "PROC_ARGC";
|
||||||
|
case CLEONOS_SYSCALL_PROC_ARGV: return "PROC_ARGV";
|
||||||
|
case CLEONOS_SYSCALL_PROC_ENVC: return "PROC_ENVC";
|
||||||
|
case CLEONOS_SYSCALL_PROC_ENV: return "PROC_ENV";
|
||||||
|
case CLEONOS_SYSCALL_PROC_LAST_SIGNAL: return "PROC_LAST_SIG";
|
||||||
|
case CLEONOS_SYSCALL_PROC_FAULT_VECTOR: return "PROC_FAULT_VEC";
|
||||||
|
case CLEONOS_SYSCALL_PROC_FAULT_ERROR: return "PROC_FAULT_ERR";
|
||||||
|
case CLEONOS_SYSCALL_PROC_FAULT_RIP: return "PROC_FAULT_RIP";
|
||||||
|
case CLEONOS_SYSCALL_PROC_COUNT: return "PROC_COUNT";
|
||||||
|
case CLEONOS_SYSCALL_PROC_PID_AT: return "PROC_PID_AT";
|
||||||
|
case CLEONOS_SYSCALL_PROC_SNAPSHOT: return "PROC_SNAPSHOT";
|
||||||
|
case CLEONOS_SYSCALL_PROC_KILL: return "PROC_KILL";
|
||||||
|
case CLEONOS_SYSCALL_KDBG_SYM: return "KDBG_SYM";
|
||||||
|
case CLEONOS_SYSCALL_KDBG_BT: return "KDBG_BT";
|
||||||
|
case CLEONOS_SYSCALL_KDBG_REGS: return "KDBG_REGS";
|
||||||
|
case CLEONOS_SYSCALL_STATS_TOTAL: return "STATS_TOTAL";
|
||||||
|
case CLEONOS_SYSCALL_STATS_ID_COUNT: return "STATS_ID_COUNT";
|
||||||
|
case CLEONOS_SYSCALL_STATS_RECENT_WINDOW: return "STATS_RECENT_WIN";
|
||||||
|
case CLEONOS_SYSCALL_STATS_RECENT_ID: return "STATS_RECENT_ID";
|
||||||
|
default: return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_sysstat_next_token(const char **io_cursor, char *out, u64 out_size) {
|
||||||
|
const char *p;
|
||||||
|
u64 n = 0ULL;
|
||||||
|
|
||||||
|
if (io_cursor == (const char **)0 || out == (char *)0 || out_size == 0ULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[0] = '\0';
|
||||||
|
p = *io_cursor;
|
||||||
|
|
||||||
|
if (p == (const char *)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*p != '\0' && ush_is_space(*p) != 0) {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == '\0') {
|
||||||
|
*io_cursor = p;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*p != '\0' && ush_is_space(*p) == 0) {
|
||||||
|
if (n + 1ULL < out_size) {
|
||||||
|
out[n++] = *p;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[n] = '\0';
|
||||||
|
*io_cursor = p;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_sysstat_parse_args(const char *arg, int *out_show_all, u64 *out_limit) {
|
||||||
|
const char *cursor = arg;
|
||||||
|
char token[USH_PATH_MAX];
|
||||||
|
int show_all = 0;
|
||||||
|
u64 limit = USH_SYSSTAT_DEFAULT_TOP;
|
||||||
|
|
||||||
|
if (out_show_all == (int *)0 || out_limit == (u64 *)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ush_sysstat_next_token(&cursor, token, (u64)sizeof(token)) != 0) {
|
||||||
|
if (ush_streq(token, "-a") != 0 || ush_streq(token, "--all") != 0) {
|
||||||
|
show_all = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_streq(token, "-n") != 0 || ush_streq(token, "--top") != 0) {
|
||||||
|
if (ush_sysstat_next_token(&cursor, token, (u64)sizeof(token)) == 0 || ush_parse_u64_dec(token, &limit) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit == 0ULL) {
|
||||||
|
limit = 1ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_show_all = show_all;
|
||||||
|
*out_limit = limit;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_sysstat_sort_recent(ush_sysstat_entry *entries, u64 count) {
|
||||||
|
u64 i;
|
||||||
|
|
||||||
|
if (entries == (ush_sysstat_entry *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0ULL; i + 1ULL < count; i++) {
|
||||||
|
u64 j;
|
||||||
|
|
||||||
|
for (j = i + 1ULL; j < count; j++) {
|
||||||
|
int swap = 0;
|
||||||
|
|
||||||
|
if (entries[j].recent > entries[i].recent) {
|
||||||
|
swap = 1;
|
||||||
|
} else if (entries[j].recent == entries[i].recent && entries[j].total > entries[i].total) {
|
||||||
|
swap = 1;
|
||||||
|
} else if (entries[j].recent == entries[i].recent && entries[j].total == entries[i].total &&
|
||||||
|
entries[j].id < entries[i].id) {
|
||||||
|
swap = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (swap != 0) {
|
||||||
|
ush_sysstat_entry tmp = entries[i];
|
||||||
|
entries[i] = entries[j];
|
||||||
|
entries[j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_cmd_sysstat(const char *arg) {
|
||||||
|
int show_all = 0;
|
||||||
|
u64 limit = USH_SYSSTAT_DEFAULT_TOP;
|
||||||
|
ush_sysstat_entry entries[USH_SYSSTAT_MAX_IDS];
|
||||||
|
u64 entry_count = 0ULL;
|
||||||
|
u64 id;
|
||||||
|
u64 total = cleonos_sys_stats_total();
|
||||||
|
u64 recent_window = cleonos_sys_stats_recent_window();
|
||||||
|
u64 to_show;
|
||||||
|
|
||||||
|
if (ush_sysstat_parse_args(arg, &show_all, &limit) == 0) {
|
||||||
|
ush_writeln("sysstat: usage sysstat [-a|--all] [-n N]");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ush_writeln("sysstat:");
|
||||||
|
ush_print_kv_hex(" TIMER_TICKS", cleonos_sys_timer_ticks());
|
||||||
|
ush_print_kv_hex(" TASK_COUNT", cleonos_sys_task_count());
|
||||||
|
ush_print_kv_hex(" CURRENT_TASK", cleonos_syscall(CLEONOS_SYSCALL_CUR_TASK, 0ULL, 0ULL, 0ULL));
|
||||||
|
ush_print_kv_hex(" CONTEXT_SWITCHES", cleonos_sys_context_switches());
|
||||||
|
ush_print_kv_hex(" PROC_COUNT", cleonos_sys_proc_count());
|
||||||
|
ush_print_kv_hex(" EXEC_REQUESTS", cleonos_sys_exec_request_count());
|
||||||
|
ush_print_kv_hex(" EXEC_SUCCESS", cleonos_sys_exec_success_count());
|
||||||
|
ush_print_kv_hex(" SYSCALL_TOTAL", total);
|
||||||
|
ush_print_kv_hex(" SYSCALL_RECENT_WINDOW", recent_window);
|
||||||
|
ush_writeln("");
|
||||||
|
|
||||||
|
for (id = 0ULL; id < USH_SYSSTAT_MAX_IDS; id++) {
|
||||||
|
u64 id_total = cleonos_sys_stats_id_count(id);
|
||||||
|
u64 id_recent = cleonos_sys_stats_recent_id(id);
|
||||||
|
|
||||||
|
if (show_all == 0 && id_total == 0ULL && id_recent == 0ULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries[entry_count].id = id;
|
||||||
|
entries[entry_count].recent = id_recent;
|
||||||
|
entries[entry_count].total = id_total;
|
||||||
|
entries[entry_count].name = ush_sysstat_name_for_id(id);
|
||||||
|
entry_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_count == 0ULL) {
|
||||||
|
ush_writeln("(no syscall activity yet)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_all == 0) {
|
||||||
|
ush_sysstat_sort_recent(entries, entry_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
to_show = entry_count;
|
||||||
|
if (show_all == 0 && to_show > limit) {
|
||||||
|
to_show = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (id = 0ULL; id < to_show; id++) {
|
||||||
|
ush_write("ID=");
|
||||||
|
ush_write_hex_u64(entries[id].id);
|
||||||
|
ush_write(" RECENT=");
|
||||||
|
ush_write_hex_u64(entries[id].recent);
|
||||||
|
ush_write(" TOTAL=");
|
||||||
|
ush_write_hex_u64(entries[id].total);
|
||||||
|
ush_write(" NAME=");
|
||||||
|
ush_writeln(entries[id].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_all == 0 && entry_count > to_show) {
|
||||||
|
ush_write("... truncated, use ");
|
||||||
|
ush_write("sysstat -a");
|
||||||
|
ush_writeln(" to show all syscall IDs");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cleonos_app_main(void) {
|
||||||
|
ush_cmd_ctx ctx;
|
||||||
|
ush_cmd_ret ret;
|
||||||
|
ush_state sh;
|
||||||
|
char initial_cwd[USH_PATH_MAX];
|
||||||
|
int has_context = 0;
|
||||||
|
int success = 0;
|
||||||
|
const char *arg = "";
|
||||||
|
|
||||||
|
ush_zero(&ctx, (u64)sizeof(ctx));
|
||||||
|
ush_zero(&ret, (u64)sizeof(ret));
|
||||||
|
ush_init_state(&sh);
|
||||||
|
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
|
||||||
|
|
||||||
|
if (ush_command_ctx_read(&ctx) != 0) {
|
||||||
|
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "sysstat") != 0) {
|
||||||
|
has_context = 1;
|
||||||
|
arg = ctx.arg;
|
||||||
|
if (ctx.cwd[0] == '/') {
|
||||||
|
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
|
||||||
|
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
success = ush_cmd_sysstat(arg);
|
||||||
|
|
||||||
|
if (has_context != 0) {
|
||||||
|
if (ush_streq(sh.cwd, initial_cwd) == 0) {
|
||||||
|
ret.flags |= USH_CMD_RET_FLAG_CWD;
|
||||||
|
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sh.exit_requested != 0) {
|
||||||
|
ret.flags |= USH_CMD_RET_FLAG_EXIT;
|
||||||
|
ret.exit_code = sh.exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)ush_command_ret_write(&ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (success != 0) ? 0 : 1;
|
||||||
|
}
|
||||||
@@ -103,6 +103,10 @@ typedef struct cleonos_proc_snapshot {
|
|||||||
#define CLEONOS_SYSCALL_KDBG_SYM 65ULL
|
#define CLEONOS_SYSCALL_KDBG_SYM 65ULL
|
||||||
#define CLEONOS_SYSCALL_KDBG_BT 66ULL
|
#define CLEONOS_SYSCALL_KDBG_BT 66ULL
|
||||||
#define CLEONOS_SYSCALL_KDBG_REGS 67ULL
|
#define CLEONOS_SYSCALL_KDBG_REGS 67ULL
|
||||||
|
#define CLEONOS_SYSCALL_STATS_TOTAL 68ULL
|
||||||
|
#define CLEONOS_SYSCALL_STATS_ID_COUNT 69ULL
|
||||||
|
#define CLEONOS_SYSCALL_STATS_RECENT_WINDOW 70ULL
|
||||||
|
#define CLEONOS_SYSCALL_STATS_RECENT_ID 71ULL
|
||||||
|
|
||||||
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
||||||
u64 cleonos_sys_log_write(const char *message, u64 length);
|
u64 cleonos_sys_log_write(const char *message, u64 length);
|
||||||
@@ -172,5 +176,9 @@ u64 cleonos_sys_proc_kill(u64 pid, u64 signal);
|
|||||||
u64 cleonos_sys_kdbg_sym(u64 addr, char *out_line, u64 out_size);
|
u64 cleonos_sys_kdbg_sym(u64 addr, char *out_line, u64 out_size);
|
||||||
u64 cleonos_sys_kdbg_bt(u64 rbp, u64 rip, char *out_text, u64 out_size);
|
u64 cleonos_sys_kdbg_bt(u64 rbp, u64 rip, char *out_text, u64 out_size);
|
||||||
u64 cleonos_sys_kdbg_regs(char *out_text, u64 out_size);
|
u64 cleonos_sys_kdbg_regs(char *out_text, u64 out_size);
|
||||||
|
u64 cleonos_sys_stats_total(void);
|
||||||
|
u64 cleonos_sys_stats_id_count(u64 id);
|
||||||
|
u64 cleonos_sys_stats_recent_window(void);
|
||||||
|
u64 cleonos_sys_stats_recent_id(u64 id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -294,3 +294,19 @@ u64 cleonos_sys_kdbg_bt(u64 rbp, u64 rip, char *out_text, u64 out_size) {
|
|||||||
u64 cleonos_sys_kdbg_regs(char *out_text, u64 out_size) {
|
u64 cleonos_sys_kdbg_regs(char *out_text, u64 out_size) {
|
||||||
return cleonos_syscall(CLEONOS_SYSCALL_KDBG_REGS, (u64)out_text, out_size, 0ULL);
|
return cleonos_syscall(CLEONOS_SYSCALL_KDBG_REGS, (u64)out_text, out_size, 0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_stats_total(void) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_STATS_TOTAL, 0ULL, 0ULL, 0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_stats_id_count(u64 id) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_STATS_ID_COUNT, id, 0ULL, 0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_stats_recent_window(void) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_STATS_RECENT_WINDOW, 0ULL, 0ULL, 0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_stats_recent_id(u64 id) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_STATS_RECENT_ID, id, 0ULL, 0ULL);
|
||||||
|
}
|
||||||
|
|||||||
@@ -71,6 +71,10 @@
|
|||||||
#define CLKS_SYSCALL_KDBG_SYM 65ULL
|
#define CLKS_SYSCALL_KDBG_SYM 65ULL
|
||||||
#define CLKS_SYSCALL_KDBG_BT 66ULL
|
#define CLKS_SYSCALL_KDBG_BT 66ULL
|
||||||
#define CLKS_SYSCALL_KDBG_REGS 67ULL
|
#define CLKS_SYSCALL_KDBG_REGS 67ULL
|
||||||
|
#define CLKS_SYSCALL_STATS_TOTAL 68ULL
|
||||||
|
#define CLKS_SYSCALL_STATS_ID_COUNT 69ULL
|
||||||
|
#define CLKS_SYSCALL_STATS_RECENT_WINDOW 70ULL
|
||||||
|
#define CLKS_SYSCALL_STATS_RECENT_ID 71ULL
|
||||||
|
|
||||||
void clks_syscall_init(void);
|
void clks_syscall_init(void);
|
||||||
u64 clks_syscall_dispatch(void *frame_ptr);
|
u64 clks_syscall_dispatch(void *frame_ptr);
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
#define CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES (128ULL * 1024ULL)
|
#define CLKS_SYSCALL_KDBG_STACK_WINDOW_BYTES (128ULL * 1024ULL)
|
||||||
#define CLKS_SYSCALL_KERNEL_SYMBOL_FILE "/system/kernel.sym"
|
#define CLKS_SYSCALL_KERNEL_SYMBOL_FILE "/system/kernel.sym"
|
||||||
#define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL
|
#define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL
|
||||||
|
#define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_STATS_RECENT_ID
|
||||||
|
#define CLKS_SYSCALL_STATS_RING_SIZE 256U
|
||||||
|
|
||||||
struct clks_syscall_frame {
|
struct clks_syscall_frame {
|
||||||
u64 rax;
|
u64 rax;
|
||||||
@@ -73,6 +75,12 @@ static clks_bool clks_syscall_last_frame_valid = CLKS_FALSE;
|
|||||||
static clks_bool clks_syscall_symbols_checked = CLKS_FALSE;
|
static clks_bool clks_syscall_symbols_checked = CLKS_FALSE;
|
||||||
static const char *clks_syscall_symbols_data = CLKS_NULL;
|
static const char *clks_syscall_symbols_data = CLKS_NULL;
|
||||||
static u64 clks_syscall_symbols_size = 0ULL;
|
static u64 clks_syscall_symbols_size = 0ULL;
|
||||||
|
static u64 clks_syscall_stats_total = 0ULL;
|
||||||
|
static u64 clks_syscall_stats_id_count[CLKS_SYSCALL_STATS_MAX_ID + 1ULL];
|
||||||
|
static u64 clks_syscall_stats_recent_id_count[CLKS_SYSCALL_STATS_MAX_ID + 1ULL];
|
||||||
|
static u16 clks_syscall_stats_recent_ring[CLKS_SYSCALL_STATS_RING_SIZE];
|
||||||
|
static u32 clks_syscall_stats_recent_head = 0U;
|
||||||
|
static u32 clks_syscall_stats_recent_size = 0U;
|
||||||
|
|
||||||
#if defined(CLKS_ARCH_X86_64)
|
#if defined(CLKS_ARCH_X86_64)
|
||||||
static inline void clks_syscall_outb(u16 port, u8 value) {
|
static inline void clks_syscall_outb(u16 port, u8 value) {
|
||||||
@@ -1492,6 +1500,75 @@ static void clks_syscall_serial_write_hex64(u64 value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clks_syscall_stats_reset(void) {
|
||||||
|
clks_syscall_stats_total = 0ULL;
|
||||||
|
clks_memset(clks_syscall_stats_id_count, 0, sizeof(clks_syscall_stats_id_count));
|
||||||
|
clks_memset(clks_syscall_stats_recent_id_count, 0, sizeof(clks_syscall_stats_recent_id_count));
|
||||||
|
clks_memset(clks_syscall_stats_recent_ring, 0, sizeof(clks_syscall_stats_recent_ring));
|
||||||
|
clks_syscall_stats_recent_head = 0U;
|
||||||
|
clks_syscall_stats_recent_size = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clks_syscall_stats_record(u64 id) {
|
||||||
|
u16 ring_id = 0xFFFFU;
|
||||||
|
|
||||||
|
clks_syscall_stats_total++;
|
||||||
|
|
||||||
|
if (id <= CLKS_SYSCALL_STATS_MAX_ID) {
|
||||||
|
clks_syscall_stats_id_count[id]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id <= 0xFFFFULL) {
|
||||||
|
ring_id = (u16)id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_syscall_stats_recent_size >= CLKS_SYSCALL_STATS_RING_SIZE) {
|
||||||
|
u64 old_id = (u64)clks_syscall_stats_recent_ring[clks_syscall_stats_recent_head];
|
||||||
|
|
||||||
|
if (old_id <= CLKS_SYSCALL_STATS_MAX_ID && clks_syscall_stats_recent_id_count[old_id] > 0ULL) {
|
||||||
|
clks_syscall_stats_recent_id_count[old_id]--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clks_syscall_stats_recent_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_syscall_stats_recent_ring[clks_syscall_stats_recent_head] = ring_id;
|
||||||
|
|
||||||
|
if (id <= CLKS_SYSCALL_STATS_MAX_ID) {
|
||||||
|
clks_syscall_stats_recent_id_count[id]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_syscall_stats_recent_head++;
|
||||||
|
|
||||||
|
if (clks_syscall_stats_recent_head >= CLKS_SYSCALL_STATS_RING_SIZE) {
|
||||||
|
clks_syscall_stats_recent_head = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 clks_syscall_stats_total_count(void) {
|
||||||
|
return clks_syscall_stats_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 clks_syscall_stats_id(u64 id) {
|
||||||
|
if (id > CLKS_SYSCALL_STATS_MAX_ID) {
|
||||||
|
return 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clks_syscall_stats_id_count[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 clks_syscall_stats_recent_window(void) {
|
||||||
|
return (u64)clks_syscall_stats_recent_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 clks_syscall_stats_recent_id(u64 id) {
|
||||||
|
if (id > CLKS_SYSCALL_STATS_MAX_ID) {
|
||||||
|
return 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clks_syscall_stats_recent_id_count[id];
|
||||||
|
}
|
||||||
|
|
||||||
static void clks_syscall_trace_user_program(u64 id) {
|
static void clks_syscall_trace_user_program(u64 id) {
|
||||||
clks_bool user_program_running =
|
clks_bool user_program_running =
|
||||||
(clks_exec_is_running() == CLKS_TRUE && clks_exec_current_path_is_user() == CLKS_TRUE)
|
(clks_exec_is_running() == CLKS_TRUE && clks_exec_current_path_is_user() == CLKS_TRUE)
|
||||||
@@ -1538,6 +1615,7 @@ void clks_syscall_init(void) {
|
|||||||
clks_syscall_symbols_checked = CLKS_FALSE;
|
clks_syscall_symbols_checked = CLKS_FALSE;
|
||||||
clks_syscall_symbols_data = CLKS_NULL;
|
clks_syscall_symbols_data = CLKS_NULL;
|
||||||
clks_syscall_symbols_size = 0ULL;
|
clks_syscall_symbols_size = 0ULL;
|
||||||
|
clks_syscall_stats_reset();
|
||||||
clks_log(CLKS_LOG_INFO, "SYSCALL", "INT80 FRAMEWORK ONLINE");
|
clks_log(CLKS_LOG_INFO, "SYSCALL", "INT80 FRAMEWORK ONLINE");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1553,6 +1631,7 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
|
|||||||
clks_syscall_last_frame_valid = CLKS_TRUE;
|
clks_syscall_last_frame_valid = CLKS_TRUE;
|
||||||
|
|
||||||
id = frame->rax;
|
id = frame->rax;
|
||||||
|
clks_syscall_stats_record(id);
|
||||||
clks_syscall_trace_user_program(id);
|
clks_syscall_trace_user_program(id);
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -1699,6 +1778,14 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
|
|||||||
return clks_syscall_kdbg_bt(frame->rbx);
|
return clks_syscall_kdbg_bt(frame->rbx);
|
||||||
case CLKS_SYSCALL_KDBG_REGS:
|
case CLKS_SYSCALL_KDBG_REGS:
|
||||||
return clks_syscall_kdbg_regs(frame->rbx, frame->rcx);
|
return clks_syscall_kdbg_regs(frame->rbx, frame->rcx);
|
||||||
|
case CLKS_SYSCALL_STATS_TOTAL:
|
||||||
|
return clks_syscall_stats_total_count();
|
||||||
|
case CLKS_SYSCALL_STATS_ID_COUNT:
|
||||||
|
return clks_syscall_stats_id(frame->rbx);
|
||||||
|
case CLKS_SYSCALL_STATS_RECENT_WINDOW:
|
||||||
|
return clks_syscall_stats_recent_window();
|
||||||
|
case CLKS_SYSCALL_STATS_RECENT_ID:
|
||||||
|
return clks_syscall_stats_recent_id(frame->rbx);
|
||||||
default:
|
default:
|
||||||
return (u64)-1;
|
return (u64)-1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `/proc/<pid>`:指定 PID 快照文本
|
- `/proc/<pid>`:指定 PID 快照文本
|
||||||
- `/proc` 为只读;写入类 syscall 不支持。
|
- `/proc` 为只读;写入类 syscall 不支持。
|
||||||
|
|
||||||
## 4. Syscall 列表(0~64)
|
## 4. Syscall 列表(0~71)
|
||||||
|
|
||||||
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
|
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
|
||||||
|
|
||||||
@@ -510,6 +510,53 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `SIGSTOP`:将 `PENDING` 进程置为 `STOPPED`;对已 `STOPPED` 目标返回成功。
|
- `SIGSTOP`:将 `PENDING` 进程置为 `STOPPED`;对已 `STOPPED` 目标返回成功。
|
||||||
- `SIGCONT`:将 `STOPPED` 进程恢复为 `PENDING`。
|
- `SIGCONT`:将 `STOPPED` 进程恢复为 `PENDING`。
|
||||||
|
|
||||||
|
### 65 `CLEONOS_SYSCALL_KDBG_SYM`
|
||||||
|
|
||||||
|
- 参数:
|
||||||
|
- `arg0`: `u64 addr`
|
||||||
|
- `arg1`: `char *out_line`
|
||||||
|
- `arg2`: `u64 out_size`
|
||||||
|
- 返回:写入字节数(含截断)
|
||||||
|
- 说明:将地址符号化为文本(含偏移与可选源码位置)。
|
||||||
|
|
||||||
|
### 66 `CLEONOS_SYSCALL_KDBG_BT`
|
||||||
|
|
||||||
|
- 参数:
|
||||||
|
- `arg0`: `struct { u64 rbp; u64 rip; u64 out_ptr; u64 out_size; } *req`
|
||||||
|
- 返回:写入字节数
|
||||||
|
- 说明:输出回溯文本;x86_64 下会尝试沿帧指针遍历。
|
||||||
|
|
||||||
|
### 67 `CLEONOS_SYSCALL_KDBG_REGS`
|
||||||
|
|
||||||
|
- 参数:
|
||||||
|
- `arg0`: `char *out_text`
|
||||||
|
- `arg1`: `u64 out_size`
|
||||||
|
- 返回:写入字节数
|
||||||
|
- 说明:输出最近一次 syscall 进入内核时的寄存器快照。
|
||||||
|
|
||||||
|
### 68 `CLEONOS_SYSCALL_STATS_TOTAL`
|
||||||
|
|
||||||
|
- 参数:无
|
||||||
|
- 返回:自启动以来的 syscall 总调用次数
|
||||||
|
|
||||||
|
### 69 `CLEONOS_SYSCALL_STATS_ID_COUNT`
|
||||||
|
|
||||||
|
- 参数:
|
||||||
|
- `arg0`: `u64 id`
|
||||||
|
- 返回:指定 syscall ID 的累计调用次数(ID 越界返回 `0`)
|
||||||
|
|
||||||
|
### 70 `CLEONOS_SYSCALL_STATS_RECENT_WINDOW`
|
||||||
|
|
||||||
|
- 参数:无
|
||||||
|
- 返回:最近窗口内样本数量
|
||||||
|
- 说明:当前内核实现窗口大小为 `256` 次 syscall。
|
||||||
|
|
||||||
|
### 71 `CLEONOS_SYSCALL_STATS_RECENT_ID`
|
||||||
|
|
||||||
|
- 参数:
|
||||||
|
- `arg0`: `u64 id`
|
||||||
|
- 返回:指定 syscall ID 在“最近窗口”中的出现次数(ID 越界返回 `0`)
|
||||||
|
|
||||||
## 5. 用户态封装函数
|
## 5. 用户态封装函数
|
||||||
|
|
||||||
用户态封装位于:
|
用户态封装位于:
|
||||||
@@ -532,6 +579,8 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `cleonos_sys_proc_argc()` / `cleonos_sys_proc_argv()` / `cleonos_sys_proc_envc()` / `cleonos_sys_proc_env()`
|
- `cleonos_sys_proc_argc()` / `cleonos_sys_proc_argv()` / `cleonos_sys_proc_envc()` / `cleonos_sys_proc_env()`
|
||||||
- `cleonos_sys_proc_last_signal()` / `cleonos_sys_proc_fault_vector()` / `cleonos_sys_proc_fault_error()` / `cleonos_sys_proc_fault_rip()`
|
- `cleonos_sys_proc_last_signal()` / `cleonos_sys_proc_fault_vector()` / `cleonos_sys_proc_fault_error()` / `cleonos_sys_proc_fault_rip()`
|
||||||
- `cleonos_sys_proc_count()` / `cleonos_sys_proc_pid_at()` / `cleonos_sys_proc_snapshot()` / `cleonos_sys_proc_kill()`
|
- `cleonos_sys_proc_count()` / `cleonos_sys_proc_pid_at()` / `cleonos_sys_proc_snapshot()` / `cleonos_sys_proc_kill()`
|
||||||
|
- `cleonos_sys_kdbg_sym()` / `cleonos_sys_kdbg_bt()` / `cleonos_sys_kdbg_regs()`
|
||||||
|
- `cleonos_sys_stats_total()` / `cleonos_sys_stats_id_count()` / `cleonos_sys_stats_recent_window()` / `cleonos_sys_stats_recent_id()`
|
||||||
|
|
||||||
## 6. 开发注意事项
|
## 6. 开发注意事项
|
||||||
|
|
||||||
@@ -542,6 +591,6 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
|
|
||||||
## 7. Wine 兼容说明
|
## 7. Wine 兼容说明
|
||||||
|
|
||||||
- `wine/cleonos_wine_lib/runner.py` 已适配 syscall `0..60`,包含 `EXEC_PATHV` / `SPAWN_PATHV` 与 `PROC_*` 系列。
|
- `wine/cleonos_wine_lib/runner.py` 目前以 syscall `0..67` 为主,新增 ID 需同步适配后才能完整观测统计类接口。
|
||||||
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
|
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
|
||||||
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0`,`AUDIO_PLAY_TONE=0`,`AUDIO_STOP=1`。
|
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0`,`AUDIO_PLAY_TONE=0`,`AUDIO_STOP=1`。
|
||||||
|
|||||||
Reference in New Issue
Block a user