diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index e7f79232..3ad51d52 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -39,6 +39,7 @@ set(SOURCES src/sys/link.cpp src/sys/uname.cpp src/sys/mount.cpp + src/sys/resource.cpp src/fs/VFS.cpp src/fs/Pipe.cpp src/fs/Mount.cpp diff --git a/kernel/src/sys/pstat.cpp b/kernel/src/sys/pstat.cpp index 5e9fd584..09d46115 100644 --- a/kernel/src/sys/pstat.cpp +++ b/kernel/src/sys/pstat.cpp @@ -28,9 +28,9 @@ Result sys_pstat(Registers*, SyscallArgs args) proc.ps_egid = thread->auth.egid; proc.ps_state = (int)thread->state; proc.ps_flags = thread->is_kernel ? PS_FLAG_KRNL : 0; - set_timespec(proc.ps_time, thread->ticks); - set_timespec(proc.ps_ktime, thread->ticks_in_kernel); - set_timespec(proc.ps_utime, thread->ticks_in_user); + set_timespec(proc.ps_time, thread->user_ticks_self + thread->kernel_ticks_self); + set_timespec(proc.ps_ktime, thread->kernel_ticks_self); + set_timespec(proc.ps_utime, thread->kernel_ticks_children); strlcpy(proc.ps_name, thread->name.chars(), sizeof(proc.ps_name)); strlcpy(proc.ps_cwd, thread->current_directory_path.is_empty() ? "/" : thread->current_directory_path.chars(), sizeof(proc.ps_cwd)); diff --git a/kernel/src/sys/resource.cpp b/kernel/src/sys/resource.cpp new file mode 100644 index 00000000..d4a38937 --- /dev/null +++ b/kernel/src/sys/resource.cpp @@ -0,0 +1,32 @@ +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include "thread/Scheduler.h" +#include + +static void ticks_to_rusage(struct rusage* ru, u64 sticks, u64 uticks) +{ + ru->ru_stime.tv_sec = sticks / 1000; + ru->ru_stime.tv_usec = (sticks % 1000) * 1000; + ru->ru_utime.tv_sec = uticks / 1000; + ru->ru_utime.tv_usec = (uticks % 1000) * 1000; +} + +Result sys_getrusage(Registers*, SyscallArgs args) +{ + int who = (int)args[0]; + struct rusage* ru = (struct rusage*)args[1]; + + auto* current = Scheduler::current(); + + struct rusage kru; + switch (who) + { + case RUSAGE_SELF: ticks_to_rusage(&kru, current->kernel_ticks_self, current->user_ticks_self); break; + case RUSAGE_CHILDREN: ticks_to_rusage(&kru, current->kernel_ticks_children, current->user_ticks_children); break; + default: return err(EINVAL); + } + + if (!MemoryManager::copy_to_user_typed(ru, &kru)) return err(EFAULT); + + return 0; +} diff --git a/kernel/src/sys/waitpid.cpp b/kernel/src/sys/waitpid.cpp index 20a05e11..92220a0e 100644 --- a/kernel/src/sys/waitpid.cpp +++ b/kernel/src/sys/waitpid.cpp @@ -50,6 +50,9 @@ Result sys_waitpid(Registers*, SyscallArgs args) int status = (int)thread->status; u64 id = thread->id; + current->user_ticks_children += thread->user_ticks_self; + current->kernel_ticks_children += thread->kernel_ticks_self; + thread->state = ThreadState::Dying; Scheduler::signal_reap_thread(); diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 52645626..a40af402 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -261,11 +261,9 @@ namespace Scheduler { CPU::disable_interrupts(); - g_current->ticks++; - - if (is_in_kernel(regs)) g_current->ticks_in_kernel++; + if (is_in_kernel(regs)) g_current->kernel_ticks_self++; else - g_current->ticks_in_user++; + g_current->user_ticks_self++; g_current->ticks_left--; @@ -342,11 +340,11 @@ namespace Scheduler for (const auto* thread : g_threads) { - kdbgln("%p %c [%-20s] %4zu, parent = (%-18p,%zu), state = %d, ticks: (t:%04zu,k:%04zu,u:%04zu), status = " + kdbgln("%p %c [%-20s] %4zu, parent = (%-18p,%zu), state = %d, ticks: (k:%04zu,u:%04zu), status = " "%d, cwd = %s", thread, thread->is_kernel ? 'k' : 'u', thread->name.chars(), thread->id, thread->parent, - thread->parent ? thread->parent->id : 0, (int)thread->state, thread->ticks, thread->ticks_in_kernel, - thread->ticks_in_user, thread->status, + thread->parent ? thread->parent->id : 0, (int)thread->state, thread->kernel_ticks_self, + thread->user_ticks_self, thread->status, thread->current_directory_path.is_empty() ? "/" : thread->current_directory_path.chars()); } diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index e50fa45e..3bef0015 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -59,9 +59,10 @@ struct Thread : public LinkedListNode Credentials auth; - u64 ticks = 0; - u64 ticks_in_user = 0; - u64 ticks_in_kernel = 0; + u64 user_ticks_self = 0; + u64 kernel_ticks_self = 0; + u64 user_ticks_children = 0; + u64 kernel_ticks_children = 0; u64 ticks_left; u64 sleep_ticks_left; diff --git a/libc/include/bits/rusage.h b/libc/include/bits/rusage.h new file mode 100644 index 00000000..4e5eff5e --- /dev/null +++ b/libc/include/bits/rusage.h @@ -0,0 +1,17 @@ +/* bits/rusage.h: The rusage structure. */ + +#ifndef _BITS_RUSAGE_H +#define _BITS_RUSAGE_H + +#include + +struct rusage +{ + struct timeval ru_utime; + struct timeval ru_stime; +}; + +#define RUSAGE_SELF 0 +#define RUSAGE_CHILDREN 1 + +#endif diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index a219df64..28ad8710 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -5,7 +5,7 @@ _e(lseek) _e(mkdir) _e(execve) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) _e(geteuid) \ _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \ _e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \ - _e(umount) _e(pstat) + _e(umount) _e(pstat) _e(getrusage) enum Syscalls {