mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
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:
parent
5978185242
commit
dc6f57f19c
Notes:
sideshowbarker
2024-07-19 18:38:42 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/dc6f57f19cf
20 changed files with 188 additions and 8 deletions
|
@ -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
|
||||
|
|
|
@ -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
90
Kernel/RTC.cpp
Normal 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
12
Kernel/RTC.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace RTC {
|
||||
|
||||
void initialize();
|
||||
time_t now();
|
||||
time_t bootTime();
|
||||
|
||||
}
|
||||
|
|
@ -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:
|
||||
|
|
|
@ -29,6 +29,7 @@ enum Function {
|
|||
GetDirEntries = 0x1997,
|
||||
PosixLstat = 0x1998,
|
||||
PosixGetcwd = 0x1999,
|
||||
PosixGettimeofday = 0x2000,
|
||||
};
|
||||
|
||||
void initialize();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
@ -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);
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#include "kprintf.h"
|
||||
#include "Console.h"
|
||||
#include <stdarg.h>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -6,6 +6,7 @@ OBJS = \
|
|||
mman.o \
|
||||
dirent.o \
|
||||
stdlib.o \
|
||||
time.o \
|
||||
entry.o
|
||||
|
||||
LIBRARY = LibC.a
|
||||
|
|
21
LibC/time.cpp
Normal file
21
LibC/time.cpp
Normal 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
11
LibC/time.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int gettimeofday(timeval*);
|
||||
time_t time(time_t*);
|
||||
|
||||
}
|
||||
|
|
@ -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
1
Userland/.gitignore
vendored
|
@ -4,4 +4,5 @@ ps
|
|||
ls
|
||||
pwd
|
||||
sleep
|
||||
date
|
||||
*.o
|
||||
|
|
|
@ -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
10
Userland/date.cpp
Normal 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;
|
||||
}
|
||||
|
Loading…
Reference in a new issue