forked from Bananymous/banan-os
Kernel: Keep track of thread user and system time separately
This commit is contained in:
@@ -124,10 +124,14 @@ namespace Kernel
|
|||||||
|
|
||||||
bool is_userspace() const { return m_is_userspace; }
|
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_start();
|
||||||
void set_cpu_time_stop();
|
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 update_processor_index_address();
|
||||||
|
|
||||||
void set_fsbase(vaddr_t base) { m_fsbase = base; }
|
void set_fsbase(vaddr_t base) { m_fsbase = base; }
|
||||||
@@ -200,8 +204,10 @@ namespace Kernel
|
|||||||
static_assert(_SIGMAX < 64);
|
static_assert(_SIGMAX < 64);
|
||||||
|
|
||||||
mutable SpinLock m_cpu_time_lock;
|
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 };
|
uint64_t m_cpu_time_start_ns { UINT64_MAX };
|
||||||
|
BAN::Atomic<bool> m_is_in_syscall { false };
|
||||||
|
|
||||||
BAN::Atomic<uint32_t> m_spinlock_count { 0 };
|
BAN::Atomic<uint32_t> m_spinlock_count { 0 };
|
||||||
BAN::Atomic<uint32_t> m_mutex_count { 0 };
|
BAN::Atomic<uint32_t> m_mutex_count { 0 };
|
||||||
|
|||||||
+15
-10
@@ -696,19 +696,24 @@ namespace Kernel
|
|||||||
|
|
||||||
size_t Process::proc_cputime(off_t offset, BAN::ByteSpan buffer) const
|
size_t Process::proc_cputime(off_t offset, BAN::ByteSpan buffer) const
|
||||||
{
|
{
|
||||||
const uint64_t cpu_time_ns = [this] {
|
uint64_t user_ns { 0 }, system_ns { 0 };
|
||||||
uint64_t cpu_time_ns { 0 };
|
|
||||||
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
for (auto* thread : m_threads)
|
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));
|
auto data = MUST(BAN::String::formatted("{} {} {}", user_ns + system_ns, user_ns, system_ns));
|
||||||
if (static_cast<size_t>(offset) >= data.size() + 1)
|
if (static_cast<size_t>(offset) >= data.size())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const size_t to_copy = BAN::Math::min<size_t>(data.size() - offset + 1, buffer.size());
|
const size_t to_copy = BAN::Math::min<size_t>(data.size() - offset, buffer.size());
|
||||||
memcpy(buffer.data(), data.data(), to_copy);
|
memcpy(buffer.data(), data.data(), to_copy);
|
||||||
return to_copy;
|
return to_copy;
|
||||||
}
|
}
|
||||||
@@ -3054,7 +3059,7 @@ namespace Kernel
|
|||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
uint64_t cpu_time_ns { 0 };
|
uint64_t cpu_time_ns { 0 };
|
||||||
for (auto* thread : m_threads)
|
for (auto* thread : m_threads)
|
||||||
cpu_time_ns += thread->cpu_time_ns();
|
cpu_time_ns += thread->cpu_time_total_ns();
|
||||||
tp = {
|
tp = {
|
||||||
.tv_sec = static_cast<time_t>(cpu_time_ns / 1'000'000'000),
|
.tv_sec = static_cast<time_t>(cpu_time_ns / 1'000'000'000),
|
||||||
.tv_nsec = static_cast<long>(cpu_time_ns % 1'000'000'000),
|
.tv_nsec = static_cast<long>(cpu_time_ns % 1'000'000'000),
|
||||||
@@ -3063,7 +3068,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
case CLOCK_THREAD_CPUTIME_ID:
|
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 = {
|
tp = {
|
||||||
.tv_sec = static_cast<time_t>(cpu_time_ns / 1'000'000'000),
|
.tv_sec = static_cast<time_t>(cpu_time_ns / 1'000'000'000),
|
||||||
.tv_nsec = static_cast<long>(cpu_time_ns % 1'000'000'000),
|
.tv_nsec = static_cast<long>(cpu_time_ns % 1'000'000'000),
|
||||||
|
|||||||
@@ -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)
|
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);
|
Processor::set_interrupt_state(InterruptState::Enabled);
|
||||||
|
|
||||||
Process::current().wait_while_stopped();
|
Process::current().wait_while_stopped();
|
||||||
@@ -101,6 +103,8 @@ namespace Kernel
|
|||||||
|
|
||||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
|
||||||
|
Thread::current().set_is_in_syscall(false);
|
||||||
|
|
||||||
ASSERT(Kernel::Thread::current().state() == Kernel::Thread::State::Executing);
|
ASSERT(Kernel::Thread::current().state() == Kernel::Thread::State::Executing);
|
||||||
|
|
||||||
if (ret.is_error())
|
if (ret.is_error())
|
||||||
|
|||||||
@@ -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);
|
SpinLockGuard _(m_cpu_time_lock);
|
||||||
if (m_cpu_time_start_ns == UINT64_MAX)
|
uint64_t offset = 0;
|
||||||
return m_cpu_time_ns;
|
if (m_cpu_time_start_ns != UINT64_MAX)
|
||||||
return m_cpu_time_ns + (SystemTimer::get().ns_since_boot() - m_cpu_time_start_ns);
|
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()
|
void Thread::set_cpu_time_start()
|
||||||
@@ -304,10 +314,21 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
SpinLockGuard _(m_cpu_time_lock);
|
SpinLockGuard _(m_cpu_time_lock);
|
||||||
ASSERT(m_cpu_time_start_ns != UINT64_MAX);
|
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;
|
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()
|
void Thread::update_processor_index_address()
|
||||||
{
|
{
|
||||||
if (!is_userspace() || !has_process())
|
if (!is_userspace() || !has_process())
|
||||||
|
|||||||
Reference in New Issue
Block a user