diff --git a/Kernel/KernelInfoPage.h b/Kernel/KernelInfoPage.h new file mode 100644 index 00000000000..d5b583d5757 --- /dev/null +++ b/Kernel/KernelInfoPage.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#ifdef KERNEL +# include +#else +# include +#endif + +struct KernelInfoPage { + volatile u32 serial; + volatile struct timeval now; +}; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 93b661ce8e9..b3d37d92ede 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -51,11 +52,13 @@ //#define SHARED_BUFFER_DEBUG static void create_signal_trampolines(); +static void create_kernel_info_page(); static pid_t next_pid; InlineLinkedList* g_processes; static String* s_hostname; static Lock* s_hostname_lock; +static VirtualAddress s_info_page_address; VirtualAddress g_return_to_ring3_from_signal_trampoline; VirtualAddress g_return_to_ring0_from_signal_trampoline; HashMap>* g_modules; @@ -70,6 +73,14 @@ void Process::initialize() s_hostname_lock = new Lock; create_signal_trampolines(); + create_kernel_info_page(); +} + +void Process::update_info_page_timestamp(const timeval& tv) +{ + auto* info_page = (KernelInfoPage*)s_info_page_address.as_ptr(); + info_page->serial++; + const_cast(info_page->now) = tv; } Vector Process::all_pids() @@ -981,6 +992,13 @@ void create_signal_trampolines() trampoline_region->remap(); } +void create_kernel_info_page() +{ + auto* info_page_region = MM.allocate_user_accessible_kernel_region(PAGE_SIZE, "Kernel info page").leak_ptr(); + s_info_page_address = info_page_region->vaddr(); + memset(s_info_page_address.as_ptr(), 0, PAGE_SIZE); +} + int Process::sys$restore_signal_mask(u32 mask) { current->m_signal_mask = mask; @@ -1682,10 +1700,7 @@ int Process::sys$sleep(unsigned seconds) timeval kgettimeofday() { - timeval tv; - tv.tv_sec = RTC::boot_time() + PIT::seconds_since_boot(); - tv.tv_usec = PIT::ticks_this_second() * 1000; - return tv; + return const_cast(((KernelInfoPage*)s_info_page_address.as_ptr())->now); } void kgettimeofday(timeval& tv) @@ -1697,7 +1712,7 @@ int Process::sys$gettimeofday(timeval* tv) { if (!validate_write_typed(tv)) return -EFAULT; - kgettimeofday(*tv); + *tv = kgettimeofday(); return 0; } @@ -3733,3 +3748,8 @@ int Process::sys$profiling_disable(pid_t pid) Profiling::stop(); return 0; } + +void* Process::sys$get_kernel_info_page() +{ + return s_info_page_address.as_ptr(); +} diff --git a/Kernel/Process.h b/Kernel/Process.h index 8db6c109a6e..56bac006d7d 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -67,6 +67,8 @@ public: static Process* from_pid(pid_t); + static void update_info_page_timestamp(const timeval&); + const String& name() const { return m_name; } pid_t pid() const { return m_pid; } pid_t sid() const { return m_sid; } @@ -233,6 +235,7 @@ public: int sys$module_unload(const char* name, size_t name_length); int sys$profiling_enable(pid_t); int sys$profiling_disable(pid_t); + void* sys$get_kernel_info_page(); static void initialize(); diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index f8849af97ad..ef710619fdb 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -548,6 +548,11 @@ void Scheduler::timer_tick(RegisterDump& regs) ++g_uptime; + timeval tv; + tv.tv_sec = RTC::boot_time() + PIT::seconds_since_boot(); + tv.tv_usec = PIT::ticks_this_second() * 1000; + Process::update_info_page_timestamp(tv); + if (s_beep_timeout && g_uptime > s_beep_timeout) { PCSpeaker::tone_off(); s_beep_timeout = 0; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 366ce1e9999..e3b238862f2 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -149,7 +149,8 @@ typedef u32 socklen_t; __ENUMERATE_SYSCALL(purge) \ __ENUMERATE_SYSCALL(set_shared_buffer_volatile) \ __ENUMERATE_SYSCALL(profiling_enable) \ - __ENUMERATE_SYSCALL(profiling_disable) + __ENUMERATE_SYSCALL(profiling_disable) \ + __ENUMERATE_SYSCALL(get_kernel_info_page) namespace Syscall { diff --git a/Libraries/LibC/time.cpp b/Libraries/LibC/time.cpp index 4cd2e47fd93..d0d156d67e6 100644 --- a/Libraries/LibC/time.cpp +++ b/Libraries/LibC/time.cpp @@ -1,10 +1,11 @@ +#include #include #include #include +#include #include #include #include -#include extern "C" { @@ -21,8 +22,17 @@ time_t time(time_t* tloc) int gettimeofday(struct timeval* __restrict__ tv, void* __restrict__) { - int rc = syscall(SC_gettimeofday, tv); - __RETURN_WITH_ERRNO(rc, rc, -1); + static volatile KernelInfoPage* kernel_info; + if (!kernel_info) + kernel_info = (volatile KernelInfoPage*)syscall(SC_get_kernel_info_page); + + for (;;) { + auto serial = kernel_info->serial; + *tv = const_cast(kernel_info->now); + if (serial == kernel_info->serial) + break; + } + return 0; } char* ctime(const time_t*)