diff --git a/lib/libsys/clock_gettime.2 b/lib/libsys/clock_gettime.2 --- a/lib/libsys/clock_gettime.2 +++ b/lib/libsys/clock_gettime.2 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 28, 2024 +.Dd August 10, 2024 .Dt CLOCK_GETTIME 2 .Os .Sh NAME @@ -99,6 +99,15 @@ Returns the execution time of the calling process. .It Dv CLOCK_THREAD_CPUTIME_ID Returns the execution time of the calling thread. +.It Dv CLOCK_TAI +Increments in SI seconds like a wall clock. +It uses a 1970 epoch and implements the TAI timescale. +Unlike CLOCK_REALTIME, does not include leap seconds. +Behavior during a leap second is not defined and depends on the underlying +system clock implementation. +Will return EINVAL if the current offset between TAI and UTC is not known, +which may be the case early in boot before NTP or other time daemon has not +yet synchronized. .El .Pp The clock IDs diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c --- a/sys/kern/kern_ntptime.c +++ b/sys/kern/kern_ntptime.c @@ -153,7 +153,8 @@ static int time_state = TIME_OK; /* clock state */ int time_status = STA_UNSYNC; /* clock status bits */ -static long time_tai; /* TAI offset (s) */ +long time_tai; /* TAI offset (s) */ +bool time_tai_set = false; /* Whether time_tai has been set */ static long time_monitor; /* last time offset scaled (ns) */ static long time_constant; /* poll interval (shift) (s) */ static long time_precision = 1; /* clock precision (ns) */ @@ -388,8 +389,10 @@ time_constant = ntv->constant; } if (modes & MOD_TAI) { - if (ntv->constant > 0) /* XXX zero & negative numbers ? */ + if (ntv->constant > 0) { /* XXX zero & negative numbers ? */ time_tai = ntv->constant; + time_tai_set = true; + } } #ifdef PPS_SYNC if (modes & MOD_PPSMAX) { diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -1038,6 +1038,8 @@ /* Internal NTP status and error estimates. */ extern int time_status; extern long time_esterror; +extern long time_tai; +extern bool time_tai_set; /* * Take a snapshot of sysclock data which can be used to compare system clocks @@ -1139,6 +1141,11 @@ getboottimebin(&boottimebin); bintime_add(bt, &boottimebin); } + if (!(flags & FBCLOCK_LEAPSEC)) { + if (time_tai == 0) + return (EINVAL); + bt->sec += time_tai; + } break; #ifdef FFCLOCK case SYSCLOCK_FFWD: diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -318,7 +319,10 @@ kern_clock_gettime(struct thread *td, clockid_t clock_id, struct timespec *ats) { struct timeval sys, user; + struct sysclock_snap clk; + struct bintime bt; struct proc *p; + int err; p = td->td_proc; switch (clock_id) { @@ -329,6 +333,14 @@ case CLOCK_REALTIME_FAST: getnanotime(ats); break; + case CLOCK_TAI: + sysclock_getsnapshot(&clk, 0); + err = sysclock_snap2bintime(&clk, &bt, clk.sysclock_active, + (clk.sysclock_active == SYSCLOCK_FFWD) ? FFCLOCK_LERP : 0); + if (err) + return (err); + bintime2timespec(&bt, ats); + break; case CLOCK_VIRTUAL: PROC_LOCK(p); PROC_STATLOCK(p); diff --git a/sys/sys/_clock_id.h b/sys/sys/_clock_id.h --- a/sys/sys/_clock_id.h +++ b/sys/sys/_clock_id.h @@ -74,6 +74,10 @@ #define CLOCK_PROCESS_CPUTIME_ID 15 #endif /* __POSIX_VISIBLE >= 199309 */ +#ifdef __BSD_VISIBLE +#define CLOCK_TAI 16 +#endif + /* * Linux compatible names. */ diff --git a/sys/sys/timeffc.h b/sys/sys/timeffc.h --- a/sys/sys/timeffc.h +++ b/sys/sys/timeffc.h @@ -89,7 +89,7 @@ * of the kernel tick timer (1/hz [s]). * FFCLOCK_LERP: Linear interpolation of ffclock time to guarantee * monotonic time. - * FFCLOCK_LEAPSEC: Include leap seconds. + * {FB|FF}CLOCK_LEAPSEC: Include leap seconds. * {FB|FF}CLOCK_UPTIME: Time stamp should be relative to system boot, not epoch. */ #define FFCLOCK_FAST 0x00000001 @@ -100,6 +100,7 @@ #define FBCLOCK_FAST 0x00010000 /* Currently unused. */ #define FBCLOCK_UPTIME 0x00020000 +#define FBCLOCK_LEAPSEC 0x00040000 #define FBCLOCK_MASK 0xffff0000 /*