Browse Source

Kernel: Add getrusage() syscall

Only the two timeval fields are maintained, as required by the POSIX
standard.
Lucas CHOLLET 3 years ago
parent
commit
839d3d9f74
5 changed files with 83 additions and 2 deletions
  1. 40 0
      Kernel/API/POSIX/sys/resource.h
  2. 1 0
      Kernel/API/Syscall.h
  3. 3 2
      Kernel/CMakeLists.txt
  4. 2 0
      Kernel/Process.h
  5. 37 0
      Kernel/Syscalls/resource.cpp

+ 40 - 0
Kernel/API/POSIX/sys/resource.h

@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022, Lucas Chollet <lucas.chollet@free.fr>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <Kernel/API/POSIX/sys/time.h>
+#include <Kernel/API/POSIX/sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct rusage {
+    struct timeval ru_utime;
+    struct timeval ru_stime;
+    long ru_maxrss;
+    long ru_ixrss;
+    long ru_idrss;
+    long ru_isrss;
+    long ru_minflt;
+    long ru_majflt;
+    long ru_nswap;
+    long ru_inblock;
+    long ru_oublock;
+    long ru_msgsnd;
+    long ru_msgrcv;
+    long ru_nsignals;
+    long ru_nvcsw;
+    long ru_nivcsw;
+};
+
+#define RUSAGE_SELF 1
+#define RUSAGE_CHILDREN 2
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 0
Kernel/API/Syscall.h

@@ -100,6 +100,7 @@ enum class NeedsBigProcessLock {
     S(getrandom, NeedsBigProcessLock::No)                   \
     S(getresgid, NeedsBigProcessLock::Yes)                  \
     S(getresuid, NeedsBigProcessLock::Yes)                  \
+    S(getrusage, NeedsBigProcessLock::Yes)                  \
     S(getsid, NeedsBigProcessLock::Yes)                     \
     S(getsockname, NeedsBigProcessLock::Yes)                \
     S(getsockopt, NeedsBigProcessLock::Yes)                 \

+ 3 - 2
Kernel/CMakeLists.txt

@@ -249,6 +249,7 @@ set(KERNEL_SOURCES
     Syscalls/readlink.cpp
     Syscalls/realpath.cpp
     Syscalls/rename.cpp
+    Syscalls/resource.cpp
     Syscalls/rmdir.cpp
     Syscalls/sched.cpp
     Syscalls/sendfd.cpp
@@ -383,7 +384,7 @@ else()
     set(SOURCES
         ${SOURCES}
         ${AK_SOURCES}
-        
+
         Arch/aarch64/dummy.cpp
         Arch/aarch64/SmapDisabler.cpp
         Arch/aarch64/ScopedCritical.cpp
@@ -426,7 +427,7 @@ else() # Assume Clang
 
     # We need this in order to pick up the #define __serenity__, otherwise we end up including unistd.h into the linker script
     set(TARGET_STRING "--target=${CMAKE_CXX_COMPILER_TARGET}")
-    
+
     add_link_options(LINKER:--build-id=none LINKER:--pack-dyn-relocs=relr)
 endif()
 

+ 2 - 0
Kernel/Process.h

@@ -16,6 +16,7 @@
 #include <AK/Variant.h>
 #include <AK/WeakPtr.h>
 #include <AK/Weakable.h>
+#include <Kernel/API/POSIX/sys/resource.h>
 #include <Kernel/API/Syscall.h>
 #include <Kernel/Assertions.h>
 #include <Kernel/AtomicEdgeAction.h>
@@ -286,6 +287,7 @@ public:
     ErrorOr<FlatPtr> sys$getppid();
     ErrorOr<FlatPtr> sys$getresuid(Userspace<UserID*>, Userspace<UserID*>, Userspace<UserID*>);
     ErrorOr<FlatPtr> sys$getresgid(Userspace<GroupID*>, Userspace<GroupID*>, Userspace<GroupID*>);
+    ErrorOr<FlatPtr> sys$getrusage(int, Userspace<rusage*>);
     ErrorOr<FlatPtr> sys$umask(mode_t);
     ErrorOr<FlatPtr> sys$open(Userspace<const Syscall::SC_open_params*>);
     ErrorOr<FlatPtr> sys$close(int fd);

+ 37 - 0
Kernel/Syscalls/resource.cpp

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022, Lucas Chollet <lucas.chollet@free.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <Kernel/Process.h>
+
+namespace Kernel {
+
+ErrorOr<FlatPtr> Process::sys$getrusage(int who, Userspace<rusage*> user_usage)
+{
+    VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
+
+    rusage usage {};
+
+    auto const ticks_per_second = TimeManagement::the().ticks_per_second();
+
+    switch (who) {
+    case RUSAGE_SELF:
+        usage.ru_utime = Time::from_ticks(m_ticks_in_user, ticks_per_second).to_timeval();
+        usage.ru_stime = Time::from_ticks(m_ticks_in_kernel, ticks_per_second).to_timeval();
+        break;
+    case RUSAGE_CHILDREN:
+        usage.ru_utime = Time::from_ticks(m_ticks_in_user_for_dead_children, ticks_per_second).to_timeval();
+        usage.ru_stime = Time::from_ticks(m_ticks_in_kernel_for_dead_children, ticks_per_second).to_timeval();
+        break;
+    default:
+        return EINVAL;
+    }
+
+    TRY(copy_to_user(user_usage, &usage));
+
+    return 0;
+}
+
+}