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

This only has second accuracy right now, I'll work out subseconds later.
This commit is contained in:
Andreas Kling 2018-10-25 17:29:49 +02:00
parent 5978185242
commit dc6f57f19c
20 changed files with 188 additions and 8 deletions

View file

@ -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

View file

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

90
Kernel/RTC.cpp Normal file
View file

@ -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
Kernel/RTC.h Normal file
View file

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

View file

@ -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:

View file

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

View file

@ -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;

View file

@ -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();

Binary file not shown.

View file

@ -25,6 +25,7 @@
#include <ELFLoader/ELFLoader.h>
#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<Console>();
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);

View file

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

View file

@ -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

View file

@ -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 };

View file

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

21
LibC/time.cpp Normal file
View file

@ -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
LibC/time.h Normal file
View file

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

View file

@ -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 */

1
Userland/.gitignore vendored
View file

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

View file

@ -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 $<

10
Userland/date.cpp Normal file
View file

@ -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;
}