Browse Source

Kernel: Do timekeeping manually instead of asking the RTC all the time.

This introduces a tiny amount of timer drift which I will have to fix
somehow eventually, but it's a huge improvement in timing consistency
as we no longer suddenly jump from e.g 10:45:49.123 to 10:45:50.000.
Andreas Kling 6 years ago
parent
commit
ab11f42094
5 changed files with 34 additions and 21 deletions
  1. 8 5
      Kernel/Ext2FileSystem.cpp
  2. 6 5
      Kernel/Process.cpp
  3. 4 4
      Kernel/Scheduler.cpp
  4. 14 6
      Kernel/i8253.cpp
  5. 2 1
      Kernel/i8253.h

+ 8 - 5
Kernel/Ext2FileSystem.cpp

@@ -317,7 +317,9 @@ void Ext2FS::free_inode(Ext2FSInode& inode)
     ASSERT(inode.m_raw_inode.i_links_count == 0);
     dbgprintf("Ext2FS: inode %u has no more links, time to delete!\n", inode.index());
 
-    inode.m_raw_inode.i_dtime = RTC::now();
+    struct timeval now;
+    kgettimeofday(now);
+    inode.m_raw_inode.i_dtime = now.tv_sec;
     write_ext2_inode(inode.index(), inode.m_raw_inode);
 
     auto block_list = block_list_for_inode(inode.m_raw_inode, true);
@@ -1178,16 +1180,17 @@ RetainPtr<Inode> Ext2FS::create_inode(InodeIdentifier parent_id, const String& n
     else
         initial_links_count = 1;
 
-    auto timestamp = RTC::now();
+    struct timeval now;
+    kgettimeofday(now);
     ext2_inode e2inode;
     memset(&e2inode, 0, sizeof(ext2_inode));
     e2inode.i_mode = mode;
     e2inode.i_uid = current->process().euid();
     e2inode.i_gid = current->process().egid();
     e2inode.i_size = size;
-    e2inode.i_atime = timestamp;
-    e2inode.i_ctime = timestamp;
-    e2inode.i_mtime = timestamp;
+    e2inode.i_atime = now.tv_sec;
+    e2inode.i_ctime = now.tv_sec;
+    e2inode.i_mtime = now.tv_sec;
     e2inode.i_dtime = 0;
     e2inode.i_links_count = initial_links_count;
 

+ 6 - 5
Kernel/Process.cpp

@@ -915,9 +915,10 @@ int Process::sys$utime(const char* pathname, const utimbuf* buf)
         atime = buf->actime;
         mtime = buf->modtime;
     } else {
-        auto now = RTC::now();
-        mtime = now;
-        atime = now;
+        struct timeval now;
+        kgettimeofday(now);
+        mtime = now.tv_sec;
+        atime = now.tv_sec;
     }
     return VFS::the().utime(String(pathname), cwd_inode(), atime, mtime);
 }
@@ -1238,8 +1239,8 @@ int Process::sys$sleep(unsigned seconds)
 
 void kgettimeofday(timeval& tv)
 {
-    tv.tv_sec = RTC::now();
-    tv.tv_usec = (PIT::ticks_since_boot() % 1000) * 1000;
+    tv.tv_sec = RTC::boot_time() + PIT::seconds_since_boot();
+    tv.tv_usec = PIT::ticks_this_second() * 1000;
 }
 
 int Process::sys$gettimeofday(timeval* tv)

+ 4 - 4
Kernel/Scheduler.cpp

@@ -55,15 +55,15 @@ bool Scheduler::pick_next()
         return context_switch(s_colonel_process->main_thread());
     }
 
-    auto now_sec = RTC::now();
-    auto now_usec = (suseconds_t)((PIT::ticks_since_boot() % 1000) * 1000);
+    struct timeval now;
+    kgettimeofday(now);
+    auto now_sec = now.tv_sec;
+    auto now_usec = now.tv_usec;
 
     // Check and unblock threads whose wait conditions have been met.
     Thread::for_each([&] (Thread& thread) {
         auto& process = thread.process();
 
-//        dbgprintf("pick_next, checking on %s(%u:%u) in state %s\n", process.name().impl()->characters(), process.pid(), thread.tid(), to_string(thread.state()));
-
         if (thread.state() == Thread::BlockedSleep) {
             if (thread.wakeup_time() <= system.uptime)
                 thread.unblock();

+ 14 - 6
Kernel/i8253.cpp

@@ -57,26 +57,34 @@ asm(
 
 #define BASE_FREQUENCY     1193182
 
-static dword s_ticks_since_boot;
+static dword s_ticks_this_second;
+static dword s_seconds_since_boot;
 
 void timer_interrupt_handler(RegisterDump& regs)
 {
     IRQHandlerScope scope(IRQ_TIMER);
-    ++s_ticks_since_boot;
+    if (++s_ticks_this_second >= TICKS_PER_SECOND) {
+        // FIXME: Synchronize with the RTC somehow to prevent drifting apart.
+        ++s_seconds_since_boot;
+        s_ticks_this_second = 0;
+    }
     Scheduler::timer_tick(regs);
 }
 
 namespace PIT {
 
-dword ticks_since_boot()
+dword ticks_this_second()
 {
-    return s_ticks_since_boot;
+    return s_ticks_this_second;
 }
 
-void initialize()
+dword seconds_since_boot()
 {
-    s_ticks_since_boot = 0;
+    return s_seconds_since_boot;
+}
 
+void initialize()
+{
     word timer_reload;
 
     IO::out8(PIT_CTL, TIMER0_SELECT | WRITE_WORD | MODE_SQUARE_WAVE);

+ 2 - 1
Kernel/i8253.h

@@ -7,6 +7,7 @@
 namespace PIT {
 
 void initialize();
-dword ticks_since_boot();
+dword ticks_this_second();
+dword seconds_since_boot();
 
 }