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; }
|
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; }
|
void set_tls(vaddr_t tls) { m_tls = tls; }
|
||||||
vaddr_t get_tls() const { return m_tls; }
|
vaddr_t get_tls() const { return m_tls; }
|
||||||
|
|
||||||
|
@ -155,6 +159,10 @@ namespace Kernel
|
||||||
SpinLock m_signal_lock;
|
SpinLock m_signal_lock;
|
||||||
static_assert(_SIGMAX < 64);
|
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_spinlock_count { 0 };
|
||||||
BAN::Atomic<uint32_t> m_mutex_count { 0 };
|
BAN::Atomic<uint32_t> m_mutex_count { 0 };
|
||||||
|
|
||||||
|
|
|
@ -2373,10 +2373,8 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_clock_gettime(clockid_t clock_id, timespec* tp)
|
BAN::ErrorOr<long> Process::sys_clock_gettime(clockid_t clock_id, timespec* tp)
|
||||||
{
|
{
|
||||||
{
|
LockGuard _(m_process_lock);
|
||||||
LockGuard _(m_process_lock);
|
TRY(validate_pointer_access(tp, sizeof(timespec), true));
|
||||||
TRY(validate_pointer_access(tp, sizeof(timespec), true));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (clock_id)
|
switch (clock_id)
|
||||||
{
|
{
|
||||||
|
@ -2386,10 +2384,31 @@ namespace Kernel
|
||||||
case CLOCK_REALTIME:
|
case CLOCK_REALTIME:
|
||||||
*tp = SystemTimer::get().real_time();
|
*tp = SystemTimer::get().real_time();
|
||||||
break;
|
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:
|
default:
|
||||||
dwarnln("TODO: clock_gettime({})", clock_id);
|
dwarnln("TODO: clock_gettime({})", clock_id);
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -382,6 +382,9 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!scheduler().is_idle())
|
||||||
|
Thread::current().set_cpu_time_stop();
|
||||||
|
|
||||||
#if ARCH(x86_64)
|
#if ARCH(x86_64)
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"movq %%rsp, %%rcx;"
|
"movq %%rsp, %%rcx;"
|
||||||
|
@ -412,6 +415,9 @@ namespace Kernel
|
||||||
|
|
||||||
processor_info.m_start_ns = SystemTimer::get().ns_since_boot();
|
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);
|
Processor::set_interrupt_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,7 +275,10 @@ namespace Kernel
|
||||||
page_table.load();
|
page_table.load();
|
||||||
|
|
||||||
if (thread->state() == Thread::State::NotStarted)
|
if (thread->state() == Thread::State::NotStarted)
|
||||||
|
{
|
||||||
thread->m_state = Thread::State::Executing;
|
thread->m_state = Thread::State::Executing;
|
||||||
|
thread->set_cpu_time_start();
|
||||||
|
}
|
||||||
|
|
||||||
Processor::gdt().set_tss_stack(thread->kernel_stack_top());
|
Processor::gdt().set_tss_stack(thread->kernel_stack_top());
|
||||||
Processor::load_tls();
|
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)
|
BAN::ErrorOr<Thread*> Thread::pthread_create(entry_t entry, void* arg)
|
||||||
{
|
{
|
||||||
auto* thread = TRY(create_userspace(m_process, m_process->page_table()));
|
auto* thread = TRY(create_userspace(m_process, m_process->page_table()));
|
||||||
|
|
Loading…
Reference in New Issue