From efec80cb38ae9b532ef6892fb7436411f1110043 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Thu, 2 Sep 2021 23:08:18 +0900 Subject: [PATCH] times: rudimentary support for process times --- apps/sh.c | 18 ++++++++++++++++++ base/usr/include/kernel/process.h | 8 ++++++++ base/usr/include/kernel/time.h | 1 + base/usr/include/sys/times.h | 17 +++++++++++++++++ base/usr/include/sys/types.h | 1 + base/usr/include/syscall.h | 1 + base/usr/include/syscall_nums.h | 1 + base/usr/include/time.h | 4 +--- kernel/arch/x86_64/cmos.c | 6 +++++- kernel/arch/x86_64/idt.c | 5 +++++ kernel/sys/process.c | 22 ++++++++++++++++++++++ kernel/sys/syscall.c | 13 +++++++++++++ kernel/vfs/procfs.c | 6 +++++- libc/time/clock.c | 5 ++++- libc/time/times.c | 11 +++++++++++ 15 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 base/usr/include/sys/times.h create mode 100644 libc/time/times.c diff --git a/apps/sh.c b/apps/sh.c index b7407eaf..3b744125 100644 --- a/apps/sh.c +++ b/apps/sh.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -2260,6 +2261,9 @@ uint32_t shell_cmd_time(int argc, char * argv[]) { struct timeval start, end; gettimeofday(&start, NULL); + struct tms timeBefore; + times(&timeBefore); + if (argc > 1) { pid_t child_pid = fork(); if (!child_pid) { @@ -2291,6 +2295,20 @@ uint32_t shell_cmd_time(int argc, char * argv[]) { fprintf(shell_stderr, "\nreal\t%dm%d.%.03ds\n", minutes, (int)sec_diff, (int)(usec_diff / 1000)); + /* User and system times from children */ + struct tms timeBuf; + times(&timeBuf); + + fprintf(shell_stderr, "user\t%dm%d.%.03ds\n", + (int)(((timeBuf.tms_cutime - timeBefore.tms_cutime) / (60 * CLOCKS_PER_SEC))), + (int)(((timeBuf.tms_cutime - timeBefore.tms_cutime) / (CLOCKS_PER_SEC)) % 60), + (int)(((timeBuf.tms_cutime - timeBefore.tms_cutime) / (CLOCKS_PER_SEC / 1000)) % 1000)); + + fprintf(shell_stderr, "sys\t%dm%d.%.03ds\n", + (int)(((timeBuf.tms_cstime - timeBefore.tms_cstime) / (60 * CLOCKS_PER_SEC))), + (int)(((timeBuf.tms_cstime - timeBefore.tms_cstime) / (CLOCKS_PER_SEC)) % 60), + (int)(((timeBuf.tms_cstime - timeBefore.tms_cstime) / (CLOCKS_PER_SEC / 1000)) % 1000)); + return WEXITSTATUS(ret_code); } diff --git a/base/usr/include/kernel/process.h b/base/usr/include/kernel/process.h index 63a10823..623451cf 100644 --- a/base/usr/include/kernel/process.h +++ b/base/usr/include/kernel/process.h @@ -120,6 +120,14 @@ typedef struct process { int supplementary_group_count; gid_t * supplementary_group_list; + + /* Process times */ + uint64_t time_total; /* user time */ + uint64_t time_sys; /* system time */ + uint64_t time_in; /* tsc stamp of when this process last entered the running state */ + uint64_t time_switch; /* tsc stamp of when this process last started doing system things */ + uint64_t time_children; + uint64_t time_sys_children; } process_t; typedef struct { diff --git a/base/usr/include/kernel/time.h b/base/usr/include/kernel/time.h index e136da6c..a5645a25 100644 --- a/base/usr/include/kernel/time.h +++ b/base/usr/include/kernel/time.h @@ -4,3 +4,4 @@ extern void relative_time(unsigned long, unsigned long, unsigned long *, unsigned long *); extern uint64_t now(void); +extern uint64_t arch_perf_timer(void); diff --git a/base/usr/include/sys/times.h b/base/usr/include/sys/times.h new file mode 100644 index 00000000..d3c265ae --- /dev/null +++ b/base/usr/include/sys/times.h @@ -0,0 +1,17 @@ +#pragma once + +#include <_cheader.h> +#include + +_Begin_C_Header + +struct tms { + clock_t tms_utime; + clock_t tms_stime; + clock_t tms_cutime; + clock_t tms_cstime; +}; + +extern clock_t times(struct tms *buf); + +_End_C_Header diff --git a/base/usr/include/sys/types.h b/base/usr/include/sys/types.h index f33e7917..005c0b20 100644 --- a/base/usr/include/sys/types.h +++ b/base/usr/include/sys/types.h @@ -19,6 +19,7 @@ typedef unsigned long blkcnt_t; typedef long off_t; typedef long time_t; +typedef long clock_t; typedef long ssize_t; diff --git a/base/usr/include/syscall.h b/base/usr/include/syscall.h index f719ba5e..44c00b32 100644 --- a/base/usr/include/syscall.h +++ b/base/usr/include/syscall.h @@ -129,6 +129,7 @@ DECL_SYSCALL0(getegid); DECL_SYSCALL1(setgid, unsigned int); DECL_SYSCALL2(getgroups, int, int*); DECL_SYSCALL2(setgroups, int, const int*); +DECL_SYSCALL1(times, struct tms*); _End_C_Header diff --git a/base/usr/include/syscall_nums.h b/base/usr/include/syscall_nums.h index fbf3262a..23d6b903 100644 --- a/base/usr/include/syscall_nums.h +++ b/base/usr/include/syscall_nums.h @@ -70,3 +70,4 @@ #define SYS_SETGID 68 #define SYS_GETGROUPS 69 #define SYS_SETGROUPS 70 +#define SYS_TIMES 71 diff --git a/base/usr/include/time.h b/base/usr/include/time.h index 695c412d..c8f0b346 100644 --- a/base/usr/include/time.h +++ b/base/usr/include/time.h @@ -35,10 +35,8 @@ extern time_t mktime(struct tm *tm); extern char * asctime(const struct tm *tm); extern char * ctime(const time_t * timep); -typedef int clock_t; - extern clock_t clock(void); -#define CLOCKS_PER_SEC 1 +#define CLOCKS_PER_SEC 1000000 struct timespec { time_t tv_sec; diff --git a/kernel/arch/x86_64/cmos.c b/kernel/arch/x86_64/cmos.c index ee5e6d84..131bd7fb 100644 --- a/kernel/arch/x86_64/cmos.c +++ b/kernel/arch/x86_64/cmos.c @@ -132,7 +132,11 @@ unsigned long tsc_mhz = 3500; /* XXX */ static inline uint64_t read_tsc(void) { uint32_t lo, hi; asm volatile ( "rdtsc" : "=a"(lo), "=d"(hi) ); - return ((uint64_t)hi << 32) | (uint64_t)lo; + return ((uint64_t)hi << 32UL) | (uint64_t)lo; +} + +uint64_t arch_perf_timer(void) { + return read_tsc(); } size_t arch_cpu_mhz(void) { diff --git a/kernel/arch/x86_64/idt.c b/kernel/arch/x86_64/idt.c index c85c0427..e7478ffe 100644 --- a/kernel/arch/x86_64/idt.c +++ b/kernel/arch/x86_64/idt.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -174,6 +175,10 @@ static void map_more_stack(uintptr_t fromAddr) { struct regs * isr_handler(struct regs * r) { this_core->interrupt_registers = r; + if (r->cs != 0x08 && this_core->current_process) { + this_core->current_process->time_switch = arch_perf_timer(); + } + switch (r->int_no) { case 14: /* Page fault */ { uintptr_t faulting_address; diff --git a/kernel/sys/process.c b/kernel/sys/process.c index 63d8704a..2fe807b4 100644 --- a/kernel/sys/process.c +++ b/kernel/sys/process.c @@ -58,6 +58,21 @@ static spin_lock_t wait_lock_tmp = { 0 }; static spin_lock_t sleep_lock = { 0 }; static spin_lock_t reap_lock = { 0 }; +void update_process_times(int includeSystem) { + uint64_t pTime = arch_perf_timer(); + if (this_core->current_process->time_in && this_core->current_process->time_in < pTime) { + this_core->current_process->time_total += pTime - this_core->current_process->time_in; + } + this_core->current_process->time_in = 0; + + if (includeSystem) { + if (this_core->current_process->time_switch && this_core->current_process->time_switch < pTime) { + this_core->current_process->time_sys += pTime - this_core->current_process->time_switch; + } + this_core->current_process->time_switch = 0; + } +} + #define must_have_lock(lck) if (lck.owner != this_core->cpu_id+1) { printf("Failed lock check.\n"); arch_fatal(); } /** @@ -86,6 +101,7 @@ static spin_lock_t reap_lock = { 0 }; */ void switch_next(void) { this_core->previous_process = this_core->current_process; + update_process_times(1); /* Get the next available process, discarded anything in the queue * marked as finished. */ @@ -688,6 +704,8 @@ volatile process_t * next_ready_process(void) { __sync_or_and_fetch(&next->flags, PROC_FLAG_RUNNING); next->owner = this_core->cpu_id; + next->time_in = arch_perf_timer(); + next->time_switch = next->time_in; return next; } @@ -975,6 +993,8 @@ int waitpid(int pid, int * status, int options) { int pid = candidate->id; if (candidate->flags & PROC_FLAG_FINISHED) { while (*((volatile int *)&candidate->flags) & PROC_FLAG_RUNNING); + proc->time_children += candidate->time_children + candidate->time_total; + proc->time_sys_children += candidate->time_sys_children + candidate->time_sys; process_delete((process_t*)candidate); } return pid; @@ -1183,6 +1203,8 @@ void task_exit(int retval) { } } + update_process_times(1); + process_t * parent = process_get_parent((process_t *)this_core->current_process); __sync_or_and_fetch(&this_core->current_process->flags, PROC_FLAG_FINISHED); diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index ef51787e..05685c8d 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -980,6 +981,17 @@ static long sys_reboot(void) { return arch_reboot(); } +static long sys_times(struct tms *buf) { + PTR_VALIDATE(buf); + + buf->tms_utime = this_core->current_process->time_total / arch_cpu_mhz(); + buf->tms_stime = this_core->current_process->time_sys / arch_cpu_mhz(); + buf->tms_cutime = this_core->current_process->time_children / arch_cpu_mhz(); + buf->tms_cstime = this_core->current_process->time_sys_children / arch_cpu_mhz(); + + return arch_perf_timer() / arch_cpu_mhz(); +} + extern long net_socket(); extern long net_setsockopt(); extern long net_bind(); @@ -1052,6 +1064,7 @@ static long (*syscalls[])() = { [SYS_SETGID] = sys_setgid, [SYS_GETGROUPS] = sys_getgroups, [SYS_SETGROUPS] = sys_setgroups, + [SYS_TIMES] = sys_times, [SYS_SOCKET] = net_socket, [SYS_SETSOCKOPT] = net_setsockopt, diff --git a/kernel/vfs/procfs.c b/kernel/vfs/procfs.c index 49472feb..ec927038 100644 --- a/kernel/vfs/procfs.c +++ b/kernel/vfs/procfs.c @@ -151,6 +151,8 @@ static ssize_t proc_status_func(fs_node_t *node, off_t offset, size_t size, uint "RssShmem:\t %ld kB\n" "MemPermille:\t %ld\n" "LastCore:\t %d\n" + "TotalTime:\t %ld ms\n" + "SysTime:\t %ld ms\n" , name, state, @@ -170,7 +172,9 @@ static ssize_t proc_status_func(fs_node_t *node, off_t offset, size_t size, uint proc->syscall_registers ? arch_stack_pointer(proc->syscall_registers) : 0, proc->cmdline ? proc->cmdline[0] : "(none)", mem_usage, shm_usage, mem_permille, - proc->owner + proc->owner, + proc->time_total / arch_cpu_mhz(), + proc->time_sys / arch_cpu_mhz() ); size_t _bsize = strlen(buf); diff --git a/libc/time/clock.c b/libc/time/clock.c index e730efbc..d40393cf 100644 --- a/libc/time/clock.c +++ b/libc/time/clock.c @@ -1,5 +1,8 @@ #include +#include clock_t clock(void) { - return -1; + struct tms timeValues; + times(&timeValues); + return timeValues.tms_utime; } diff --git a/libc/time/times.c b/libc/time/times.c new file mode 100644 index 00000000..287fdac0 --- /dev/null +++ b/libc/time/times.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +DEFN_SYSCALL1(times, SYS_TIMES, struct tms *); + +clock_t times(struct tms * buf) { + __sets_errno(syscall_times(buf)); +} +