times: rudimentary support for process times
This commit is contained in:
parent
6eaeff3451
commit
efec80cb38
18
apps/sh.c
18
apps/sh.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
17
base/usr/include/sys/times.h
Normal file
17
base/usr/include/sys/times.h
Normal 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
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -70,3 +70,4 @@
|
||||
#define SYS_SETGID 68
|
||||
#define SYS_GETGROUPS 69
|
||||
#define SYS_SETGROUPS 70
|
||||
#define SYS_TIMES 71
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
11
libc/time/times.c
Normal 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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user