瀏覽代碼

Add gettimeofday() syscall and LibC wrappers gettimeofday() and time().

This only has second accuracy right now, I'll work out subseconds later.
Andreas Kling 6 年之前
父節點
當前提交
dc6f57f19c
共有 20 個文件被更改,包括 188 次插入8 次删除
  1. 2 1
      Kernel/.bochsrc
  2. 2 1
      Kernel/Makefile
  3. 90 0
      Kernel/RTC.cpp
  4. 12 0
      Kernel/RTC.h
  5. 3 2
      Kernel/Syscall.cpp
  6. 1 0
      Kernel/Syscall.h
  7. 10 0
      Kernel/Task.cpp
  8. 1 0
      Kernel/Task.h
  9. 二進制
      Kernel/_fs_contents
  10. 3 0
      Kernel/init.cpp
  11. 0 2
      Kernel/kprintf.cpp
  12. 1 0
      Kernel/sync-sh
  13. 6 0
      Kernel/types.h
  14. 1 0
      LibC/Makefile
  15. 21 0
      LibC/time.cpp
  16. 11 0
      LibC/time.h
  17. 6 0
      LibC/types.h
  18. 1 0
      Userland/.gitignore
  19. 7 2
      Userland/Makefile
  20. 10 0
      Userland/date.cpp

+ 2 - 1
Kernel/.bochsrc

@@ -35,7 +35,8 @@ cpuid: smap=false, mwait=true
 print_timestamps: enabled=0
 print_timestamps: enabled=0
 port_e9_hack: enabled=1
 port_e9_hack: enabled=1
 private_colormap: enabled=0
 private_colormap: enabled=0
-clock: sync=none, time0=local, rtc_sync=0
+#clock: sync=realtime, time0=local, rtc_sync=1
+clock: sync=none, time0=local, rtc_sync=1
 # no cmosimage
 # no cmosimage
 log: -
 log: -
 logprefix: %t%e%d
 logprefix: %t%e%d

+ 2 - 1
Kernel/Makefile

@@ -19,7 +19,8 @@ KERNEL_OBJS = \
        Console.o \
        Console.o \
        IRQHandler.o \
        IRQHandler.o \
        kprintf.o \
        kprintf.o \
-       ProcFileSystem.o
+       ProcFileSystem.o \
+       RTC.o
 
 
 VFS_OBJS = \
 VFS_OBJS = \
     ../VirtualFileSystem/DiskDevice.o \
     ../VirtualFileSystem/DiskDevice.o \

+ 90 - 0
Kernel/RTC.cpp

@@ -0,0 +1,90 @@
+#include "RTC.h"
+#include "CMOS.h"
+
+namespace RTC {
+
+static time_t s_bootTime;
+
+void initialize()
+{    
+    byte cmosMode = CMOS::read(0x0b);
+    cmosMode |= 2; // 24 hour mode
+    cmosMode |= 4; // No BCD mode
+    CMOS::write(0x0b, cmosMode);
+
+    s_bootTime = now();
+}
+
+time_t bootTime()
+{
+    return s_bootTime;
+}
+
+static bool updateInProgress()
+{
+    return CMOS::read(0x0a) & 0x80;
+}
+
+inline bool isLeapYear(unsigned year)
+{
+    return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400) == 0));
+}
+
+static unsigned daysInMonthsSinceStartOfYear(unsigned month, unsigned year)
+{
+    switch (month) {
+    case 11: return 30;
+    case 10: return 31;
+    case 9: return 30;
+    case 8: return 31;
+    case 7: return 31;
+    case 6: return 30;
+    case 5: return 31;
+    case 4: return 30;
+    case 3: return 31;
+    case 2:
+        if (isLeapYear(year))
+            return 29;
+        return 28;
+    case 1: return 31;
+    default: return 0;
+    }
+}
+
+static unsigned daysInYearsSinceEpoch(unsigned year)
+{
+    unsigned days = 0;
+    while (year > 1969) {
+        days += 365;
+        if (isLeapYear(year))
+            ++days;
+        --year;
+    }
+    return days;
+}
+
+time_t now()
+{
+    // FIXME: We should probably do something more robust here.
+    //        Perhaps read all the values twice and verify that they were identical.
+    //        We don't want to be caught in the middle of an RTC register update.
+    while (updateInProgress())
+        ;
+
+    unsigned year = (CMOS::read(0x32) * 100) + CMOS::read(0x09);
+    unsigned month = CMOS::read(0x08);
+    unsigned day = CMOS::read(0x07);
+    unsigned hour = CMOS::read(0x04);
+    unsigned minute = CMOS::read(0x02);
+    unsigned second = CMOS::read(0x00);
+
+    return daysInYearsSinceEpoch(year - 1) * 86400
+         + daysInMonthsSinceStartOfYear(month - 1, year) * 86400
+         + day * 86400
+         + hour * 3600
+         + minute * 60
+         + second;
+}
+
+}
+

+ 12 - 0
Kernel/RTC.h

@@ -0,0 +1,12 @@
+#pragma once
+
+#include "types.h"
+
+namespace RTC {
+
+void initialize();
+time_t now();
+time_t bootTime();
+
+}
+

+ 3 - 2
Kernel/Syscall.cpp

@@ -61,8 +61,9 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
         Console::the().putChar(arg1 & 0xff);
         Console::the().putChar(arg1 & 0xff);
         break;
         break;
     case Syscall::Sleep:
     case Syscall::Sleep:
-        current->sys$sleep(arg1);
-        break;
+        return current->sys$sleep(arg1);
+    case Syscall::PosixGettimeofday:
+        return current->sys$gettimeofday((timeval*)arg1);
     case Syscall::Spawn:
     case Syscall::Spawn:
         return current->sys$spawn((const char*)arg1);
         return current->sys$spawn((const char*)arg1);
     case Syscall::GetDirEntries:
     case Syscall::GetDirEntries:

+ 1 - 0
Kernel/Syscall.h

@@ -29,6 +29,7 @@ enum Function {
     GetDirEntries = 0x1997,
     GetDirEntries = 0x1997,
     PosixLstat = 0x1998,
     PosixLstat = 0x1998,
     PosixGetcwd = 0x1999,
     PosixGetcwd = 0x1999,
+    PosixGettimeofday = 0x2000,
 };
 };
 
 
 void initialize();
 void initialize();

+ 10 - 0
Kernel/Task.cpp

@@ -11,6 +11,7 @@
 #include "MemoryManager.h"
 #include "MemoryManager.h"
 #include "errno.h"
 #include "errno.h"
 #include "i8253.h"
 #include "i8253.h"
+#include "RTC.h"
 
 
 //#define DEBUG_IO
 //#define DEBUG_IO
 //#define TASK_DEBUG
 //#define TASK_DEBUG
@@ -728,6 +729,15 @@ int Task::sys$sleep(unsigned seconds)
     return 0;
     return 0;
 }
 }
 
 
+int Task::sys$gettimeofday(timeval* tv)
+{
+    InterruptDisabler disabler;
+    auto now = RTC::now();
+    tv->tv_sec = now;
+    tv->tv_usec = 0;
+    return 0;
+}
+
 uid_t Task::sys$getuid()
 uid_t Task::sys$getuid()
 {
 {
     return m_uid;
     return m_uid;

+ 1 - 0
Kernel/Task.h

@@ -99,6 +99,7 @@ public:
     int sys$get_dir_entries(int fd, void*, size_t);
     int sys$get_dir_entries(int fd, void*, size_t);
     int sys$getcwd(char*, size_t);
     int sys$getcwd(char*, size_t);
     int sys$sleep(unsigned seconds);
     int sys$sleep(unsigned seconds);
+    int sys$gettimeofday(timeval*);
 
 
     static void initialize();
     static void initialize();
 
 

二進制
Kernel/_fs_contents


+ 3 - 0
Kernel/init.cpp

@@ -25,6 +25,7 @@
 #include <ELFLoader/ELFLoader.h>
 #include <ELFLoader/ELFLoader.h>
 #include "Console.h"
 #include "Console.h"
 #include "ProcFileSystem.h"
 #include "ProcFileSystem.h"
+#include "RTC.h"
 
 
 #define TEST_VFS
 #define TEST_VFS
 //#define STRESS_TEST_SPAWNING
 //#define STRESS_TEST_SPAWNING
@@ -179,6 +180,7 @@ void init()
 
 
     auto console = make<Console>();
     auto console = make<Console>();
 
 
+    RTC::initialize();
     PIC::initialize();
     PIC::initialize();
     gdt_init();
     gdt_init();
     idt_init();
     idt_init();
@@ -191,6 +193,7 @@ void init()
     PIT::initialize();
     PIT::initialize();
 
 
     memset(&system, 0, sizeof(system));
     memset(&system, 0, sizeof(system));
+
     WORD base_memory = (CMOS::read(0x16) << 8) | CMOS::read(0x15);
     WORD base_memory = (CMOS::read(0x16) << 8) | CMOS::read(0x15);
     WORD ext_memory = (CMOS::read(0x18) << 8) | CMOS::read(0x17);
     WORD ext_memory = (CMOS::read(0x18) << 8) | CMOS::read(0x17);
 
 

+ 0 - 2
Kernel/kprintf.cpp

@@ -1,5 +1,3 @@
-#pragma once
-
 #include "kprintf.h"
 #include "kprintf.h"
 #include "Console.h"
 #include "Console.h"
 #include <stdarg.h>
 #include <stdarg.h>

+ 1 - 0
Kernel/sync-sh

@@ -6,5 +6,6 @@ cp ../Userland/ps mnt/bin/ps
 cp ../Userland/ls mnt/bin/ls
 cp ../Userland/ls mnt/bin/ls
 cp ../Userland/pwd mnt/bin/pwd
 cp ../Userland/pwd mnt/bin/pwd
 cp ../Userland/sleep mnt/bin/sleep
 cp ../Userland/sleep mnt/bin/sleep
+cp ../Userland/date mnt/bin/date
 umount mnt
 umount mnt
 sync
 sync

+ 6 - 0
Kernel/types.h

@@ -23,8 +23,14 @@ typedef DWORD uid_t;
 typedef DWORD gid_t;
 typedef DWORD gid_t;
 typedef int pid_t;
 typedef int pid_t;
 typedef DWORD time_t;
 typedef DWORD time_t;
+typedef DWORD suseconds_t;
 typedef DWORD size_t;
 typedef DWORD size_t;
 
 
+struct timeval {
+    time_t tv_sec;
+    suseconds_t tv_usec;
+};
+
 struct FarPtr {
 struct FarPtr {
     DWORD offset { 0 };
     DWORD offset { 0 };
     WORD selector { 0 };
     WORD selector { 0 };

+ 1 - 0
LibC/Makefile

@@ -6,6 +6,7 @@ OBJS = \
        mman.o \
        mman.o \
        dirent.o \
        dirent.o \
        stdlib.o \
        stdlib.o \
+       time.o \
        entry.o
        entry.o
 
 
 LIBRARY = LibC.a
 LIBRARY = LibC.a

+ 21 - 0
LibC/time.cpp

@@ -0,0 +1,21 @@
+#include "time.h"
+#include "errno.h"
+#include <Kernel/Syscall.h>
+
+extern "C" {
+
+time_t time(time_t* tloc)
+{
+    timeval tv;
+    if (gettimeofday(&tv) < 0)
+        return (time_t)-1;
+    return tv.tv_sec;
+}
+
+int gettimeofday(timeval* tv)
+{
+    int rc = Syscall::invoke(Syscall::PosixGettimeofday, (dword)tv);
+    __RETURN_WITH_ERRNO(rc, rc, -1);
+}
+
+}

+ 11 - 0
LibC/time.h

@@ -0,0 +1,11 @@
+#pragma once
+
+#include "types.h"
+
+extern "C" {
+
+int gettimeofday(timeval*);
+time_t time(time_t*);
+
+}
+

+ 6 - 0
LibC/types.h

@@ -26,6 +26,12 @@ typedef dword nlink_t;
 typedef dword blksize_t;
 typedef dword blksize_t;
 typedef dword blkcnt_t;
 typedef dword blkcnt_t;
 typedef dword time_t;
 typedef dword time_t;
+typedef dword suseconds_t;
+
+struct timeval {
+    time_t tv_sec;
+    suseconds_t tv_usec;
+};
 
 
 struct stat {
 struct stat {
     dev_t     st_dev;     /* ID of device containing file */
     dev_t     st_dev;     /* ID of device containing file */

+ 1 - 0
Userland/.gitignore

@@ -4,4 +4,5 @@ ps
 ls
 ls
 pwd
 pwd
 sleep
 sleep
+date
 *.o
 *.o

+ 7 - 2
Userland/Makefile

@@ -4,7 +4,8 @@ OBJS = \
        ps.o \
        ps.o \
        ls.o \
        ls.o \
        pwd.o \
        pwd.o \
-       sleep.o
+       sleep.o \
+       date.o
 
 
 APPS = \
 APPS = \
        id \
        id \
@@ -12,7 +13,8 @@ APPS = \
        ps \
        ps \
        ls \
        ls \
        pwd \
        pwd \
-       sleep
+       sleep \
+       date
 
 
 ARCH_FLAGS =
 ARCH_FLAGS =
 STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
 STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
@@ -50,6 +52,9 @@ pwd: pwd.o
 sleep: sleep.o
 sleep: sleep.o
 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
 
 
+date: date.o
+	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
+
 .cpp.o:
 .cpp.o:
 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
 
 

+ 10 - 0
Userland/date.cpp

@@ -0,0 +1,10 @@
+#include <LibC/time.h>
+#include <LibC/stdio.h>
+
+int main(int c, char** v)
+{
+    time_t now = time(nullptr);
+    printf("%u\n", now);
+    return 0;
+}
+