times: rudimentary support for process times

This commit is contained in:
K. Lange 2021-09-02 23:08:18 +09:00
parent 6eaeff3451
commit efec80cb38
15 changed files with 113 additions and 6 deletions

View File

@ -30,6 +30,7 @@
#include <ctype.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/wait.h>
#include <sys/utsname.h>
#include <sys/stat.h>
@ -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);
}

View File

@ -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 {

View File

@ -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);

View File

@ -0,0 +1,17 @@
#pragma once
#include <_cheader.h>
#include <sys/types.h>
_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

View File

@ -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;

View File

@ -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

View File

@ -70,3 +70,4 @@
#define SYS_SETGID 68
#define SYS_GETGROUPS 69
#define SYS_SETGROUPS 70
#define SYS_TIMES 71

View File

@ -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;

View File

@ -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) {

View File

@ -6,6 +6,7 @@
#include <kernel/process.h>
#include <kernel/signal.h>
#include <kernel/misc.h>
#include <kernel/time.h>
#include <sys/time.h>
#include <sys/utsname.h>
@ -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;

View File

@ -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);

View File

@ -4,6 +4,7 @@
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/time.h>
#include <sys/times.h>
#include <syscall_nums.h>
#include <kernel/printf.h>
#include <kernel/process.h>
@ -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,

View File

@ -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);

View File

@ -1,5 +1,8 @@
#include <time.h>
#include <sys/times.h>
clock_t clock(void) {
return -1;
struct tms timeValues;
times(&timeValues);
return timeValues.tms_utime;
}

11
libc/time/times.c Normal file
View File

@ -0,0 +1,11 @@
#include <sys/times.h>
#include <errno.h>
#include <syscall.h>
#include <syscall_nums.h>
DEFN_SYSCALL1(times, SYS_TIMES, struct tms *);
clock_t times(struct tms * buf) {
__sets_errno(syscall_times(buf));
}