From dc6f57f19cff71c6bd83a42fd58a93adbbeb70cb Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 25 Oct 2018 17:29:49 +0200 Subject: [PATCH] Add gettimeofday() syscall and LibC wrappers gettimeofday() and time(). This only has second accuracy right now, I'll work out subseconds later. --- Kernel/.bochsrc | 3 +- Kernel/Makefile | 3 +- Kernel/RTC.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++ Kernel/RTC.h | 12 ++++++ Kernel/Syscall.cpp | 5 ++- Kernel/Syscall.h | 1 + Kernel/Task.cpp | 10 +++++ Kernel/Task.h | 1 + Kernel/_fs_contents | Bin 1024000 -> 1024000 bytes Kernel/init.cpp | 3 ++ Kernel/kprintf.cpp | 2 - Kernel/sync-sh | 1 + Kernel/types.h | 6 +++ LibC/Makefile | 1 + LibC/time.cpp | 21 +++++++++++ LibC/time.h | 11 ++++++ LibC/types.h | 6 +++ Userland/.gitignore | 1 + Userland/Makefile | 9 ++++- Userland/date.cpp | 10 +++++ 20 files changed, 188 insertions(+), 8 deletions(-) create mode 100644 Kernel/RTC.cpp create mode 100644 Kernel/RTC.h create mode 100644 LibC/time.cpp create mode 100644 LibC/time.h create mode 100644 Userland/date.cpp diff --git a/Kernel/.bochsrc b/Kernel/.bochsrc index 8027057545..03643f30f3 100644 --- a/Kernel/.bochsrc +++ b/Kernel/.bochsrc @@ -35,7 +35,8 @@ cpuid: smap=false, mwait=true print_timestamps: enabled=0 port_e9_hack: enabled=1 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 log: - logprefix: %t%e%d diff --git a/Kernel/Makefile b/Kernel/Makefile index 3fc318e9de..e74007fe1d 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -19,7 +19,8 @@ KERNEL_OBJS = \ Console.o \ IRQHandler.o \ kprintf.o \ - ProcFileSystem.o + ProcFileSystem.o \ + RTC.o VFS_OBJS = \ ../VirtualFileSystem/DiskDevice.o \ diff --git a/Kernel/RTC.cpp b/Kernel/RTC.cpp new file mode 100644 index 0000000000..ef0734390a --- /dev/null +++ b/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; +} + +} + diff --git a/Kernel/RTC.h b/Kernel/RTC.h new file mode 100644 index 0000000000..77b1e5ef7f --- /dev/null +++ b/Kernel/RTC.h @@ -0,0 +1,12 @@ +#pragma once + +#include "types.h" + +namespace RTC { + +void initialize(); +time_t now(); +time_t bootTime(); + +} + diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 762008e84f..4524f72682 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -61,8 +61,9 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3) Console::the().putChar(arg1 & 0xff); break; 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: return current->sys$spawn((const char*)arg1); case Syscall::GetDirEntries: diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index bef6d5ff36..3569c91f44 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -29,6 +29,7 @@ enum Function { GetDirEntries = 0x1997, PosixLstat = 0x1998, PosixGetcwd = 0x1999, + PosixGettimeofday = 0x2000, }; void initialize(); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 9612a24cb9..28ed1981a1 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -11,6 +11,7 @@ #include "MemoryManager.h" #include "errno.h" #include "i8253.h" +#include "RTC.h" //#define DEBUG_IO //#define TASK_DEBUG @@ -728,6 +729,15 @@ int Task::sys$sleep(unsigned seconds) 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() { return m_uid; diff --git a/Kernel/Task.h b/Kernel/Task.h index 13435fc528..3f855f6d2e 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -99,6 +99,7 @@ public: int sys$get_dir_entries(int fd, void*, size_t); int sys$getcwd(char*, size_t); int sys$sleep(unsigned seconds); + int sys$gettimeofday(timeval*); static void initialize(); diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents index da330ef7e331510de91b386c9be3a52985107048..9dd078d965a83547e636605386639ad2101f24e4 100644 GIT binary patch delta 2988 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 N7VvIYSitw-KLF#Q1A_nn diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 92026a036c..06593b518b 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -25,6 +25,7 @@ #include #include "Console.h" #include "ProcFileSystem.h" +#include "RTC.h" #define TEST_VFS //#define STRESS_TEST_SPAWNING @@ -179,6 +180,7 @@ void init() auto console = make(); + RTC::initialize(); PIC::initialize(); gdt_init(); idt_init(); @@ -191,6 +193,7 @@ void init() PIT::initialize(); memset(&system, 0, sizeof(system)); + WORD base_memory = (CMOS::read(0x16) << 8) | CMOS::read(0x15); WORD ext_memory = (CMOS::read(0x18) << 8) | CMOS::read(0x17); diff --git a/Kernel/kprintf.cpp b/Kernel/kprintf.cpp index 2234967e59..b80fcc2e0b 100644 --- a/Kernel/kprintf.cpp +++ b/Kernel/kprintf.cpp @@ -1,5 +1,3 @@ -#pragma once - #include "kprintf.h" #include "Console.h" #include diff --git a/Kernel/sync-sh b/Kernel/sync-sh index b19da4ba8f..4053a3ab20 100755 --- a/Kernel/sync-sh +++ b/Kernel/sync-sh @@ -6,5 +6,6 @@ cp ../Userland/ps mnt/bin/ps cp ../Userland/ls mnt/bin/ls cp ../Userland/pwd mnt/bin/pwd cp ../Userland/sleep mnt/bin/sleep +cp ../Userland/date mnt/bin/date umount mnt sync diff --git a/Kernel/types.h b/Kernel/types.h index 3b4b609454..ac5a4feedd 100644 --- a/Kernel/types.h +++ b/Kernel/types.h @@ -23,8 +23,14 @@ typedef DWORD uid_t; typedef DWORD gid_t; typedef int pid_t; typedef DWORD time_t; +typedef DWORD suseconds_t; typedef DWORD size_t; +struct timeval { + time_t tv_sec; + suseconds_t tv_usec; +}; + struct FarPtr { DWORD offset { 0 }; WORD selector { 0 }; diff --git a/LibC/Makefile b/LibC/Makefile index 3f28724fd9..c958788553 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -6,6 +6,7 @@ OBJS = \ mman.o \ dirent.o \ stdlib.o \ + time.o \ entry.o LIBRARY = LibC.a diff --git a/LibC/time.cpp b/LibC/time.cpp new file mode 100644 index 0000000000..43efb2f364 --- /dev/null +++ b/LibC/time.cpp @@ -0,0 +1,21 @@ +#include "time.h" +#include "errno.h" +#include + +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); +} + +} diff --git a/LibC/time.h b/LibC/time.h new file mode 100644 index 0000000000..acce4816bd --- /dev/null +++ b/LibC/time.h @@ -0,0 +1,11 @@ +#pragma once + +#include "types.h" + +extern "C" { + +int gettimeofday(timeval*); +time_t time(time_t*); + +} + diff --git a/LibC/types.h b/LibC/types.h index 23f532c938..d8aacd8728 100644 --- a/LibC/types.h +++ b/LibC/types.h @@ -26,6 +26,12 @@ typedef dword nlink_t; typedef dword blksize_t; typedef dword blkcnt_t; typedef dword time_t; +typedef dword suseconds_t; + +struct timeval { + time_t tv_sec; + suseconds_t tv_usec; +}; struct stat { dev_t st_dev; /* ID of device containing file */ diff --git a/Userland/.gitignore b/Userland/.gitignore index 9effb83fcc..e17fc11729 100644 --- a/Userland/.gitignore +++ b/Userland/.gitignore @@ -4,4 +4,5 @@ ps ls pwd sleep +date *.o diff --git a/Userland/Makefile b/Userland/Makefile index 20e729d999..1615f689b5 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -4,7 +4,8 @@ OBJS = \ ps.o \ ls.o \ pwd.o \ - sleep.o + sleep.o \ + date.o APPS = \ id \ @@ -12,7 +13,8 @@ APPS = \ ps \ ls \ pwd \ - sleep + sleep \ + date ARCH_FLAGS = STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib @@ -50,6 +52,9 @@ pwd: pwd.o sleep: sleep.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a +date: date.o + $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a + .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Userland/date.cpp b/Userland/date.cpp new file mode 100644 index 0000000000..00738773c5 --- /dev/null +++ b/Userland/date.cpp @@ -0,0 +1,10 @@ +#include +#include + +int main(int c, char** v) +{ + time_t now = time(nullptr); + printf("%u\n", now); + return 0; +} +