diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index 8b5c2fd2..d090c77c 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -124,10 +124,14 @@ namespace Kernel bool is_userspace() const { return m_is_userspace; } - uint64_t cpu_time_ns() const; + uint64_t cpu_time_total_ns() const; + void cpu_time_ns(uint64_t& user_ns, uint64_t& system_ns) const; void set_cpu_time_start(); void set_cpu_time_stop(); + void set_is_in_syscall(bool is_in_syscall); + bool is_in_syscall() const { return m_is_in_syscall; } + void update_processor_index_address(); void set_fsbase(vaddr_t base) { m_fsbase = base; } @@ -200,8 +204,10 @@ namespace Kernel static_assert(_SIGMAX < 64); mutable SpinLock m_cpu_time_lock; - uint64_t m_cpu_time_ns { 0 }; + uint64_t m_cpu_time_user_ns { 0 }; + uint64_t m_cpu_time_system_ns { 0 }; uint64_t m_cpu_time_start_ns { UINT64_MAX }; + BAN::Atomic m_is_in_syscall { false }; BAN::Atomic m_spinlock_count { 0 }; BAN::Atomic m_mutex_count { 0 }; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index c721b72f..aadf34f6 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -696,19 +696,24 @@ namespace Kernel size_t Process::proc_cputime(off_t offset, BAN::ByteSpan buffer) const { - const uint64_t cpu_time_ns = [this] { - uint64_t cpu_time_ns { 0 }; + uint64_t user_ns { 0 }, system_ns { 0 }; + + { LockGuard _(m_process_lock); for (auto* thread : m_threads) - cpu_time_ns += thread->cpu_time_ns(); - return cpu_time_ns; - }(); + { + uint64_t u, s; + thread->cpu_time_ns(u, s); + user_ns += u; + system_ns += s; + } + } - auto data = MUST(BAN::String::formatted("{}", cpu_time_ns)); - if (static_cast(offset) >= data.size() + 1) + auto data = MUST(BAN::String::formatted("{} {} {}", user_ns + system_ns, user_ns, system_ns)); + if (static_cast(offset) >= data.size()) return 0; - const size_t to_copy = BAN::Math::min(data.size() - offset + 1, buffer.size()); + const size_t to_copy = BAN::Math::min(data.size() - offset, buffer.size()); memcpy(buffer.data(), data.data(), to_copy); return to_copy; } @@ -3054,7 +3059,7 @@ namespace Kernel LockGuard _(m_process_lock); uint64_t cpu_time_ns { 0 }; for (auto* thread : m_threads) - cpu_time_ns += thread->cpu_time_ns(); + cpu_time_ns += thread->cpu_time_total_ns(); tp = { .tv_sec = static_cast(cpu_time_ns / 1'000'000'000), .tv_nsec = static_cast(cpu_time_ns % 1'000'000'000), @@ -3063,7 +3068,7 @@ namespace Kernel } case CLOCK_THREAD_CPUTIME_ID: { - const auto cpu_time_ns = Thread::current().cpu_time_ns(); + const auto cpu_time_ns = Thread::current().cpu_time_total_ns(); tp = { .tv_sec = static_cast(cpu_time_ns / 1'000'000'000), .tv_nsec = static_cast(cpu_time_ns % 1'000'000'000), diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index cb0fcc76..71fb59d3 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -43,6 +43,8 @@ namespace Kernel extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5) { + Thread::current().set_is_in_syscall(true); + Processor::set_interrupt_state(InterruptState::Enabled); Process::current().wait_while_stopped(); @@ -101,6 +103,8 @@ namespace Kernel Processor::set_interrupt_state(InterruptState::Disabled); + Thread::current().set_is_in_syscall(false); + ASSERT(Kernel::Thread::current().state() == Kernel::Thread::State::Executing); if (ret.is_error()) diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index 9be966f8..c863b1bb 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -285,12 +285,22 @@ namespace Kernel } } - uint64_t Thread::cpu_time_ns() const + uint64_t Thread::cpu_time_total_ns() const { SpinLockGuard _(m_cpu_time_lock); - if (m_cpu_time_start_ns == UINT64_MAX) - return m_cpu_time_ns; - return m_cpu_time_ns + (SystemTimer::get().ns_since_boot() - m_cpu_time_start_ns); + uint64_t offset = 0; + if (m_cpu_time_start_ns != UINT64_MAX) + offset += SystemTimer::get().ns_since_boot() - m_cpu_time_start_ns; + return m_cpu_time_user_ns + m_cpu_time_system_ns + offset; + } + + void Thread::cpu_time_ns(uint64_t& user_ns, uint64_t& system_ns) const + { + SpinLockGuard _(m_cpu_time_lock); + user_ns = m_cpu_time_user_ns; + system_ns = m_cpu_time_system_ns; + if (m_cpu_time_start_ns != UINT64_MAX) + system_ns += SystemTimer::get().ns_since_boot() - m_cpu_time_start_ns; } void Thread::set_cpu_time_start() @@ -304,10 +314,21 @@ namespace Kernel { SpinLockGuard _(m_cpu_time_lock); ASSERT(m_cpu_time_start_ns != UINT64_MAX); - m_cpu_time_ns += SystemTimer::get().ns_since_boot() - m_cpu_time_start_ns; + uint64_t& value = m_is_in_syscall ? m_cpu_time_system_ns : m_cpu_time_user_ns; + value += SystemTimer::get().ns_since_boot() - m_cpu_time_start_ns; m_cpu_time_start_ns = UINT64_MAX; } + void Thread::set_is_in_syscall(bool is_in_syscall) + { + SpinLockGuard _(m_cpu_time_lock); + const uint64_t current_ns = SystemTimer::get().ns_since_boot(); + uint64_t& value = m_is_in_syscall ? m_cpu_time_system_ns : m_cpu_time_user_ns; + value += current_ns - m_cpu_time_start_ns; + m_is_in_syscall = is_in_syscall; + m_cpu_time_start_ns = current_ns; + } + void Thread::update_processor_index_address() { if (!is_userspace() || !has_process())