summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-12-03 01:12:26 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-12-03 01:14:19 +0100
commite7cc08226f5af4711f8e8438d7132c35b10666ed (patch)
treedef609f70bb376b9ab989c3b60792abbf2989147
parent4bc87dc7b99c4f7a9270e23e5958b4c93fe76033 (diff)
downloadserenity-e7cc08226f5af4711f8e8438d7132c35b10666ed.zip
Implement basic support for times().
The kernel now bills processes for time spent in kernelspace and userspace separately. The accounting is forwarded to the parent process in reap(). This makes the "time" builtin in bash work.
-rw-r--r--AK/Types.h2
-rw-r--r--Kernel/Process.cpp19
-rw-r--r--Kernel/Process.h7
-rw-r--r--Kernel/Scheduler.cpp6
-rw-r--r--Kernel/Syscall.cpp2
-rw-r--r--Kernel/Syscall.h1
-rw-r--r--LibC/stdio.cpp1
-rw-r--r--LibC/stdlib.cpp2
-rw-r--r--LibC/times.cpp9
-rw-r--r--VirtualFileSystem/UnixTypes.h8
10 files changed, 50 insertions, 7 deletions
diff --git a/AK/Types.h b/AK/Types.h
index 2854fabaa3..bfba6136b8 100644
--- a/AK/Types.h
+++ b/AK/Types.h
@@ -12,7 +12,7 @@ typedef signed int signed_dword;
typedef signed long long int signed_qword;
typedef decltype(sizeof(void*)) size_t;
-typedef long ssize_t;
+typedef signed_dword ssize_t;
static_assert(sizeof(size_t) == sizeof(dword));
static_assert(sizeof(ssize_t) == sizeof(signed_dword));
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index c47aaf5def..3a1db69a26 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -1415,6 +1415,14 @@ int Process::reap(Process& process)
{
InterruptDisabler disabler;
int exit_status = (process.m_termination_status << 8) | process.m_termination_signal;
+
+ if (process.ppid()) {
+ auto* parent = Process::from_pid(process.ppid());
+ ASSERT(parent);
+ parent->m_ticks_in_user_for_dead_children += process.m_ticks_in_user + process.m_ticks_in_user_for_dead_children;
+ parent->m_ticks_in_kernel_for_dead_children += process.m_ticks_in_kernel + process.m_ticks_in_kernel_for_dead_children;
+ }
+
dbgprintf("reap: %s(%u) {%s}\n", process.name().characters(), process.pid(), toString(process.state()));
ASSERT(process.state() == Dead);
g_processes->remove(&process);
@@ -1763,3 +1771,14 @@ int Process::sys$mkdir(const char* pathname, mode_t mode)
return error;
return 0;
}
+
+Unix::clock_t Process::sys$times(Unix::tms* times)
+{
+ if (!validate_write_typed(times))
+ return -EFAULT;
+ times->tms_utime = m_ticks_in_user;
+ times->tms_stime = m_ticks_in_kernel;
+ times->tms_cutime = m_ticks_in_user_for_dead_children;
+ times->tms_cstime = m_ticks_in_kernel_for_dead_children;
+ return 0;
+}
diff --git a/Kernel/Process.h b/Kernel/Process.h
index 56c829d7dd..5b56e32039 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -172,6 +172,7 @@ public:
int sys$fcntl(int fd, int cmd, dword extra_arg);
int sys$ioctl(int fd, unsigned request, unsigned arg);
int sys$mkdir(const char* pathname, mode_t mode);
+ Unix::clock_t sys$times(Unix::tms*);
static void initialize();
@@ -187,6 +188,12 @@ public:
void did_schedule() { ++m_timesScheduled; }
dword timesScheduled() const { return m_timesScheduled; }
+ dword m_ticks_in_user { 0 };
+ dword m_ticks_in_kernel { 0 };
+
+ dword m_ticks_in_user_for_dead_children { 0 };
+ dword m_ticks_in_kernel_for_dead_children { 0 };
+
pid_t waitee_pid() const { return m_waitee_pid; }
dword framePtr() const { return m_tss.ebp; }
diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp
index 56fe2ddf7f..88156eb9bb 100644
--- a/Kernel/Scheduler.cpp
+++ b/Kernel/Scheduler.cpp
@@ -181,6 +181,12 @@ bool Scheduler::context_switch(Process& process)
process.set_ticks_left(time_slice);
process.did_schedule();
+ if (process.tss().cs & 3) {
+ ++process.m_ticks_in_user;
+ } else {
+ ++process.m_ticks_in_kernel;
+ }
+
if (current == &process)
return false;
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index 6a4711191f..d5864406c8 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -175,6 +175,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
return current->sys$fstat((int)arg1, (Unix::stat*)arg2);
case Syscall::SC_mkdir:
return current->sys$mkdir((const char*)arg1, (mode_t)arg2);
+ case Syscall::SC_times:
+ return current->sys$times((Unix::tms*)arg1);
default:
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
break;
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index 18fdf5d9d7..81717dbda6 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -63,6 +63,7 @@
__ENUMERATE_SYSCALL(fcntl) \
__ENUMERATE_SYSCALL(ioctl) \
__ENUMERATE_SYSCALL(mkdir) \
+ __ENUMERATE_SYSCALL(times) \
#define DO_SYSCALL_A0(function) Syscall::invoke((dword)(function))
diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp
index ed49a3ee1f..23223ca035 100644
--- a/LibC/stdio.cpp
+++ b/LibC/stdio.cpp
@@ -8,7 +8,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
-#include <Kernel/Syscall.h>
#include <AK/printf.cpp>
extern "C" {
diff --git a/LibC/stdlib.cpp b/LibC/stdlib.cpp
index fb5c737b05..1cb16f5a2f 100644
--- a/LibC/stdlib.cpp
+++ b/LibC/stdlib.cpp
@@ -5,8 +5,8 @@
#include <string.h>
#include <alloca.h>
#include <assert.h>
-#include <Kernel/Syscall.h>
#include <AK/Assertions.h>
+#include <AK/Types.h>
extern "C" {
diff --git a/LibC/times.cpp b/LibC/times.cpp
index a517e4385e..0fe57c1a9e 100644
--- a/LibC/times.cpp
+++ b/LibC/times.cpp
@@ -1,8 +1,9 @@
#include <sys/times.h>
-#include <assert.h>
+#include <errno.h>
+#include <Kernel/Syscall.h>
-clock_t times(struct tms*)
+clock_t times(struct tms* buf)
{
- assert(false);
- return 0;
+ int rc = Syscall::invoke(Syscall::SC_times, (dword)buf);
+ __RETURN_WITH_ERRNO(rc, rc, (clock_t)-1);
}
diff --git a/VirtualFileSystem/UnixTypes.h b/VirtualFileSystem/UnixTypes.h
index d1e0e36efb..f90e860847 100644
--- a/VirtualFileSystem/UnixTypes.h
+++ b/VirtualFileSystem/UnixTypes.h
@@ -219,6 +219,14 @@ typedef dword mode_t;
typedef dword nlink_t;
typedef dword uid_t;
typedef dword gid_t;
+typedef dword clock_t;
+
+struct tms {
+ clock_t tms_utime;
+ clock_t tms_stime;
+ clock_t tms_cutime;
+ clock_t tms_cstime;
+};
#ifdef SERENITY
typedef void (*__sighandler_t)(int);