Kernel: Implement CLOCK_{PROCESS,THREAD}_CPUTIME_ID
This commit is contained in:
parent
4fa40de557
commit
83c0ef3514
|
@ -103,6 +103,10 @@ namespace Kernel
|
|||
|
||||
bool is_userspace() const { return m_is_userspace; }
|
||||
|
||||
uint64_t cpu_time_ns() const;
|
||||
void set_cpu_time_start();
|
||||
void set_cpu_time_stop();
|
||||
|
||||
void set_tls(vaddr_t tls) { m_tls = tls; }
|
||||
vaddr_t get_tls() const { return m_tls; }
|
||||
|
||||
|
@ -155,6 +159,10 @@ namespace Kernel
|
|||
SpinLock m_signal_lock;
|
||||
static_assert(_SIGMAX < 64);
|
||||
|
||||
mutable SpinLock m_cpu_time_lock;
|
||||
uint64_t m_cpu_time_ns { 0 };
|
||||
uint64_t m_cpu_time_start_ns { UINT64_MAX };
|
||||
|
||||
BAN::Atomic<uint32_t> m_spinlock_count { 0 };
|
||||
BAN::Atomic<uint32_t> m_mutex_count { 0 };
|
||||
|
||||
|
|
|
@ -2372,11 +2372,9 @@ namespace Kernel
|
|||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_clock_gettime(clockid_t clock_id, timespec* tp)
|
||||
{
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_pointer_access(tp, sizeof(timespec), true));
|
||||
}
|
||||
|
||||
switch (clock_id)
|
||||
{
|
||||
|
@ -2386,10 +2384,31 @@ namespace Kernel
|
|||
case CLOCK_REALTIME:
|
||||
*tp = SystemTimer::get().real_time();
|
||||
break;
|
||||
case CLOCK_PROCESS_CPUTIME_ID:
|
||||
{
|
||||
uint64_t cpu_time_ns { 0 };
|
||||
for (auto* thread : m_threads)
|
||||
cpu_time_ns += thread->cpu_time_ns();
|
||||
*tp = {
|
||||
.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),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
{
|
||||
const auto cpu_time_ns = Thread::current().cpu_time_ns();
|
||||
*tp = {
|
||||
.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),
|
||||
};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dwarnln("TODO: clock_gettime({})", clock_id);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -382,6 +382,9 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
if (!scheduler().is_idle())
|
||||
Thread::current().set_cpu_time_stop();
|
||||
|
||||
#if ARCH(x86_64)
|
||||
asm volatile(
|
||||
"movq %%rsp, %%rcx;"
|
||||
|
@ -412,6 +415,9 @@ namespace Kernel
|
|||
|
||||
processor_info.m_start_ns = SystemTimer::get().ns_since_boot();
|
||||
|
||||
if (!scheduler().is_idle())
|
||||
Thread::current().set_cpu_time_start();
|
||||
|
||||
Processor::set_interrupt_state(state);
|
||||
}
|
||||
|
||||
|
|
|
@ -275,7 +275,10 @@ namespace Kernel
|
|||
page_table.load();
|
||||
|
||||
if (thread->state() == Thread::State::NotStarted)
|
||||
{
|
||||
thread->m_state = Thread::State::Executing;
|
||||
thread->set_cpu_time_start();
|
||||
}
|
||||
|
||||
Processor::gdt().set_tss_stack(thread->kernel_stack_top());
|
||||
Processor::load_tls();
|
||||
|
|
|
@ -166,6 +166,29 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t Thread::cpu_time_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);
|
||||
}
|
||||
|
||||
void Thread::set_cpu_time_start()
|
||||
{
|
||||
SpinLockGuard _(m_cpu_time_lock);
|
||||
ASSERT(m_cpu_time_start_ns == UINT64_MAX);
|
||||
m_cpu_time_start_ns = SystemTimer::get().ns_since_boot();
|
||||
}
|
||||
|
||||
void Thread::set_cpu_time_stop()
|
||||
{
|
||||
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;
|
||||
m_cpu_time_start_ns = UINT64_MAX;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<Thread*> Thread::pthread_create(entry_t entry, void* arg)
|
||||
{
|
||||
auto* thread = TRY(create_userspace(m_process, m_process->page_table()));
|
||||
|
|
Loading…
Reference in New Issue