1
0
mirror of https://github.com/SerenityOS/serenity synced 2024-07-03 10:33:40 +00:00

Kernel: Use UnixDateTime wherever applicable

"Wherever applicable" = most places, actually :^), especially for
networking and filesystem timestamps.

This includes changes to unzip, which uses DOSPackedTime, since that is
changed for the FAT file systems.
This commit is contained in:
kleines Filmröllchen 2023-03-13 22:11:13 +01:00 committed by Jelle Raaijmakers
parent c1323febc2
commit 939600d2d4
41 changed files with 115 additions and 125 deletions

View File

@ -8,12 +8,12 @@
namespace AK { namespace AK {
Duration time_from_packed_dos(DOSPackedDate date, DOSPackedTime time) UnixDateTime time_from_packed_dos(DOSPackedDate date, DOSPackedTime time)
{ {
if (date.value == 0) if (date.value == 0)
return Duration(); return UnixDateTime::from_unix_time_parts(first_dos_year, 1, 1, 0, 0, 0, 0);
return Duration::from_timestamp(first_dos_year + date.year, date.month, date.day, time.hour, time.minute, time.second * 2, 0); return UnixDateTime::from_unix_time_parts(first_dos_year + date.year, date.month, date.day, time.hour, time.minute, time.second * 2, 0);
} }
DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day) DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day)

View File

@ -33,7 +33,7 @@ static_assert(sizeof(DOSPackedDate) == 2);
inline constexpr u16 first_dos_year = 1980; inline constexpr u16 first_dos_year = 1980;
Duration time_from_packed_dos(DOSPackedDate, DOSPackedTime); UnixDateTime time_from_packed_dos(DOSPackedDate, DOSPackedTime);
DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day); DOSPackedDate to_packed_dos_date(unsigned year, unsigned month, unsigned day);
DOSPackedTime to_packed_dos_time(unsigned hour, unsigned minute, unsigned second); DOSPackedTime to_packed_dos_time(unsigned hour, unsigned minute, unsigned second);

View File

@ -19,9 +19,9 @@ void initialize()
s_boot_time = now(); s_boot_time = now();
} }
Duration boot_time() UnixDateTime boot_time()
{ {
return Duration::from_timespec({ s_boot_time, 0 }); return UnixDateTime::from_seconds_since_epoch(s_boot_time);
} }
static bool update_in_progress() static bool update_in_progress()

View File

@ -13,6 +13,6 @@ namespace Kernel::RTC {
void initialize(); void initialize();
time_t now(); time_t now();
Duration boot_time(); UnixDateTime boot_time();
} }

View File

@ -329,10 +329,11 @@ ErrorOr<u32> Controller::get_pcm_output_sample_rate(size_t channel_index)
ErrorOr<void> wait_until(size_t delay_in_microseconds, size_t timeout_in_microseconds, Function<ErrorOr<bool>()> condition) ErrorOr<void> wait_until(size_t delay_in_microseconds, size_t timeout_in_microseconds, Function<ErrorOr<bool>()> condition)
{ {
auto const& time_management = TimeManagement::the(); auto const& time_management = TimeManagement::the();
u64 start_microseconds = time_management.now().to_microseconds(); // FIXME: Use monotonic time instead.
u64 start_microseconds = time_management.now().offset_to_epoch().to_microseconds();
while (!TRY(condition())) { while (!TRY(condition())) {
microseconds_delay(delay_in_microseconds); microseconds_delay(delay_in_microseconds);
if ((time_management.now().to_microseconds() - start_microseconds) >= timeout_in_microseconds) if ((time_management.now().offset_to_epoch().to_microseconds() - start_microseconds) >= timeout_in_microseconds)
return ETIMEDOUT; return ETIMEDOUT;
} }
return {}; return {};

View File

@ -38,7 +38,7 @@ InodeMetadata DevPtsFSInode::metadata() const
{ {
if (auto pty = m_pty.strong_ref()) { if (auto pty = m_pty.strong_ref()) {
auto metadata = m_metadata; auto metadata = m_metadata;
metadata.mtime = Duration::from_timespec({ pty->time_of_last_write(), 0 }); metadata.mtime = pty->time_of_last_write();
return metadata; return metadata;
} }
return m_metadata; return m_metadata;

View File

@ -471,7 +471,7 @@ ErrorOr<NonnullRefPtr<Inode>> Ext2FS::create_inode(Ext2FSInode& parent_inode, St
return ENOENT; return ENOENT;
ext2_inode e2inode {}; ext2_inode e2inode {};
auto now = kgettimeofday().to_truncated_seconds(); auto now = kgettimeofday().truncated_seconds_since_epoch();
e2inode.i_mode = mode; e2inode.i_mode = mode;
e2inode.i_uid = uid.value(); e2inode.i_uid = uid.value();
e2inode.i_gid = gid.value(); e2inode.i_gid = gid.value();
@ -572,7 +572,7 @@ ErrorOr<void> Ext2FS::free_inode(Ext2FSInode& inode)
// NOTE: After this point, the inode metadata is wiped. // NOTE: After this point, the inode metadata is wiped.
memset(&inode.m_raw_inode, 0, sizeof(ext2_inode)); memset(&inode.m_raw_inode, 0, sizeof(ext2_inode));
inode.m_raw_inode.i_dtime = kgettimeofday().to_truncated_seconds(); inode.m_raw_inode.i_dtime = kgettimeofday().truncated_seconds_since_epoch();
TRY(write_ext2_inode(inode.index(), inode.m_raw_inode)); TRY(write_ext2_inode(inode.index(), inode.m_raw_inode));
// Mark the inode as free. // Mark the inode as free.

View File

@ -474,10 +474,10 @@ InodeMetadata Ext2FSInode::metadata() const
metadata.uid = m_raw_inode.i_uid; metadata.uid = m_raw_inode.i_uid;
metadata.gid = m_raw_inode.i_gid; metadata.gid = m_raw_inode.i_gid;
metadata.link_count = m_raw_inode.i_links_count; metadata.link_count = m_raw_inode.i_links_count;
metadata.atime = Duration::from_timespec({ m_raw_inode.i_atime, 0 }); metadata.atime = UnixDateTime::from_seconds_since_epoch(m_raw_inode.i_atime);
metadata.ctime = Duration::from_timespec({ m_raw_inode.i_ctime, 0 }); metadata.ctime = UnixDateTime::from_seconds_since_epoch(m_raw_inode.i_ctime);
metadata.mtime = Duration::from_timespec({ m_raw_inode.i_mtime, 0 }); metadata.mtime = UnixDateTime::from_seconds_since_epoch(m_raw_inode.i_mtime);
metadata.dtime = Duration::from_timespec({ m_raw_inode.i_dtime, 0 }); metadata.dtime = UnixDateTime::from_seconds_since_epoch(m_raw_inode.i_dtime);
metadata.block_size = fs().block_size(); metadata.block_size = fs().block_size();
metadata.block_count = m_raw_inode.i_blocks; metadata.block_count = m_raw_inode.i_blocks;
@ -985,7 +985,7 @@ ErrorOr<NonnullRefPtr<Inode>> Ext2FSInode::lookup(StringView name)
return fs().get_inode({ fsid(), inode_index }); return fs().get_inode({ fsid(), inode_index });
} }
ErrorOr<void> Ext2FSInode::update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) ErrorOr<void> Ext2FSInode::update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime)
{ {
MutexLocker locker(m_inode_lock); MutexLocker locker(m_inode_lock);
if (fs().is_readonly()) if (fs().is_readonly())

View File

@ -37,7 +37,7 @@ private:
virtual ErrorOr<void> add_child(Inode& child, StringView name, mode_t) override; virtual ErrorOr<void> add_child(Inode& child, StringView name, mode_t) override;
virtual ErrorOr<void> remove_child(StringView name) override; virtual ErrorOr<void> remove_child(StringView name) override;
virtual ErrorOr<void> replace_child(StringView name, Inode& child) override; virtual ErrorOr<void> replace_child(StringView name, Inode& child) override;
virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) override; virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
virtual ErrorOr<void> increment_link_count() override; virtual ErrorOr<void> increment_link_count() override;
virtual ErrorOr<void> decrement_link_count() override; virtual ErrorOr<void> decrement_link_count() override;
virtual ErrorOr<void> chmod(mode_t) override; virtual ErrorOr<void> chmod(mode_t) override;

View File

@ -145,7 +145,7 @@ ErrorOr<void> ISO9660Inode::truncate(u64)
return EROFS; return EROFS;
} }
ErrorOr<void> ISO9660Inode::update_timestamps(Optional<Duration>, Optional<Duration>, Optional<Duration>) ErrorOr<void> ISO9660Inode::update_timestamps(Optional<UnixDateTime>, Optional<UnixDateTime>, Optional<UnixDateTime>)
{ {
return EROFS; return EROFS;
} }
@ -169,7 +169,7 @@ void ISO9660Inode::create_metadata()
{ {
u32 data_length = LittleEndian { m_record.data_length.little }; u32 data_length = LittleEndian { m_record.data_length.little };
bool is_directory = has_flag(m_record.file_flags, ISO::FileFlags::Directory); bool is_directory = has_flag(m_record.file_flags, ISO::FileFlags::Directory);
auto recorded_at = Duration::from_timespec({ parse_numerical_date_time(m_record.recording_date_and_time), 0 }); auto recorded_at = parse_numerical_date_time(m_record.recording_date_and_time);
m_metadata = { m_metadata = {
.inode = identifier(), .inode = identifier(),
@ -189,16 +189,12 @@ void ISO9660Inode::create_metadata()
}; };
} }
time_t ISO9660Inode::parse_numerical_date_time(ISO::NumericalDateAndTime const& date) UnixDateTime ISO9660Inode::parse_numerical_date_time(ISO::NumericalDateAndTime const& date)
{ {
i32 year_offset = date.years_since_1900 - 70; i32 year_offset = date.years_since_1900 - 70;
return (year_offset * 60 * 60 * 24 * 30 * 12) // FIXME: This ignores timezone information in date.
+ (date.month * 60 * 60 * 24 * 30) return UnixDateTime::from_unix_time_parts(year_offset, date.month, date.day, date.hour, date.minute, date.second, 0);
+ (date.day * 60 * 60 * 24)
+ (date.hour * 60 * 60)
+ (date.minute * 60)
+ date.second;
} }
StringView ISO9660Inode::get_normalized_filename(ISO::DirectoryRecordHeader const& record, Bytes buffer) StringView ISO9660Inode::get_normalized_filename(ISO::DirectoryRecordHeader const& record, Bytes buffer)

View File

@ -32,7 +32,7 @@ public:
virtual ErrorOr<void> chmod(mode_t) override; virtual ErrorOr<void> chmod(mode_t) override;
virtual ErrorOr<void> chown(UserID, GroupID) override; virtual ErrorOr<void> chown(UserID, GroupID) override;
virtual ErrorOr<void> truncate(u64) override; virtual ErrorOr<void> truncate(u64) override;
virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) override; virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
private: private:
// HACK: The base ISO 9660 standard says the maximum filename length is 37 // HACK: The base ISO 9660 standard says the maximum filename length is 37
@ -51,7 +51,7 @@ private:
static StringView get_normalized_filename(ISO::DirectoryRecordHeader const& record, Bytes buffer); static StringView get_normalized_filename(ISO::DirectoryRecordHeader const& record, Bytes buffer);
void create_metadata(); void create_metadata();
time_t parse_numerical_date_time(ISO::NumericalDateAndTime const&); UnixDateTime parse_numerical_date_time(ISO::NumericalDateAndTime const&);
InodeMetadata m_metadata; InodeMetadata m_metadata;
ISO::DirectoryRecordHeader m_record; ISO::DirectoryRecordHeader m_record;

View File

@ -115,7 +115,7 @@ ErrorOr<size_t> Inode::read_until_filled_or_end(off_t offset, size_t length, Use
return length - remaining_length; return length - remaining_length;
} }
ErrorOr<void> Inode::update_timestamps([[maybe_unused]] Optional<Duration> atime, [[maybe_unused]] Optional<Duration> ctime, [[maybe_unused]] Optional<Duration> mtime) ErrorOr<void> Inode::update_timestamps([[maybe_unused]] Optional<UnixDateTime> atime, [[maybe_unused]] Optional<UnixDateTime> ctime, [[maybe_unused]] Optional<UnixDateTime> mtime)
{ {
return ENOTIMPL; return ENOTIMPL;
} }

View File

@ -82,7 +82,7 @@ public:
bool is_metadata_dirty() const { return m_metadata_dirty; } bool is_metadata_dirty() const { return m_metadata_dirty; }
virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime); virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime);
virtual ErrorOr<void> increment_link_count(); virtual ErrorOr<void> increment_link_count();
virtual ErrorOr<void> decrement_link_count(); virtual ErrorOr<void> decrement_link_count();

View File

@ -120,10 +120,10 @@ struct InodeMetadata {
UserID uid { 0 }; UserID uid { 0 };
GroupID gid { 0 }; GroupID gid { 0 };
nlink_t link_count { 0 }; nlink_t link_count { 0 };
Duration atime {}; UnixDateTime atime {};
Duration ctime {}; UnixDateTime ctime {};
Duration mtime {}; UnixDateTime mtime {};
Duration dtime {}; UnixDateTime dtime {};
blkcnt_t block_count { 0 }; blkcnt_t block_count { 0 };
blksize_t block_size { 0 }; blksize_t block_size { 0 };
MajorNumber major_device { 0 }; MajorNumber major_device { 0 };

View File

@ -54,7 +54,7 @@ private:
// ^Inode (Silent ignore handling) // ^Inode (Silent ignore handling)
virtual ErrorOr<void> flush_metadata() override { return {}; } virtual ErrorOr<void> flush_metadata() override { return {}; }
virtual ErrorOr<void> update_timestamps(Optional<Duration>, Optional<Duration>, Optional<Duration>) override { return {}; } virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime>, Optional<UnixDateTime>, Optional<UnixDateTime>) override { return {}; }
// ^Inode // ^Inode
virtual ErrorOr<void> attach(OpenFileDescription& description) override; virtual ErrorOr<void> attach(OpenFileDescription& description) override;

View File

@ -381,7 +381,7 @@ ErrorOr<void> RAMFSInode::truncate(u64 size)
return {}; return {};
} }
ErrorOr<void> RAMFSInode::update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) ErrorOr<void> RAMFSInode::update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime)
{ {
MutexLocker locker(m_inode_lock); MutexLocker locker(m_inode_lock);

View File

@ -35,7 +35,7 @@ public:
virtual ErrorOr<void> chmod(mode_t) override; virtual ErrorOr<void> chmod(mode_t) override;
virtual ErrorOr<void> chown(UserID, GroupID) override; virtual ErrorOr<void> chown(UserID, GroupID) override;
virtual ErrorOr<void> truncate(u64) override; virtual ErrorOr<void> truncate(u64) override;
virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) override; virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
private: private:
RAMFSInode(RAMFS& fs, InodeMetadata const& metadata, LockWeakPtr<RAMFSInode> parent); RAMFSInode(RAMFS& fs, InodeMetadata const& metadata, LockWeakPtr<RAMFSInode> parent);

View File

@ -110,7 +110,7 @@ ErrorOr<void> SysFSInode::truncate(u64 size)
return m_associated_component->truncate(size); return m_associated_component->truncate(size);
} }
ErrorOr<void> SysFSInode::update_timestamps(Optional<Duration>, Optional<Duration>, Optional<Duration>) ErrorOr<void> SysFSInode::update_timestamps(Optional<UnixDateTime>, Optional<UnixDateTime>, Optional<UnixDateTime>)
{ {
return {}; return {};
} }

View File

@ -35,7 +35,7 @@ protected:
virtual ErrorOr<void> chmod(mode_t) override; virtual ErrorOr<void> chmod(mode_t) override;
virtual ErrorOr<void> chown(UserID, GroupID) override; virtual ErrorOr<void> chown(UserID, GroupID) override;
virtual ErrorOr<void> truncate(u64) override; virtual ErrorOr<void> truncate(u64) override;
virtual ErrorOr<void> update_timestamps(Optional<Duration> atime, Optional<Duration> ctime, Optional<Duration> mtime) override; virtual ErrorOr<void> update_timestamps(Optional<UnixDateTime> atime, Optional<UnixDateTime> ctime, Optional<UnixDateTime> mtime) override;
virtual ErrorOr<void> attach(OpenFileDescription& description) override final; virtual ErrorOr<void> attach(OpenFileDescription& description) override final;
virtual void did_seek(OpenFileDescription&, off_t) override final; virtual void did_seek(OpenFileDescription&, off_t) override final;

View File

@ -306,7 +306,7 @@ ErrorOr<void> VirtualFileSystem::utime(Credentials const& credentials, StringVie
if (custody->is_readonly()) if (custody->is_readonly())
return EROFS; return EROFS;
TRY(inode.update_timestamps(Duration::from_timespec({ atime, 0 }), {}, Duration::from_timespec({ mtime, 0 }))); TRY(inode.update_timestamps(UnixDateTime::from_seconds_since_epoch(atime), {}, UnixDateTime::from_seconds_since_epoch(mtime)));
return {}; return {};
} }
@ -326,9 +326,9 @@ ErrorOr<void> VirtualFileSystem::do_utimens(Credentials const& credentials, Cust
// NOTE: A standard ext2 inode cannot store nanosecond timestamps. // NOTE: A standard ext2 inode cannot store nanosecond timestamps.
TRY(inode.update_timestamps( TRY(inode.update_timestamps(
(atime.tv_nsec != UTIME_OMIT) ? Duration::from_timespec(atime) : Optional<Duration> {}, (atime.tv_nsec != UTIME_OMIT) ? UnixDateTime::from_unix_timespec(atime) : Optional<UnixDateTime> {},
{}, {},
(mtime.tv_nsec != UTIME_OMIT) ? Duration::from_timespec(mtime) : Optional<Duration> {})); (mtime.tv_nsec != UTIME_OMIT) ? UnixDateTime::from_unix_timespec(mtime) : Optional<UnixDateTime> {}));
return {}; return {};
} }

View File

@ -287,7 +287,7 @@ ErrorOr<size_t> IPv4Socket::receive_byte_buffered(OpenFileDescription& descripti
return nreceived_or_error; return nreceived_or_error;
} }
ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> addr, Userspace<socklen_t*> addr_length, Duration& packet_timestamp, bool blocking) ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> addr, Userspace<socklen_t*> addr_length, UnixDateTime& packet_timestamp, bool blocking)
{ {
MutexLocker locker(mutex()); MutexLocker locker(mutex());
ReceivedPacket taken_packet; ReceivedPacket taken_packet;
@ -382,7 +382,7 @@ ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& descrip
return protocol_receive(packet->data->bytes(), buffer, buffer_length, flags); return protocol_receive(packet->data->bytes(), buffer, buffer_length, flags);
} }
ErrorOr<size_t> IPv4Socket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> user_addr, Userspace<socklen_t*> user_addr_length, Duration& packet_timestamp, bool blocking) ErrorOr<size_t> IPv4Socket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> user_addr, Userspace<socklen_t*> user_addr_length, UnixDateTime& packet_timestamp, bool blocking)
{ {
if (user_addr_length) { if (user_addr_length) {
socklen_t addr_length; socklen_t addr_length;
@ -415,7 +415,7 @@ ErrorOr<size_t> IPv4Socket::recvfrom(OpenFileDescription& description, UserOrKer
return total_nreceived; return total_nreceived;
} }
bool IPv4Socket::did_receive(IPv4Address const& source_address, u16 source_port, ReadonlyBytes packet, Duration const& packet_timestamp) bool IPv4Socket::did_receive(IPv4Address const& source_address, u16 source_port, ReadonlyBytes packet, UnixDateTime const& packet_timestamp)
{ {
MutexLocker locker(mutex()); MutexLocker locker(mutex());

View File

@ -40,13 +40,13 @@ public:
virtual bool can_read(OpenFileDescription const&, u64) const override; virtual bool can_read(OpenFileDescription const&, u64) const override;
virtual bool can_write(OpenFileDescription const&, u64) const override; virtual bool can_write(OpenFileDescription const&, u64) const override;
virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override; virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override;
virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking) override; virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking) override;
virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t) override; virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t) override;
virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override; virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override;
virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override; virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override;
bool did_receive(IPv4Address const& peer_address, u16 peer_port, ReadonlyBytes, Duration const&); bool did_receive(IPv4Address const& peer_address, u16 peer_port, ReadonlyBytes, UnixDateTime const&);
IPv4Address const& local_address() const { return m_local_address; } IPv4Address const& local_address() const { return m_local_address; }
u16 local_port() const { return m_local_port; } u16 local_port() const { return m_local_port; }
@ -99,7 +99,7 @@ private:
virtual bool is_ipv4() const override { return true; } virtual bool is_ipv4() const override { return true; }
ErrorOr<size_t> receive_byte_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, bool blocking); ErrorOr<size_t> receive_byte_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, bool blocking);
ErrorOr<size_t> receive_packet_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking); ErrorOr<size_t> receive_packet_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking);
void set_can_read(bool); void set_can_read(bool);
@ -112,7 +112,7 @@ private:
struct ReceivedPacket { struct ReceivedPacket {
IPv4Address peer_address; IPv4Address peer_address;
u16 peer_port; u16 peer_port;
Duration timestamp; UnixDateTime timestamp;
OwnPtr<KBuffer> data; OwnPtr<KBuffer> data;
}; };

View File

@ -333,7 +333,7 @@ DoubleBuffer* LocalSocket::send_buffer_for(OpenFileDescription& description)
return nullptr; return nullptr;
} }
ErrorOr<size_t> LocalSocket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_size, int, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking) ErrorOr<size_t> LocalSocket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_size, int, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking)
{ {
auto* socket_buffer = receive_buffer_for(description); auto* socket_buffer = receive_buffer_for(description);
if (!socket_buffer) if (!socket_buffer)

View File

@ -47,7 +47,7 @@ public:
virtual bool can_read(OpenFileDescription const&, u64) const override; virtual bool can_read(OpenFileDescription const&, u64) const override;
virtual bool can_write(OpenFileDescription const&, u64) const override; virtual bool can_write(OpenFileDescription const&, u64) const override;
virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override; virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override;
virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking) override; virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking) override;
virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override; virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override;
virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override; virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override;
virtual ErrorOr<void> chown(Credentials const&, OpenFileDescription&, UserID, GroupID) override; virtual ErrorOr<void> chown(Credentials const&, OpenFileDescription&, UserID, GroupID) override;

View File

@ -95,7 +95,7 @@ void NetworkAdapter::did_receive(ReadonlyBytes payload)
on_receive(); on_receive();
} }
size_t NetworkAdapter::dequeue_packet(u8* buffer, size_t buffer_size, Duration& packet_timestamp) size_t NetworkAdapter::dequeue_packet(u8* buffer, size_t buffer_size, UnixDateTime& packet_timestamp)
{ {
InterruptDisabler disabler; InterruptDisabler disabler;
if (m_packet_queue.is_empty()) if (m_packet_queue.is_empty())

View File

@ -29,7 +29,7 @@ class NetworkAdapter;
using NetworkByteBuffer = AK::Detail::ByteBuffer<1500>; using NetworkByteBuffer = AK::Detail::ByteBuffer<1500>;
struct PacketWithTimestamp final : public AtomicRefCounted<PacketWithTimestamp> { struct PacketWithTimestamp final : public AtomicRefCounted<PacketWithTimestamp> {
PacketWithTimestamp(NonnullOwnPtr<KBuffer> buffer, Duration timestamp) PacketWithTimestamp(NonnullOwnPtr<KBuffer> buffer, UnixDateTime timestamp)
: buffer(move(buffer)) : buffer(move(buffer))
, timestamp(timestamp) , timestamp(timestamp)
{ {
@ -38,7 +38,7 @@ struct PacketWithTimestamp final : public AtomicRefCounted<PacketWithTimestamp>
ReadonlyBytes bytes() { return buffer->bytes(); } ReadonlyBytes bytes() { return buffer->bytes(); }
NonnullOwnPtr<KBuffer> buffer; NonnullOwnPtr<KBuffer> buffer;
Duration timestamp; UnixDateTime timestamp;
IntrusiveListNode<PacketWithTimestamp, RefPtr<PacketWithTimestamp>> packet_node; IntrusiveListNode<PacketWithTimestamp, RefPtr<PacketWithTimestamp>> packet_node;
}; };
@ -79,7 +79,7 @@ public:
void send(MACAddress const&, ARPPacket const&); void send(MACAddress const&, ARPPacket const&);
void fill_in_ipv4_header(PacketWithTimestamp&, IPv4Address const&, MACAddress const&, IPv4Address const&, IPv4Protocol, size_t, u8 type_of_service, u8 ttl); void fill_in_ipv4_header(PacketWithTimestamp&, IPv4Address const&, MACAddress const&, IPv4Address const&, IPv4Protocol, size_t, u8 type_of_service, u8 ttl);
size_t dequeue_packet(u8* buffer, size_t buffer_size, Duration& packet_timestamp); size_t dequeue_packet(u8* buffer, size_t buffer_size, UnixDateTime& packet_timestamp);
bool has_queued_packets() const { return !m_packet_queue.is_empty(); } bool has_queued_packets() const { return !m_packet_queue.is_empty(); }

View File

@ -26,10 +26,10 @@
namespace Kernel { namespace Kernel {
static void handle_arp(EthernetFrameHeader const&, size_t frame_size); static void handle_arp(EthernetFrameHeader const&, size_t frame_size);
static void handle_ipv4(EthernetFrameHeader const&, size_t frame_size, Duration const& packet_timestamp); static void handle_ipv4(EthernetFrameHeader const&, size_t frame_size, UnixDateTime const& packet_timestamp);
static void handle_icmp(EthernetFrameHeader const&, IPv4Packet const&, Duration const& packet_timestamp); static void handle_icmp(EthernetFrameHeader const&, IPv4Packet const&, UnixDateTime const& packet_timestamp);
static void handle_udp(IPv4Packet const&, Duration const& packet_timestamp); static void handle_udp(IPv4Packet const&, UnixDateTime const& packet_timestamp);
static void handle_tcp(IPv4Packet const&, Duration const& packet_timestamp); static void handle_tcp(IPv4Packet const&, UnixDateTime const& packet_timestamp);
static void send_delayed_tcp_ack(TCPSocket& socket); static void send_delayed_tcp_ack(TCPSocket& socket);
static void send_tcp_rst(IPv4Packet const& ipv4_packet, TCPPacket const& tcp_packet, RefPtr<NetworkAdapter> adapter); static void send_tcp_rst(IPv4Packet const& ipv4_packet, TCPPacket const& tcp_packet, RefPtr<NetworkAdapter> adapter);
static void flush_delayed_tcp_acks(); static void flush_delayed_tcp_acks();
@ -74,7 +74,7 @@ void NetworkTask_main(void*)
}; };
}); });
auto dequeue_packet = [&pending_packets](u8* buffer, size_t buffer_size, Duration& packet_timestamp) -> size_t { auto dequeue_packet = [&pending_packets](u8* buffer, size_t buffer_size, UnixDateTime& packet_timestamp) -> size_t {
if (pending_packets == 0) if (pending_packets == 0)
return 0; return 0;
size_t packet_size = 0; size_t packet_size = 0;
@ -94,7 +94,7 @@ void NetworkTask_main(void*)
TODO(); TODO();
auto buffer_region = region_or_error.release_value(); auto buffer_region = region_or_error.release_value();
auto buffer = (u8*)buffer_region->vaddr().get(); auto buffer = (u8*)buffer_region->vaddr().get();
Duration packet_timestamp; UnixDateTime packet_timestamp;
for (;;) { for (;;) {
flush_delayed_tcp_acks(); flush_delayed_tcp_acks();
@ -177,7 +177,7 @@ void handle_arp(EthernetFrameHeader const& eth, size_t frame_size)
} }
} }
void handle_ipv4(EthernetFrameHeader const& eth, size_t frame_size, Duration const& packet_timestamp) void handle_ipv4(EthernetFrameHeader const& eth, size_t frame_size, UnixDateTime const& packet_timestamp)
{ {
constexpr size_t minimum_ipv4_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet); constexpr size_t minimum_ipv4_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet);
if (frame_size < minimum_ipv4_frame_size) { if (frame_size < minimum_ipv4_frame_size) {
@ -222,7 +222,7 @@ void handle_ipv4(EthernetFrameHeader const& eth, size_t frame_size, Duration con
} }
} }
void handle_icmp(EthernetFrameHeader const& eth, IPv4Packet const& ipv4_packet, Duration const& packet_timestamp) void handle_icmp(EthernetFrameHeader const& eth, IPv4Packet const& ipv4_packet, UnixDateTime const& packet_timestamp)
{ {
auto& icmp_header = *static_cast<ICMPHeader const*>(ipv4_packet.payload()); auto& icmp_header = *static_cast<ICMPHeader const*>(ipv4_packet.payload());
dbgln_if(ICMP_DEBUG, "handle_icmp: source={}, destination={}, type={:#02x}, code={:#02x}", ipv4_packet.source().to_string(), ipv4_packet.destination().to_string(), icmp_header.type(), icmp_header.code()); dbgln_if(ICMP_DEBUG, "handle_icmp: source={}, destination={}, type={:#02x}, code={:#02x}", ipv4_packet.source().to_string(), ipv4_packet.destination().to_string(), icmp_header.type(), icmp_header.code());
@ -273,7 +273,7 @@ void handle_icmp(EthernetFrameHeader const& eth, IPv4Packet const& ipv4_packet,
} }
} }
void handle_udp(IPv4Packet const& ipv4_packet, Duration const& packet_timestamp) void handle_udp(IPv4Packet const& ipv4_packet, UnixDateTime const& packet_timestamp)
{ {
if (ipv4_packet.payload_size() < sizeof(UDPPacket)) { if (ipv4_packet.payload_size() < sizeof(UDPPacket)) {
dbgln("handle_udp: Packet too small ({}, need {})", ipv4_packet.payload_size(), sizeof(UDPPacket)); dbgln("handle_udp: Packet too small ({}, need {})", ipv4_packet.payload_size(), sizeof(UDPPacket));
@ -367,7 +367,7 @@ void send_tcp_rst(IPv4Packet const& ipv4_packet, TCPPacket const& tcp_packet, Re
routing_decision.adapter->release_packet_buffer(*packet); routing_decision.adapter->release_packet_buffer(*packet);
} }
void handle_tcp(IPv4Packet const& ipv4_packet, Duration const& packet_timestamp) void handle_tcp(IPv4Packet const& ipv4_packet, UnixDateTime const& packet_timestamp)
{ {
if (ipv4_packet.payload_size() < sizeof(TCPPacket)) { if (ipv4_packet.payload_size() < sizeof(TCPPacket)) {
dbgln("handle_tcp: IPv4 payload is too small to be a TCP packet ({}, need {})", ipv4_packet.payload_size(), sizeof(TCPPacket)); dbgln("handle_tcp: IPv4 payload is too small to be a TCP packet ({}, need {})", ipv4_packet.payload_size(), sizeof(TCPPacket));

View File

@ -245,7 +245,7 @@ ErrorOr<size_t> Socket::read(OpenFileDescription& description, u64, UserOrKernel
{ {
if (is_shut_down_for_reading()) if (is_shut_down_for_reading())
return 0; return 0;
Duration t {}; UnixDateTime t {};
return recvfrom(description, buffer, size, 0, {}, 0, t, description.is_blocking()); return recvfrom(description, buffer, size, 0, {}, 0, t, description.is_blocking());
} }

View File

@ -79,7 +79,7 @@ public:
virtual bool is_local() const { return false; } virtual bool is_local() const { return false; }
virtual bool is_ipv4() const { return false; } virtual bool is_ipv4() const { return false; }
virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int flags, Userspace<sockaddr const*>, socklen_t) = 0; virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int flags, Userspace<sockaddr const*>, socklen_t) = 0;
virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Duration&, bool blocking) = 0; virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, UnixDateTime&, bool blocking) = 0;
virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t); virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t);
virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>); virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>);

View File

@ -216,11 +216,11 @@ private:
u32 m_duplicate_acks { 0 }; u32 m_duplicate_acks { 0 };
u32 m_last_ack_number_sent { 0 }; u32 m_last_ack_number_sent { 0 };
Duration m_last_ack_sent_time; UnixDateTime m_last_ack_sent_time;
// FIXME: Make this configurable (sysctl) // FIXME: Make this configurable (sysctl)
static constexpr u32 maximum_retransmits = 5; static constexpr u32 maximum_retransmits = 5;
Duration m_last_retransmit_time; UnixDateTime m_last_retransmit_time;
u32 m_retransmit_attempts { 0 }; u32 m_retransmit_attempts { 0 };
// FIXME: Parse window size TCP option from the peer // FIXME: Parse window size TCP option from the peer

View File

@ -164,7 +164,7 @@ public:
static void timer_tick(RegisterState const& regs) static void timer_tick(RegisterState const& regs)
{ {
static Duration last_wakeup; static UnixDateTime last_wakeup;
auto now = kgettimeofday(); auto now = kgettimeofday();
constexpr auto ideal_interval = Duration::from_microseconds(1000'000 / OPTIMAL_PROFILE_TICKS_PER_SECOND_RATE); constexpr auto ideal_interval = Duration::from_microseconds(1000'000 / OPTIMAL_PROFILE_TICKS_PER_SECOND_RATE);
auto expected_wakeup = last_wakeup + ideal_interval; auto expected_wakeup = last_wakeup + ideal_interval;

View File

@ -635,7 +635,7 @@ ErrorOr<Process::ScopedDescriptionAllocation> Process::OpenFileDescriptions::all
return EMFILE; return EMFILE;
} }
Duration kgettimeofday() UnixDateTime kgettimeofday()
{ {
return TimeManagement::now(); return TimeManagement::now();
} }
@ -699,7 +699,7 @@ ErrorOr<void> Process::dump_core()
return {}; return {};
} }
auto coredump_path = TRY(name().with([&](auto& process_name) { auto coredump_path = TRY(name().with([&](auto& process_name) {
return KString::formatted("{}/{}_{}_{}", coredump_directory_path->view(), process_name->view(), pid().value(), kgettimeofday().to_truncated_seconds()); return KString::formatted("{}/{}_{}_{}", coredump_directory_path->view(), process_name->view(), pid().value(), kgettimeofday().seconds_since_epoch());
})); }));
auto coredump = TRY(Coredump::try_create(*this, coredump_path->view())); auto coredump = TRY(Coredump::try_create(*this, coredump_path->view()));
return coredump->write(); return coredump->write();

View File

@ -41,7 +41,7 @@
namespace Kernel { namespace Kernel {
MutexProtected<OwnPtr<KString>>& hostname(); MutexProtected<OwnPtr<KString>>& hostname();
Duration kgettimeofday(); UnixDateTime kgettimeofday();
#define ENUMERATE_PLEDGE_PROMISES \ #define ENUMERATE_PLEDGE_PROMISES \
__ENUMERATE_PLEDGE_PROMISE(stdio) \ __ENUMERATE_PLEDGE_PROMISE(stdio) \

View File

@ -44,7 +44,7 @@ ErrorOr<FlatPtr> Process::sys$clock_settime(clockid_t clock_id, Userspace<timesp
if (!credentials->is_superuser()) if (!credentials->is_superuser())
return EPERM; return EPERM;
auto time = TRY(copy_time_from_user(user_ts)); auto time = UnixDateTime::epoch() + TRY(copy_time_from_user(user_ts));
switch (clock_id) { switch (clock_id) {
case CLOCK_REALTIME: case CLOCK_REALTIME:
@ -110,9 +110,8 @@ ErrorOr<FlatPtr> Process::sys$adjtime(Userspace<timeval const*> user_delta, User
{ {
VERIFY_NO_PROCESS_BIG_LOCK(this); VERIFY_NO_PROCESS_BIG_LOCK(this);
if (user_old_delta) { if (user_old_delta) {
timespec old_delta_ts = TimeManagement::the().remaining_epoch_time_adjustment(); auto old_delta_duration = TimeManagement::the().remaining_epoch_time_adjustment();
timeval old_delta; auto old_delta = old_delta_duration.to_timeval();
timespec_to_timeval(old_delta_ts, old_delta);
TRY(copy_to_user(user_old_delta, &old_delta)); TRY(copy_to_user(user_old_delta, &old_delta));
} }
@ -123,8 +122,7 @@ ErrorOr<FlatPtr> Process::sys$adjtime(Userspace<timeval const*> user_delta, User
return EPERM; return EPERM;
auto delta = TRY(copy_time_from_user(user_delta)); auto delta = TRY(copy_time_from_user(user_delta));
// FIXME: Should use AK::Duration internally TimeManagement::the().set_remaining_epoch_time_adjustment(delta);
TimeManagement::the().set_remaining_epoch_time_adjustment(delta.to_timespec());
} }
return 0; return 0;

View File

@ -272,7 +272,7 @@ ErrorOr<FlatPtr> Process::sys$recvmsg(int sockfd, Userspace<struct msghdr*> user
return 0; return 0;
auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len)); auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len));
Duration timestamp {}; UnixDateTime timestamp {};
bool blocking = (flags & MSG_DONTWAIT) ? false : description->is_blocking(); bool blocking = (flags & MSG_DONTWAIT) ? false : description->is_blocking();
auto result = socket.recvfrom(*description, data_buffer, iovs[0].iov_len, flags, user_addr, user_addr_length, timestamp, blocking); auto result = socket.recvfrom(*description, data_buffer, iovs[0].iov_len, flags, user_addr, user_addr_length, timestamp, blocking);

View File

@ -19,7 +19,7 @@ ErrorOr<FlatPtr> Process::sys$utime(Userspace<char const*> user_path, size_t pat
if (user_buf) { if (user_buf) {
TRY(copy_from_user(&buf, user_buf)); TRY(copy_from_user(&buf, user_buf));
} else { } else {
auto now = kgettimeofday().to_truncated_seconds(); auto now = kgettimeofday().truncated_seconds_since_epoch();
// Not a bug! // Not a bug!
buf = { now, now }; buf = { now, now };
} }

View File

@ -80,7 +80,7 @@ void SlavePTY::on_master_write(UserOrKernelBuffer const& buffer, size_t size)
ErrorOr<size_t> SlavePTY::on_tty_write(UserOrKernelBuffer const& data, size_t size) ErrorOr<size_t> SlavePTY::on_tty_write(UserOrKernelBuffer const& data, size_t size)
{ {
m_time_of_last_write = kgettimeofday().to_truncated_seconds(); m_time_of_last_write = kgettimeofday();
return m_master->on_slave_write(data, size); return m_master->on_slave_write(data, size);
} }

View File

@ -21,7 +21,7 @@ public:
void on_master_write(UserOrKernelBuffer const&, size_t); void on_master_write(UserOrKernelBuffer const&, size_t);
unsigned index() const { return m_index; } unsigned index() const { return m_index; }
time_t time_of_last_write() const { return m_time_of_last_write; } UnixDateTime time_of_last_write() const { return m_time_of_last_write; }
virtual FileBlockerSet& blocker_set() override; virtual FileBlockerSet& blocker_set() override;
@ -45,7 +45,7 @@ private:
SlavePTY(NonnullRefPtr<MasterPTY>, unsigned index); SlavePTY(NonnullRefPtr<MasterPTY>, unsigned index);
NonnullRefPtr<MasterPTY> const m_master; NonnullRefPtr<MasterPTY> const m_master;
time_t m_time_of_last_write { 0 }; UnixDateTime m_time_of_last_write {};
unsigned m_index { 0 }; unsigned m_index { 0 };
mutable IntrusiveListNode<SlavePTY> m_list_node; mutable IntrusiveListNode<SlavePTY> m_list_node;

View File

@ -87,9 +87,9 @@ Duration TimeManagement::current_time(clockid_t clock_id) const
case CLOCK_MONOTONIC_RAW: case CLOCK_MONOTONIC_RAW:
return monotonic_time_raw(); return monotonic_time_raw();
case CLOCK_REALTIME: case CLOCK_REALTIME:
return epoch_time(TimePrecision::Precise); return epoch_time(TimePrecision::Precise).offset_to_epoch();
case CLOCK_REALTIME_COARSE: case CLOCK_REALTIME_COARSE:
return epoch_time(TimePrecision::Coarse); return epoch_time(TimePrecision::Coarse).offset_to_epoch();
default: default:
// Syscall entrypoint is missing a is_valid_clock_id(..) check? // Syscall entrypoint is missing a is_valid_clock_id(..) check?
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
@ -101,12 +101,13 @@ bool TimeManagement::is_system_timer(HardwareTimerBase const& timer) const
return &timer == m_system_timer.ptr(); return &timer == m_system_timer.ptr();
} }
void TimeManagement::set_epoch_time(Duration ts) void TimeManagement::set_epoch_time(UnixDateTime ts)
{ {
// FIXME: The interrupt disabler intends to enforce atomic update of epoch time and remaining adjustment,
// but that sort of assumption is known to break on SMP.
InterruptDisabler disabler; InterruptDisabler disabler;
// FIXME: Should use AK::Duration internally m_epoch_time = ts;
m_epoch_time = ts.to_timespec(); m_remaining_epoch_time_adjustment = {};
m_remaining_epoch_time_adjustment = { 0, 0 };
} }
Duration TimeManagement::monotonic_time(TimePrecision precision) const Duration TimeManagement::monotonic_time(TimePrecision precision) const
@ -147,16 +148,16 @@ Duration TimeManagement::monotonic_time(TimePrecision precision) const
return Duration::from_timespec({ (i64)seconds, (i32)ns }); return Duration::from_timespec({ (i64)seconds, (i32)ns });
} }
Duration TimeManagement::epoch_time(TimePrecision) const UnixDateTime TimeManagement::epoch_time(TimePrecision) const
{ {
// TODO: Take into account precision // TODO: Take into account precision
timespec ts; UnixDateTime time;
u32 update_iteration; u32 update_iteration;
do { do {
update_iteration = m_update1.load(AK::MemoryOrder::memory_order_acquire); update_iteration = m_update1.load(AK::MemoryOrder::memory_order_acquire);
ts = m_epoch_time; time = m_epoch_time;
} while (update_iteration != m_update2.load(AK::MemoryOrder::memory_order_acquire)); } while (update_iteration != m_update2.load(AK::MemoryOrder::memory_order_acquire));
return Duration::from_timespec(ts); return time;
} }
u64 TimeManagement::uptime_ms() const u64 TimeManagement::uptime_ms() const
@ -226,7 +227,7 @@ time_t TimeManagement::ticks_per_second() const
return m_time_keeper_timer->ticks_per_second(); return m_time_keeper_timer->ticks_per_second();
} }
Duration TimeManagement::boot_time() UnixDateTime TimeManagement::boot_time()
{ {
#if ARCH(X86_64) #if ARCH(X86_64)
return RTC::boot_time(); return RTC::boot_time();
@ -252,14 +253,14 @@ UNMAP_AFTER_INIT TimeManagement::TimeManagement()
if (ACPI::is_enabled()) { if (ACPI::is_enabled()) {
if (!ACPI::Parser::the()->x86_specific_flags().cmos_rtc_not_present) { if (!ACPI::Parser::the()->x86_specific_flags().cmos_rtc_not_present) {
RTC::initialize(); RTC::initialize();
m_epoch_time.tv_sec += boot_time().to_timespec().tv_sec; m_epoch_time += boot_time().offset_to_epoch();
} else { } else {
dmesgln("ACPI: RTC CMOS Not present"); dmesgln("ACPI: RTC CMOS Not present");
} }
} else { } else {
// We just assume that we can access RTC CMOS, if ACPI isn't usable. // We just assume that we can access RTC CMOS, if ACPI isn't usable.
RTC::initialize(); RTC::initialize();
m_epoch_time.tv_sec += boot_time().to_timespec().tv_sec; m_epoch_time += boot_time().offset_to_epoch();
} }
if (probe_non_legacy_hardware_timers) { if (probe_non_legacy_hardware_timers) {
if (!probe_and_set_x86_non_legacy_hardware_timers()) if (!probe_and_set_x86_non_legacy_hardware_timers())
@ -275,7 +276,7 @@ UNMAP_AFTER_INIT TimeManagement::TimeManagement()
#endif #endif
} }
Duration TimeManagement::now() UnixDateTime TimeManagement::now()
{ {
return s_the.ptr()->epoch_time(); return s_the.ptr()->epoch_time();
} }
@ -437,7 +438,8 @@ void TimeManagement::increment_time_since_boot_hpet()
m_seconds_since_boot = seconds_since_boot; m_seconds_since_boot = seconds_since_boot;
m_ticks_this_second = ticks_this_second; m_ticks_this_second = ticks_this_second;
// TODO: Apply m_remaining_epoch_time_adjustment // TODO: Apply m_remaining_epoch_time_adjustment
timespec_add(m_epoch_time, { (time_t)(delta_ns / 1000000000), (long)(delta_ns % 1000000000) }, m_epoch_time); timespec time_adjustment = { (time_t)(delta_ns / 1000000000), (long)(delta_ns % 1000000000) };
m_epoch_time += Duration::from_timespec(time_adjustment);
m_update1.store(update_iteration + 1, AK::MemoryOrder::memory_order_release); m_update1.store(update_iteration + 1, AK::MemoryOrder::memory_order_release);
@ -483,20 +485,16 @@ void TimeManagement::increment_time_since_boot()
// Compute time adjustment for adjtime. Let the clock run up to 1% fast or slow. // Compute time adjustment for adjtime. Let the clock run up to 1% fast or slow.
// That way, adjtime can adjust up to 36 seconds per hour, without time getting very jumpy. // That way, adjtime can adjust up to 36 seconds per hour, without time getting very jumpy.
// Once we have a smarter NTP service that also adjusts the frequency instead of just slewing time, maybe we can lower this. // Once we have a smarter NTP service that also adjusts the frequency instead of just slewing time, maybe we can lower this.
long NanosPerTick = 1'000'000'000 / m_time_keeper_timer->frequency(); long nanos_per_tick = 1'000'000'000 / m_time_keeper_timer->frequency();
time_t MaxSlewNanos = NanosPerTick / 100; time_t max_slew_nanos = nanos_per_tick / 100;
u32 update_iteration = m_update2.fetch_add(1, AK::MemoryOrder::memory_order_acquire); u32 update_iteration = m_update2.fetch_add(1, AK::MemoryOrder::memory_order_acquire);
// Clamp twice, to make sure intermediate fits into a long. auto slew_nanos = Duration::from_nanoseconds(
long slew_nanos = clamp(clamp(m_remaining_epoch_time_adjustment.tv_sec, (time_t)-1, (time_t)1) * 1'000'000'000 + m_remaining_epoch_time_adjustment.tv_nsec, -MaxSlewNanos, MaxSlewNanos); clamp(m_remaining_epoch_time_adjustment.to_nanoseconds(), -max_slew_nanos, max_slew_nanos));
timespec slew_nanos_ts; m_remaining_epoch_time_adjustment -= slew_nanos;
timespec_sub({ 0, slew_nanos }, { 0, 0 }, slew_nanos_ts); // Normalize tv_nsec to be positive.
timespec_sub(m_remaining_epoch_time_adjustment, slew_nanos_ts, m_remaining_epoch_time_adjustment);
timespec epoch_tick = { .tv_sec = 0, .tv_nsec = NanosPerTick }; m_epoch_time += Duration::from_nanoseconds(nanos_per_tick + slew_nanos.to_nanoseconds());
epoch_tick.tv_nsec += slew_nanos; // No need for timespec_add(), guaranteed to be in range.
timespec_add(m_epoch_time, epoch_tick, m_epoch_time);
if (++m_ticks_this_second >= m_time_keeper_timer->ticks_per_second()) { if (++m_ticks_this_second >= m_time_keeper_timer->ticks_per_second()) {
// FIXME: Synchronize with other clock somehow to prevent drifting apart. // FIXME: Synchronize with other clock somehow to prevent drifting apart.
@ -540,7 +538,7 @@ void TimeManagement::update_time_page()
{ {
auto& page = time_page(); auto& page = time_page();
u32 update_iteration = AK::atomic_fetch_add(&page.update2, 1u, AK::MemoryOrder::memory_order_acquire); u32 update_iteration = AK::atomic_fetch_add(&page.update2, 1u, AK::MemoryOrder::memory_order_acquire);
page.clocks[CLOCK_REALTIME_COARSE] = m_epoch_time; page.clocks[CLOCK_REALTIME_COARSE] = m_epoch_time.to_timespec();
page.clocks[CLOCK_MONOTONIC_COARSE] = monotonic_time(TimePrecision::Coarse).to_timespec(); page.clocks[CLOCK_MONOTONIC_COARSE] = monotonic_time(TimePrecision::Coarse).to_timespec();
AK::atomic_store(&page.update1, update_iteration + 1u, AK::MemoryOrder::memory_order_release); AK::atomic_store(&page.update1, update_iteration + 1u, AK::MemoryOrder::memory_order_release);
} }

View File

@ -48,10 +48,10 @@ public:
// TODO: implement // TODO: implement
return monotonic_time(TimePrecision::Precise); return monotonic_time(TimePrecision::Precise);
} }
Duration epoch_time(TimePrecision = TimePrecision::Precise) const; UnixDateTime epoch_time(TimePrecision = TimePrecision::Precise) const;
void set_epoch_time(Duration); void set_epoch_time(UnixDateTime);
time_t ticks_per_second() const; time_t ticks_per_second() const;
static Duration boot_time(); static UnixDateTime boot_time();
Duration clock_resolution() const; Duration clock_resolution() const;
bool is_system_timer(HardwareTimerBase const&) const; bool is_system_timer(HardwareTimerBase const&) const;
@ -64,14 +64,12 @@ public:
bool disable_profile_timer(); bool disable_profile_timer();
u64 uptime_ms() const; u64 uptime_ms() const;
static Duration now(); static UnixDateTime now();
// FIXME: Should use AK::Duration internally // FIXME: Most likely broken, because it does not check m_update[12] for in-progress updates.
// FIXME: Also, most likely broken, because it does not check m_update[12] for in-progress updates. Duration remaining_epoch_time_adjustment() const { return m_remaining_epoch_time_adjustment; }
timespec remaining_epoch_time_adjustment() const { return m_remaining_epoch_time_adjustment; } // FIXME: Most likely broken, because it does not check m_update[12] for in-progress updates.
// FIXME: Should use AK::Duration internally void set_remaining_epoch_time_adjustment(Duration adjustment) { m_remaining_epoch_time_adjustment = adjustment; }
// FIXME: Also, most likely broken, because it does not check m_update[12] for in-progress updates.
void set_remaining_epoch_time_adjustment(timespec const& adjustment) { m_remaining_epoch_time_adjustment = adjustment; }
bool can_query_precise_time() const { return m_can_query_precise_time; } bool can_query_precise_time() const { return m_can_query_precise_time; }
@ -102,9 +100,8 @@ private:
Atomic<u32> m_update1 { 0 }; Atomic<u32> m_update1 { 0 };
u32 m_ticks_this_second { 0 }; u32 m_ticks_this_second { 0 };
u64 m_seconds_since_boot { 0 }; u64 m_seconds_since_boot { 0 };
// FIXME: Should use AK::Duration internally UnixDateTime m_epoch_time {};
timespec m_epoch_time { 0, 0 }; Duration m_remaining_epoch_time_adjustment {};
timespec m_remaining_epoch_time_adjustment { 0, 0 };
Atomic<u32> m_update2 { 0 }; Atomic<u32> m_update2 { 0 };
u32 m_time_ticks_per_second { 0 }; // may be different from interrupts/second (e.g. hpet) u32 m_time_ticks_per_second { 0 }; // may be different from interrupts/second (e.g. hpet)

View File

@ -22,7 +22,7 @@
static ErrorOr<void> adjust_modification_time(Archive::ZipMember const& zip_member) static ErrorOr<void> adjust_modification_time(Archive::ZipMember const& zip_member)
{ {
auto time = time_from_packed_dos(zip_member.modification_date, zip_member.modification_time); auto time = time_from_packed_dos(zip_member.modification_date, zip_member.modification_time);
auto seconds = static_cast<time_t>(time.to_seconds()); auto seconds = static_cast<time_t>(time.seconds_since_epoch());
struct utimbuf buf { struct utimbuf buf {
.actime = seconds, .actime = seconds,
.modtime = seconds .modtime = seconds