mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 08:56:40 +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
|
@ -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
|
||||||
|
|
|
@ -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
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);
|
Console::the().putChar(arg1 & 0xff);
|
||||||
break;
|
break;
|
||||||
case Syscall::Sleep:
|
case Syscall::Sleep:
|
||||||
current->sys$sleep(arg1);
|
return current->sys$sleep(arg1);
|
||||||
break;
|
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:
|
||||||
|
|
|
@ -29,6 +29,7 @@ enum Function {
|
||||||
GetDirEntries = 0x1997,
|
GetDirEntries = 0x1997,
|
||||||
PosixLstat = 0x1998,
|
PosixLstat = 0x1998,
|
||||||
PosixGetcwd = 0x1999,
|
PosixGetcwd = 0x1999,
|
||||||
|
PosixGettimeofday = 0x2000,
|
||||||
};
|
};
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "Console.h"
|
#include "Console.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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
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 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
Userland/.gitignore
vendored
1
Userland/.gitignore
vendored
|
@ -4,4 +4,5 @@ ps
|
||||||
ls
|
ls
|
||||||
pwd
|
pwd
|
||||||
sleep
|
sleep
|
||||||
|
date
|
||||||
*.o
|
*.o
|
||||||
|
|
|
@ -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
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