Compare commits

..

35 Commits

Author SHA1 Message Date
Jonas 'Sortie' Termansen 70c5499709 Revert "Parallelize driver initialization."
This reverts commit 0fef08bbc4.
2023-04-03 00:22:20 +02:00
Jonas 'Sortie' Termansen 2ccbb69032 Aurora procedural wallpaper. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 49e25c1bd4 Work around pty deadlock. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen b9d8175545 Add cdrom mounting live environment. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 0fef08bbc4 Parallelize driver initialization. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen b304e34d56 Speed up ata(4) 400 ns waits.
Waiting for any non-zero duration currently waits for at least one timer
cycle (10 ms), which is especially expensive during early boot.

The current workaround of simply reading the status 14 times seems really
suspicious although the osdev wiki documents it, but let's see how well it
works on real hardware, it's probably good enough.

Try to determine the initial selected drive to save one drive selection.
2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 40e3432faf Decrease PS/2 timeouts. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 9ba552a1b5 Add uptime(1) -pr options. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 54f99f8269 Add iso9660 filesystem implementation. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 263a1ec1f1 Add kernel virtual address space usage debug information. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 2d8f7bc57a Revert "Update to bison-3.8.2."
This reverts commit b82fae810b42c5426d21c4dc153b32f086dd7fde.
2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 5948a2be00 Update to bison-3.8.2. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 2f36596b6d Debug TCP socket state listing. 2023-03-27 00:16:19 +02:00
Jonas 'Sortie' Termansen 7e0555f2c2 Add kernel heap allocation tracing debug facility. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 8730de52de Add m4, perl, and texinfo to the basic ports set. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 3eeab1d368 Trianglix 4. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 8990553795 Add tix-check(8). 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen fb76556f95 Add automatic installer and upgrader. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen d9aef1d8d9 Volatile release. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 72814b830c Add tix-upgrade(8). 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 4a455be70a Add display server. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 0305241095 Add pty(1). 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen ef75110afb Revert "Debug system calls exiting without interrupts enabled."
This reverts commit c0bc774c9aa8aa3834f40afc7ad5aa909afc61a1.
2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 0482958335 Debug system calls exiting without interrupts enabled. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen f6257155cc Add signify port. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen d93fb760d5 Add irc(1).
Co-authored-by: Juhani Krekelä <juhani@krekelä.fi>
2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen ee5f69c0c3 Add getaddrinfo(1). 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen bb570bbbf2 Add host(1). 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 42a8e34e80 Add nginx port. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 60471c9f52 Enable stack smash protection by default. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 4227cbfa94 Enable undefined behavior sanitization by default. 2023-03-27 00:16:18 +02:00
Jonas 'Sortie' Termansen 2799f04cad Add date(1) -drs options. 2023-03-27 00:06:33 +02:00
Jonas 'Sortie' Termansen e9e57dc9af Add ntpd port. 2023-03-27 00:06:33 +02:00
Jonas 'Sortie' Termansen 9033153c47 Add sub_leap_seconds(3) and add_leap_seconds(3).
Advertise leap seconds being counted via CLOCK_REALTIME_HAS_LEAP_SECONDS.
2023-03-27 00:06:33 +02:00
Jonas 'Sortie' Termansen 97c57ca604 Add strptime(3). 2023-03-22 00:16:15 +01:00
12 changed files with 444 additions and 249 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -37,6 +37,8 @@ extern "C" {
#define CLOCK_THREAD_CPUTIME_ID 8
#define CLOCK_THREAD_SYSTIME_ID 9
#define CLOCK_REALTIME_HAS_LEAP_SECONDS 1
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -32,7 +32,6 @@
#include <stdlib.h>
#include <string.h>
#include <sortix/clock.h>
#include <sortix/fcntl.h>
#include <sortix/mman.h>
#include <sortix/stat.h>
@ -429,70 +428,6 @@ static void SystemIdleThread(void* /*user*/)
}
}
kthread_mutex_t driver_threads_lock = KTHREAD_MUTEX_INITIALIZER;
kthread_cond_t driver_threads_cond = KTHREAD_COND_INITIALIZER;
size_t driver_threads_done = 0;
size_t driver_threads_total = 0;
// Parallelize the initialization of slow drivers.
static void RunDriverThread(void (*entry)(void*), void* user, const char* name)
{
kthread_mutex_lock(&driver_threads_lock);
driver_threads_total++;
kthread_mutex_unlock(&driver_threads_lock);
if ( !RunKernelThread(entry, user, name) )
PanicF("RunKernelThread: %s", name);
}
static void FinishedDriverThread()
{
ScopedLock lock(&driver_threads_lock);
driver_threads_done++;
kthread_cond_broadcast(&driver_threads_cond);
}
struct PS2ThreadCtx
{
PS2Keyboard* keyboard;
PS2Mouse* mouse;
};
static void PS2Thread(void* user)
{
struct PS2ThreadCtx* ctx = (struct PS2ThreadCtx*) user;
PS2::Init(ctx->keyboard, ctx->mouse);
FinishedDriverThread();
}
struct DevCtx
{
Ref<Descriptor> dev;
};
static void AHCIThread(void* user)
{
AHCI::Init("/dev", ((struct DevCtx*) user)->dev);
FinishedDriverThread();
}
static void ATAThread(void* user)
{
ATA::Init("/dev", ((struct DevCtx*) user)->dev);
FinishedDriverThread();
}
static void BGAThread(void* /*user*/)
{
BGA::Init();
FinishedDriverThread();
}
static void EMThread(void* user)
{
EM::Init("/dev", ((struct DevCtx*) user)->dev);
FinishedDriverThread();
}
static void BootThread(void* /*user*/)
{
//
@ -576,7 +511,6 @@ static void BootThread(void* /*user*/)
Ref<Descriptor> slashdev = droot->open(&ctx, "dev", O_READ | O_DIRECTORY);
if ( !slashdev )
Panic("Unable to create descriptor for RAM filesystem /dev directory.");
struct DevCtx dev_ctx = { slashdev };
// Initialize the keyboard.
PS2Keyboard* keyboard = new PS2Keyboard();
@ -594,8 +528,7 @@ static void BootThread(void* /*user*/)
Panic("Could not allocate PS2 Mouse driver");
// Initialize the PS/2 controller.
struct PS2ThreadCtx ps2_context = { keyboard, mouse };
RunDriverThread(PS2Thread, &ps2_context, "ps2");
PS2::Init(keyboard, mouse);
// Register /dev/tty as the current-terminal factory.
Ref<Inode> tty(new DevTTY(slashdev->dev, 0666, 0, 0));
@ -683,13 +616,13 @@ static void BootThread(void* /*user*/)
#endif
// Initialize AHCI devices.
RunDriverThread(AHCIThread, &dev_ctx, "ahci");
AHCI::Init("/dev", slashdev);
// Initialize ATA devices.
RunDriverThread(ATAThread, &dev_ctx, "ata");
ATA::Init("/dev", slashdev);
// Initialize the BGA driver.
RunDriverThread(BGAThread, NULL, "bga");
BGA::Init();
// Initialize the filesystem network.
NetFS::Init();
@ -711,15 +644,9 @@ static void BootThread(void* /*user*/)
{
// Initialize the EM driver.
if ( enable_em )
RunDriverThread(EMThread, &dev_ctx, "em");
EM::Init("/dev", slashdev);
}
// Await the drivers initialized in the background threads.
kthread_mutex_lock(&driver_threads_lock);
while ( driver_threads_done != driver_threads_total )
kthread_cond_wait(&driver_threads_cond, &driver_threads_lock);
kthread_mutex_unlock(&driver_threads_lock);
//
// Stage 6. Executing Hosted Environment ("User-Space")
//

View File

@ -780,6 +780,10 @@ scram/scram.2 \
sys/dnsconfig/getdnsconfig.2 \
sys/dnsconfig/setdnsconfig.2 \
MANPAGES3=\
time/add_leap_seconds.3 \
time/sub_leap_seconds.3 \
HEADERS:=$(shell find include -type f)
LIBK_OBJS:=$(FREEOBJS:.o=.libk.o)
@ -906,3 +910,5 @@ install-libs-kernel: $(INSTALLLIBSKERNEL)
install-man:
mkdir -p $(DESTDIR)$(MANDIR)/man2
cp $(MANPAGES2) $(DESTDIR)$(MANDIR)/man2
mkdir -p $(DESTDIR)$(MANDIR)/man3
cp $(MANPAGES3) $(DESTDIR)$(MANDIR)/man3

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen.
* Copyright (c) 2011, 2012, 2013, 2014, 2023 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -163,7 +163,9 @@ time_t timegm(struct tm*);
#if __USE_SORTIX
int clock_gettimeres(clockid_t, struct timespec*, struct timespec*);
int clock_settimeres(clockid_t, const struct timespec*, const struct timespec*);
int timens(struct tmns* tmns);
int timens(struct tmns*);
int sub_leap_seconds(time_t*);
int add_leap_seconds(time_t*);
#endif
extern char* tzname[2];

View File

@ -0,0 +1,104 @@
.Dd March 26, 2023
.Dt ADD_LEAP_SECONDS 2
.Os
.Sh NAME
.Nm add_leap_seconds ,
.Nm sub_leap_seconds
.Nd convert between utc and tai-10 timestamps
.Sh SYNOPSIS
.In time.h
.Ft int
.Fn add_leap_seconds "time_t *timestamp"
.Ft int
.Fn sub_leap_seconds "time_t *timestamp"
.Sh DESCRIPTION
.Fn add_leap_seconds
adds leap seconds to the UTC
.Fa timestamp
to give the corresponding TAI-10 timestamp.
.Pp
.Fn sub_leap_seconds
subtracts leap seconds from the TAI-10
.Fa timestamp
to give the corresponding UTC timestamp.
.Pp
Leap seconds are announced usually six months in advanced by the
International Earth Rotation and Reference Systems Service (IERS) in Bulletin C.
Leap seconds can be added or removed at the end of the June or December (UTC)
where the last minute can be 61 or 59 seconds.
Leap seconds correct the difference between solar time and civil time when
planetary rotation varies.
Leap seconds have never been removed as of mid 2023.
.Pp
.Dv CLOCK_REALTIME
on this system is in the TAI-10 format which measures the number of actual
seconds including leap seconds that has happened since the Unix epoch of
1970-01-01 00:00:00 UTC.
The inclusion of leap seconds is advertised by the
.Dv CLOCK_REALTIME_HAS_LEAP_SECONDS
definition.
This violates POSIX's requirement that
.Dv CLOCK_REALTIME
is in UTC, which pretends leap seconds don't happen.
The
.Fn add_leap_seconds
and
.Fn sub_leap_seconds
functions are useful when exchanging timestamps with other operating systems.
.Pp
TAI-10 is International Atomic Time (TAI) subtracted by 10 seconds so the epoch
is the same moment in TAI-10 and UTC.
.Pp
TAI-10 has the advantage that every actual past moment in time has an unique and
unambiguous and continuous representation.
The time difference between two TAI-10 timestamps can be calculated as a simple
subtraction.
Durations can be simply added to TAI-10 timestamps to produce the the timestamp
changed by that many seconds.
However it's not possible to compute which TAI10 timestamp corresponds to a
calendar date and time more than 6 months in the future, as the leap seconds
have not been announced yet.
The system leap second table needs to be up to date in order to perform properly
between TAI-10 and calendar time.
TAI-10 is the most useful format when dealing with relative times, as it's
guaranteed a certain amount of time has elapsed.
.Pp
UTC has the disadvantage that two different seconds can have the same timestamp
when leap seconds are removed, and UTC can be discontinuous if a leap second
removed where a timestamp could correspond to no actual moment in time.
The actual time between two UTC timestamps cannot be computed by a simple
subtraction (a leap second table is required) and durations cannot simply be
added to wait for a particular amount of time.
UTC is the most useful format when dealing with calendar times, as it's always
possible to losslessly convert UTC to and from calendar time.
.Sh RETURN VALUES
On success 1 is returned.
.Pp
0 is returned when the input timestamp has no representation in the output
format or is ambigous.
The output timestamp will be the best approximation.
This can happen in
.Fn sub_leap_seconds
when converting from TAI-10 to UTC and a leap second has been
inserted, or in
.Fn add_leap_seconds
when converting from UTC to TAI-10 and a leap second has been removed (which has
never happened so far).
.Pp
-1 is returned when the input timestamp is too far in the future and it is
unknown whether a leap second will occur.
The output timestamp will be the best approximation.
The accurate result can be obtained when the system leap second table has been
updated.
.Sh SEE ALSO
.Xr clock_gettime 2 ,
.Xr gmtime_r 3 ,
.Xr localtime_r 3 ,
.Xr mktime 3 ,
.Xr timegm 3
.Sh HISTORY
The
.Fn add_leap_seconds
and
.Fn sub_leap_seconds
functions originally appeared in Sortix 1.1.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -23,23 +23,25 @@
#include <stdint.h>
#include <time.h>
static const int DAYS_JANUARY = 31;
static const int DAYS_FEBRUARY = 28;
static const int DAYS_MARCH = 31;
static const int DAYS_APRIL = 30;
static const int DAYS_MAY = 31;
static const int DAYS_JUNE = 30;
static const int DAYS_JULY = 31;
static const int DAYS_AUGUST = 31;
static const int DAYS_SEPTEMBER = 30;
static const int DAYS_OCTOBER = 31;
static const int DAYS_NOVEMBER = 30;
static const int DAYS_DECEMBER = 31;
#define DAYS_JANUARY 31
#define DAYS_FEBRUARY 28
#define DAYS_MARCH 31
#define DAYS_APRIL 30
#define DAYS_MAY 31
#define DAYS_JUNE 30
#define DAYS_JULY 31
#define DAYS_AUGUST 31
#define DAYS_SEPTEMBER 30
#define DAYS_OCTOBER 31
#define DAYS_NOVEMBER 30
#define DAYS_DECEMBER 31
#define UNKNOWN 127
#define DECL_LEAP_SECOND(year, jun, dec) \
{0, 0, 0, 0, 0, jun, 0, 0, 0, 0, 0, dec}
static int8_t leap_seconds[][12] =
static const char leap_seconds[][12] =
{
DECL_LEAP_SECOND(1970, 0, 0),
DECL_LEAP_SECOND(1971, 0, 0),
@ -88,18 +90,47 @@ static int8_t leap_seconds[][12] =
DECL_LEAP_SECOND(2014, 0, 0),
DECL_LEAP_SECOND(2015, 1, 0),
DECL_LEAP_SECOND(2016, 0, 1),
DECL_LEAP_SECOND(2017, 0, 0),
DECL_LEAP_SECOND(2018, 0, 0),
DECL_LEAP_SECOND(2019, 0, 0),
DECL_LEAP_SECOND(2020, 0, 0),
DECL_LEAP_SECOND(2021, 0, 0),
DECL_LEAP_SECOND(2022, 0, 0),
DECL_LEAP_SECOND(2023, 0, UNKNOWN),
};
static time_t get_leap_second(int year, int month)
static const char month_days_list[12] =
{
DAYS_JANUARY,
DAYS_FEBRUARY,
DAYS_MARCH,
DAYS_APRIL,
DAYS_MAY,
DAYS_JUNE,
DAYS_JULY,
DAYS_AUGUST,
DAYS_SEPTEMBER,
DAYS_OCTOBER,
DAYS_NOVEMBER,
DAYS_DECEMBER,
};
static time_t get_leap_second_maybe(int year, int month)
{
const time_t num_years = sizeof(leap_seconds) / sizeof(leap_seconds[0]);
if ( year < 1970 )
return 0;
if ( num_years <= year-1970 )
return 0;
return UNKNOWN;
return leap_seconds[year-1970][month];
}
static time_t get_leap_second(int year, int month)
{
time_t result = get_leap_second_maybe(year, month);
return result == UNKNOWN ? 0 : result;
}
static time_t leap_seconds_in_year(int year)
{
time_t ret = 0;
@ -129,6 +160,11 @@ static time_t days_in_year(int year)
DAYS_DECEMBER;
}
static int days_in_month(int year, int month)
{
return month_days_list[month] + (month == 1 && is_leap_year(year));
}
struct tm* gmtime_r(const time_t* time_ptr, struct tm* ret)
{
time_t left = *time_ptr;
@ -165,29 +201,13 @@ struct tm* gmtime_r(const time_t* time_ptr, struct tm* ret)
ret->tm_wday = (ret->tm_wday - year_days + 7*7*7*7) % 7;
}
int month_days_list[12] =
{
DAYS_JANUARY,
DAYS_FEBRUARY + (is_leap_year(ret->tm_year) ? 1 : 0),
DAYS_MARCH,
DAYS_APRIL,
DAYS_MAY,
DAYS_JUNE,
DAYS_JULY,
DAYS_AUGUST,
DAYS_SEPTEMBER,
DAYS_OCTOBER,
DAYS_NOVEMBER,
DAYS_DECEMBER,
};
// Figure out the correct month.
ret->tm_mon = 0;
ret->tm_yday = 0;
while ( true )
{
int month_leaps = get_leap_second(ret->tm_year, ret->tm_mon);
int month_days = month_days_list[ret->tm_mon];
int month_days = days_in_month(ret->tm_year, ret->tm_mon);
int month_seconds = month_days * 24 * 60 * 60 + month_leaps;
if ( month_seconds <= left )
{
@ -204,7 +224,7 @@ struct tm* gmtime_r(const time_t* time_ptr, struct tm* ret)
left = left % (24 * 60 * 60);
// If this is a regular timestamp.
if ( ret->tm_mday < month_days_list[ret->tm_mon] )
if ( ret->tm_mday < days_in_month(ret->tm_year, ret->tm_mon) )
{
ret->tm_yday += ret->tm_mday;
@ -257,26 +277,10 @@ time_t timegm(struct tm* tm)
ret += year_seconds;
}
int month_days_list[12] =
{
DAYS_JANUARY,
DAYS_FEBRUARY + (is_leap_year(year) ? 1 : 0),
DAYS_MARCH,
DAYS_APRIL,
DAYS_MAY,
DAYS_JUNE,
DAYS_JULY,
DAYS_AUGUST,
DAYS_SEPTEMBER,
DAYS_OCTOBER,
DAYS_NOVEMBER,
DAYS_DECEMBER,
};
for ( uint8_t m = 0; m < month; m++ )
for ( int m = 0; m < month; m++ )
{
int month_leaps = get_leap_second(year, m);
int month_days = month_days_list[m];
int month_days = days_in_month(year, m);
int month_seconds = month_days * 24 * 60 * 60 + month_leaps;
ret += month_seconds;
}
@ -290,3 +294,58 @@ time_t timegm(struct tm* tm)
return ret;
}
int sub_leap_seconds(time_t* ptr)
{
time_t t = *ptr;
time_t next = 0;
time_t offset = 0;
for ( int year = 1970; true; year++ )
{
for ( int month = 0; month < 12; month++ )
{
time_t seconds = days_in_month(year, month) * 24 * 60 * 60;
time_t leap = get_leap_second_maybe(year, month);
next += seconds;
if ( leap == UNKNOWN )
{
*ptr = t - offset;
return t < next - 1 ? 1 : -1;
}
next += leap;
if ( t < next )
{
*ptr = t - offset;
return 0 < leap && t + 1 == next ? 0 : 1;
}
offset += leap;
}
}
}
int add_leap_seconds(time_t* ptr)
{
time_t t = *ptr;
time_t next = 0;
time_t offset = 0;
for ( int year = 1970; true; year++ )
{
for ( int month = 0; month < 12; month++ )
{
time_t seconds = days_in_month(year, month) * 24 * 60 * 60;
time_t leap = get_leap_second_maybe(year, month);
next += seconds;
if ( leap == UNKNOWN )
{
*ptr = t + offset;
return t < next - 1 ? 1 : -1;
}
if ( t < next )
{
*ptr = t + offset;
return leap < 0 && t + 1 == next ? 0 : 1;
}
offset += leap;
}
}
}

View File

@ -0,0 +1 @@
add_leap_seconds.3

View File

@ -127,9 +127,9 @@ diff -Paur --no-dereference -- nginx.upstream/auto/install nginx/auto/install
+
+ mkdir -p '\$(DESTDIR)$NGX_SYSCONFDIR/default/passwd.d'
+ mkdir -p '\$(DESTDIR)$NGX_SYSCONFDIR/default/group.d'
+ echo "_nginx:x:100:100:_nginx:/var/empty:sh" \\
+ echo "_nginx:x:101:101:_nginx:/var/empty:sh" \\
+ > '\$(DESTDIR)$NGX_SYSCONFDIR/default/passwd.d/nginx'
+ echo "_nginx::100:_nginx" \\
+ echo "_nginx::101:_nginx" \\
+ > '\$(DESTDIR)$NGX_SYSCONFDIR/default/group.d/nginx'
END

View File

@ -80,9 +80,9 @@ diff -Paur --no-dereference -- ntpd.upstream/Makefile.in ntpd/Makefile.in
+ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/default"
+ $(INSTALL) -m 644 "$(srcdir)/ntpd.conf" "$(DESTDIR)$(sysconfdir)/default/ntpd.conf"
+ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/default/passwd.d"
+ echo "_ntp:x:101:101:_ntp:/var/empty:sh" > "$(DESTDIR)$(sysconfdir)/default/passwd.d/ntpd"
+ echo "_ntp:x:100:100:_ntp:/var/empty:sh" > "$(DESTDIR)$(sysconfdir)/default/passwd.d/ntpd"
+ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/default/group.d"
+ echo "_ntp::101:_ntp" > "$(DESTDIR)$(sysconfdir)/default/group.d/ntpd"
+ echo "_ntp::100:_ntp" > "$(DESTDIR)$(sysconfdir)/default/group.d/ntpd"
uninstall-local:
- @if cmp -s "$(DESTDIR)$(sysconfdir)/ntpd.conf" "$(srcdir)/ntpd.conf"; then \
@ -134,7 +134,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/client.c ntpd/src/client.c
interval = error_interval();
set_next(p, interval);
- log_info("reply from %s: negative delay %fs, "
+ log_info("reply from %s: negative delay %llims, "
+ log_info("reply from %s: negative delay %lldms, "
"next query %llds",
log_sockaddr((struct sockaddr *)&p->addr->ss),
- p->reply[p->shift].delay, (long long)interval);
@ -148,7 +148,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/client.c ntpd/src/client.c
interval = scale_interval(INTERVAL_QUERY_NORMAL);
- log_debug("reply from %s: offset %f delay %f, "
+ log_debug("reply from %s: offset %llims delay %llims, "
+ log_debug("reply from %s: offset %lldms delay %lldms, "
"next query %llds",
log_sockaddr((struct sockaddr *)&p->addr->ss),
- offset, delay,
@ -198,13 +198,27 @@ diff -Paur --no-dereference -- ntpd.upstream/src/constraint.c ntpd/src/constrain
gettime_from_timeval(&tv[1]);
- log_info("constraint reply from %s: offset %f",
+ log_info("constraint reply from %s: offset %lli ms",
+ log_info("constraint reply from %s: offset %lld ms",
log_sockaddr((struct sockaddr *)&cstr->addr->ss),
- offset);
+ (long long)(offset * 1000));
cstr->state = STATE_REPLY_RECEIVED;
cstr->last = getmonotime();
@@ -1095,6 +1100,13 @@
/* Return parsed date as local time */
t = timegm(&httpsdate->tls_tm);
+ /* PATCH: Adjust for leap seconds in Sortix CLOCK_REALTIME. */
+#ifdef CLOCK_REALTIME_HAS_LEAP_SECONDS
+ if (!sub_leap_seconds(&t) || !sub_leap_seconds(&when.tv_sec)) {
+ return (NULL); /* Ignore during added leap second. */
+ }
+#endif
+
/* Report parsed Date: as "received time" */
rectv->tv_sec = t;
rectv->tv_usec = 0;
diff -Paur --no-dereference -- ntpd.upstream/src/control.c ntpd/src/control.c
--- ntpd.upstream/src/control.c
+++ ntpd/src/control.c
@ -233,10 +247,8 @@ diff -Paur --no-dereference -- ntpd.upstream/src/control.c ntpd/src/control.c
diff -Paur --no-dereference -- ntpd.upstream/src/init/ntpd ntpd/src/init/ntpd
--- ntpd.upstream/src/init/ntpd
+++ ntpd/src/init/ntpd
@@ -0,0 +1,4 @@
@@ -0,0 +1,2 @@
+require network
+#program=ntpd
+#exec $program -d
+exec ntpd -d
diff -Paur --no-dereference -- ntpd.upstream/src/Makefile.in ntpd/src/Makefile.in
--- ntpd.upstream/src/Makefile.in
@ -336,7 +348,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntp.c ntpd/src/ntp.c
diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
--- ntpd.upstream/src/ntpd.c
+++ ntpd/src/ntpd.c
@@ -45,6 +45,107 @@
@@ -45,6 +45,53 @@
#include "ntpd.h"
@ -364,60 +376,6 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
+ return 0;
+}
+
+/*
+From musl:
+
+Copyright © 2005-2014 Rich Felker, et al.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+int daemon(int nochdir, int noclose)
+{
+ if (!nochdir && chdir("/"))
+ return -1;
+ if (!noclose) {
+ int fd, failed = 0;
+ if ((fd = open("/dev/null", O_RDWR)) < 0) return -1;
+ if (dup2(fd, 0) < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0)
+ failed++;
+ if (fd > 2) close(fd);
+ if (failed) return -1;
+ }
+
+ switch(fork()) {
+ case 0: break;
+ case -1: return -1;
+ default: _exit(0);
+ }
+
+ if (setsid() < 0) return -1;
+
+ switch(fork()) {
+ case 0: break;
+ case -1: return -1;
+ default: _exit(0);
+ }
+
+ return 0;
+}
+
+int
+adjfreq(const int64_t *freq, int64_t *oldfreq)
+{
@ -444,7 +402,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
void sighdlr(int);
__dead void usage(void);
int auto_preconditions(const struct ntpd_conf *);
@@ -70,6 +171,7 @@
@@ -70,6 +117,7 @@
volatile sig_atomic_t sigchld = 0;
struct imsgbuf *ibuf;
int timeout = INFTIM;
@ -452,7 +410,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
extern u_int constraint_cnt;
@@ -108,6 +210,17 @@
@@ -108,6 +156,17 @@
}
}
@ -470,7 +428,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
__dead void
usage(void)
{
@@ -176,7 +289,10 @@
@@ -176,7 +235,10 @@
/* NOTREACHED */
}
@ -482,7 +440,7 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
memset(&lconf, 0, sizeof(lconf));
@@ -222,6 +338,12 @@
@@ -222,6 +284,12 @@
}
}
@ -495,34 +453,63 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
/* log to stderr until daemonized */
logdest = LOG_TO_STDERR;
if (!lconf.debug)
@@ -335,6 +457,10 @@
if (pledge("stdio rpath inet settime proc exec id", NULL) == -1)
err(1, "pledge");
+ if (!lconf.settime) {
+ ready();
+ }
+
while (quit == 0) {
new_cnt = PFD_MAX + constraint_cnt;
if (new_cnt > pfd_elms) {
@@ -380,6 +506,7 @@
@@ -287,11 +355,13 @@
logdest = lconf.debug ? LOG_TO_STDERR : LOG_TO_SYSLOG;
if (!lconf.settime) {
log_init(logdest, lconf.verbose, LOG_DAEMON);
+#if 0 /* PATCH: Modern daemons must not background. */
if (!lconf.debug) {
if (daemon(1, 0))
fatal("daemon");
writepid(&lconf);
}
+#endif
} else {
settime_deadline = getmonotime();
timeout = 100;
@@ -375,11 +445,14 @@
log_init(logdest, lconf.verbose, LOG_DAEMON);
log_warnx("no reply received in time, skipping initial "
"time setting");
+#if 0
if (!lconf.debug) {
if (daemon(1, 0))
fatal("daemon");
writepid(&lconf);
}
+#endif
+ ready();
}
if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT))
@@ -487,6 +614,7 @@
@@ -473,20 +546,25 @@
case IMSG_SETTIME:
if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
fatalx("invalid IMSG_SETTIME received");
- if (!lconf->settime)
+ if (!lconf->settime) {
+ ready();
break;
+ }
log_init(lconf->debug ? LOG_TO_STDERR : LOG_TO_SYSLOG,
lconf->verbose, LOG_DAEMON);
memcpy(&d, imsg.data, sizeof(d));
ntpd_settime(d);
+#if 0
/* daemonize now */
if (!lconf->debug) {
if (daemon(1, 0))
fatal("daemon");
writepid(lconf);
}
+#endif
lconf->settime = 0;
timeout = INFTIM;
+ ready();
break;
case IMSG_CONSTRAINT_QUERY:
priv_constraint_msg(imsg.hdr.peerid,
@@ -507,9 +635,8 @@
@@ -507,9 +585,8 @@
void
reset_adjtime(void)
{
@ -533,25 +520,52 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
if (adjtime(&tv, NULL) == -1)
log_warn("reset adjtime failed");
}
@@ -523,9 +650,9 @@
@@ -523,9 +600,9 @@
d += getoffset();
if (d >= threshold || d <= -1 * threshold)
- log_info("adjusting local clock by %fs", d);
+ log_info("adjusting local clock by %llims", (long long)(d * 1000));
+ log_info("adjusting local clock by %lldms", (long long)(d * 1000));
else
- log_debug("adjusting local clock by %fs", d);
+ log_debug("adjusting local clock by %llims", (long long)(d * 1000));
+ log_debug("adjusting local clock by %lldms", (long long)(d * 1000));
#ifdef HAVE_ADJTIMEX
int rc;
@@ -614,14 +741,26 @@
@@ -582,12 +659,12 @@
if (wrlog) {
if (ppmfreq >= LOG_NEGLIGIBLE_ADJFREQ ||
ppmfreq <= -LOG_NEGLIGIBLE_ADJFREQ)
- log_info("adjusting clock frequency by %f to %fppm%s",
- ppmfreq, curfreq / 1e3 / (1LL << 32),
+ log_info("adjusting clock frequency by %lld to %lldppm%s",
+ (long long)ppmfreq, (long long)(curfreq / 1e3 / (1LL << 32)),
r ? "" : " (no drift file)");
else
- log_debug("adjusting clock frequency by %f to %fppm%s",
- ppmfreq, curfreq / 1e3 / (1LL << 32),
+ log_debug("adjusting clock frequency by %lld to %lldppm%s",
+ (long long)ppmfreq, (long long)(curfreq / 1e3 / (1LL << 32)),
r ? "" : " (no drift file)");
}
@@ -610,18 +687,36 @@
return;
}
d_to_tv(d, &tv);
+#ifdef CLOCK_REALTIME_HAS_LEAP_SECONDS
+ if (!add_leap_seconds(&tv.tv_sec)) {
+ /* You finally, really did it. You maniacs! You blew it up! God damn
+ you. God damn you all to hell. */
+ return; /* Removed leap seconds have no representation here. */
+ }
+#endif
curtime.tv_usec += tv.tv_usec + 1000000;
curtime.tv_sec += tv.tv_sec - 1 + (curtime.tv_usec / 1000000);
curtime.tv_usec %= 1000000;
+#if defined(__sortix__)
+ struct timespec ts =
+ {
+ struct timespec ts = {
+ .tv_sec = curtime.tv_sec,
+ .tv_nsec = curtime.tv_usec * 1000
+ };
@ -569,38 +583,60 @@ diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.c ntpd/src/ntpd.c
strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y",
localtime(&tval));
- log_info("set local clock to %s (offset %fs)", buf, d);
+ log_info("set local clock to %s (offset %llims)", buf, (long long)(d * 1000.0));
+ log_info("set local clock to %s (offset %lldms)", buf, (long long)(d * 1000.0));
}
static FILE *freqfp;
@@ -632,6 +771,7 @@
@@ -632,6 +727,7 @@
int64_t current;
int fd;
double d;
+ long long lli;
+ long long lld;
fd = open(DRIFTFILE, O_RDWR);
if (fd == -1) {
@@ -649,7 +789,8 @@
@@ -649,7 +745,8 @@
if (adjfreq(NULL, &current) == -1)
log_warn("adjfreq failed");
else if (current == 0 && freqfp) {
- if (fscanf(freqfp, "%lf", &d) == 1) {
+ if (fscanf(freqfp, "%lli", &lli) == 1) {
+ d = (double)lli;
+ if (fscanf(freqfp, "%lld", &lld) == 1) {
+ d = (double)lld;
d /= 1e6; /* scale from ppm */
ntpd_adjfreq(d, 0);
} else
@@ -667,7 +808,8 @@
@@ -667,7 +764,8 @@
if (freqfp == NULL)
return 0;
rewind(freqfp);
- r = fprintf(freqfp, "%.3f\n", d * 1e6); /* scale to ppm */
+ long long lli = (long long)(d * 1e6);
+ r = fprintf(freqfp, "%lli\n", lli); /* scale to ppm */
+ long long lld = (long long)(d * 1e6);
+ r = fprintf(freqfp, "%lld\n", lld); /* scale to ppm */
if (r < 0 || fflush(freqfp) != 0) {
if (warnonce) {
log_warnx("can't write %s", DRIFTFILE);
@@ -901,8 +999,8 @@
clock_offset = cstatus->clock_offset < 0 ?
-1.0 * cstatus->clock_offset : cstatus->clock_offset;
if (clock_offset > 5e-7)
- printf(", clock offset is %.3fms\n",
- cstatus->clock_offset);
+ printf(", clock offset is %lldms\n",
+ (long long)cstatus->clock_offset);
else
printf("\n");
}
@@ -952,8 +1050,8 @@
(long long)cpeer->next, (long long)cpeer->poll);
if (cpeer->trustlevel >= TRUSTLEVEL_BADPEER)
- printf(" %12.3fms %9.3fms %8.3fms\n", cpeer->offset,
- cpeer->delay, cpeer->jitter);
+ printf(" %12lldms %9lldms %8lldms\n", (long long)cpeer->offset,
+ (long long)cpeer->delay, (long long)cpeer->jitter);
else
printf(" ---- peer not valid ----\n");
diff -Paur --no-dereference -- ntpd.upstream/src/ntpd.h ntpd/src/ntpd.h
--- ntpd.upstream/src/ntpd.h
+++ ntpd/src/ntpd.h
@ -794,12 +830,21 @@ diff -Paur --no-dereference -- ntpd.upstream/src/util.c ntpd/src/util.c
double
gettime_corrected(void)
{
diff -Paur --no-dereference -- ntpd.upstream/TODO.sortix ntpd/TODO.sortix
--- ntpd.upstream/TODO.sortix
+++ ntpd/TODO.sortix
@@ -0,0 +1,5 @@
+- nptd is unaware of leap seconds but Sortix is aware of them to the clock doesn't actually get synced correctly.
+- Sortix needs `adjtime` or the time adjustments can be jarring.
+- Sortix needs `strptime`.
+- Sortix needs `getservbyname` but worked around by hard-coding the ntp port.
+- The dns process wasn't being properly killed and awaited when exiting.
@@ -48,6 +50,17 @@
if (gettimeofday(&tv, NULL) == -1)
fatal("gettimeofday");
+/* PATCH: Sortix counts leap seconds in CLOCK_REALTIME but ntpd doesn't measure
+ leap seconds. Subtract them from the internal time to be UTC. */
+#ifdef CLOCK_REALTIME_HAS_LEAP_SECONDS
+ while (!sub_leap_seconds(&tv.tv_sec)) {
+ /* UTC cannot represent the current second because a leap second is
+ being inserted right now. Wait for it to pass and ignore it. */
+ sleep(1);
+ gettimeofday(&tv, NULL);
+ }
+#endif
+
return (gettime_from_timeval(&tv));
}

View File

@ -9,5 +9,4 @@ UPSTREAM_SITE=https://ftp.openbsd.org/pub/OpenBSD/OpenNTPD
UPSTREAM_ARCHIVE=$ARCHIVE
BUILD_SYSTEM=configure
MAKE_VARS='V=1'
POST_INSTALL=tix-eradicate-libtool-la
VERSION_REGEX='([0-9]+\.[0-9]+p[0-9]+)'

View File

@ -271,6 +271,17 @@ and such.
.Dv CLOCK_REALTIME
counts the number of seconds since the epoch including leap seconds, unlike
other operating systems and in violation of POSIX.
.Dv CLOCK_REALTIME_HAS_LEAP_SECONDS
definition advertises
.Dv CLOCK_REALTIME
contains leap seconds since the epoch in the TAI-10 format.
.Pp
.Xr sub_leap_seconds 3
converts timestamps from TAI-10 to UTC by subtracting the leap seconds, while
.Xr add_leap_seconds 3
converts timestamps from UTC TO TAI-10 by adding the leap seconds.
These functions are useful when communicating with other operating systems
either via the network or exchanged data files.
.Ss u_char, u_short, u_int, u_long
.Vt unsigned char ,
.Vt unsigned short ,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2021 Jonas 'Sortie' Termansen.
* Copyright (c) 2013, 2021, 2023 Jonas 'Sortie' Termansen.
* Copyright (c) 2022 Juhani 'nortti' Krekelä.
* Copyright (c) 2022 Dennis Wölfing.
*
@ -19,6 +19,8 @@
* Print or set system date and time.
*/
#include <sys/stat.h>
#include <err.h>
#include <stdbool.h>
#include <stdint.h>
@ -50,13 +52,18 @@ static char* astrftime(const char* format, const struct tm* tm)
int main(int argc, char* argv[])
{
const char* format = "+%a %b %e %H:%M:%S %Z %Y";
const char* date = NULL;
bool set = false;
const char* reference = NULL;
int opt;
while ( (opt = getopt(argc, argv, "u")) != -1 )
while ( (opt = getopt(argc, argv, "d:r:s:u")) != -1 )
{
switch ( opt )
{
case 'd': date = optarg; break;
case 'r': reference = optarg; break;
case 's': date = optarg; set = true; break;
case 'u':
if ( setenv("TZ", "UTC0", 1) )
err(1, "setenv");
@ -65,20 +72,52 @@ int main(int argc, char* argv[])
}
}
if ( date && reference )
errx(1, "the -d and -r options are mutually incompatible");
if ( set && reference )
errx(1, "the -s and -r options are mutually incompatible");
const char* format = "+%a %b %e %H:%M:%S %Z %Y";
if ( 1 <= argc - optind )
{
if ( argv[optind][0] != '+' )
errx(1, "setting the system time is not implemented");
errx(1, "the format specifier must start with a +");
format = argv[optind];
}
if ( 2 <= argc - optind )
errx(1, "unexpected extra operand: %s", argv[optind + 1]);
time_t current_time = time(NULL);
struct timespec moment = {0};
struct tm tm = {0};
struct tm tm;
if ( !localtime_r(&current_time, &tm) )
err(1, "localtime_r(%ji)", (intmax_t) current_time);
if ( date )
{
memset(&tm, 0, sizeof(tm));
if ( !strptime(date, format + 1, &tm) )
errx(1, "date didn't match %s: %s", format + 1, date);
moment.tv_sec = timegm(&tm); // TODO: timelocal
}
else
{
if ( reference )
{
struct stat st;
if ( stat(reference, &st) < 0 )
err(1, "%s", reference);
moment = st.st_mtim;
}
else
clock_gettime(CLOCK_REALTIME, &moment);
if ( !localtime_r(&moment.tv_sec, &tm) )
err(1, "localtime_r(%ji)", (intmax_t) moment.tv_sec);
}
if ( set )
{
if ( clock_settime(CLOCK_REALTIME, &moment) < 0 )
err(1, "clock_settime: CLOCK_REALTIME");
return 0;
}
char* string = astrftime(format, &tm);
if ( !string )