Page MenuHomeFreeBSD

D46268.diff
No OneTemporary

D46268.diff

diff --git a/lib/libsys/_umtx_op.2 b/lib/libsys/_umtx_op.2
--- a/lib/libsys/_umtx_op.2
+++ b/lib/libsys/_umtx_op.2
@@ -210,6 +210,8 @@
.It
.Dv CLOCK_SECOND
.It
+.Dv CLOCK_TAI
+.It
.Dv CLOCK_UPTIME
.It
.Dv CLOCK_UPTIME_FAST
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,11 +99,20 @@
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.
+Similar to CLOCK_REALTIME, but without leap seconds.
+It will increase monotonically during a leap second.
+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
+synchronized.
.El
.Pp
The clock IDs
.Dv CLOCK_BOOTTIME ,
.Dv CLOCK_REALTIME ,
+.Dv CLOCK_TAI ,
.Dv CLOCK_MONOTONIC ,
and
.Dv CLOCK_UPTIME
@@ -202,7 +211,8 @@
.Dv CLOCK_MONOTONIC_PRECISE ,
.Dv CLOCK_REALTIME_FAST ,
.Dv CLOCK_REALTIME_PRECISE ,
-.Dv CLOCK_SECOND
+.Dv CLOCK_SECOND ,
+.Dv CLOCK_TAI ,
.Dv CLOCK_UPTIME ,
.Dv CLOCK_UPTIME_FAST ,
and
diff --git a/lib/libsys/nanosleep.2 b/lib/libsys/nanosleep.2
--- a/lib/libsys/nanosleep.2
+++ b/lib/libsys/nanosleep.2
@@ -27,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 29, 2025
+.Dd May 3, 2025
.Dt NANOSLEEP 2
.Os
.Sh NAME
@@ -116,6 +116,8 @@
.It
CLOCK_SECOND
.It
+CLOCK_TAI
+.It
CLOCK_UPTIME
.It
CLOCK_UPTIME_FAST
diff --git a/lib/libsys/timer_create.2 b/lib/libsys/timer_create.2
--- a/lib/libsys/timer_create.2
+++ b/lib/libsys/timer_create.2
@@ -126,7 +126,8 @@
This implementation supports a
.Fa clock_id
of
-.Dv CLOCK_REALTIME
+.Dv CLOCK_REALTIME ,
+.Dv CLOCK_TAI ,
or
.Dv CLOCK_MONOTONIC .
.Pp
diff --git a/lib/libthr/thread/thr_condattr.c b/lib/libthr/thread/thr_condattr.c
--- a/lib/libthr/thread/thr_condattr.c
+++ b/lib/libthr/thread/thr_condattr.c
@@ -94,6 +94,7 @@
if (attr == NULL || *attr == NULL)
return (EINVAL);
if (clock_id != CLOCK_REALTIME &&
+ clock_id != CLOCK_TAI &&
clock_id != CLOCK_VIRTUAL &&
clock_id != CLOCK_PROF &&
clock_id != CLOCK_MONOTONIC) {
diff --git a/share/man/man3/pthread_condattr.3 b/share/man/man3/pthread_condattr.3
--- a/share/man/man3/pthread_condattr.3
+++ b/share/man/man3/pthread_condattr.3
@@ -85,7 +85,8 @@
.Xr pthread_cond_timedwait 3
and may be set to
.Dv CLOCK_REALTIME
-(default)
+(default),
+.Dv CLOCK_TAI ,
or
.Dv CLOCK_MONOTONIC .
.Pp
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
@@ -504,7 +504,7 @@
* simulation.
*/
void
-ntp_update_second(int64_t *adjustment, time_t *newsec)
+ntp_update_second(int64_t *adjustment, time_t *newsec, long *tai_off)
{
int tickrate;
l_fp ftemp; /* 32/64-bit temporary */
@@ -624,6 +624,7 @@
L_ADD(time_adj, ftemp);
}
*adjustment = time_adj;
+ *tai_off = time_tai;
#ifdef PPS_SYNC
if (pps_valid > 0)
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
@@ -72,6 +72,7 @@
uint64_t th_scale;
u_int th_large_delta;
u_int th_offset_count;
+ long th_tai_offset;
struct bintime th_offset;
struct bintime th_bintime;
struct timeval th_microtime;
@@ -1066,6 +1067,7 @@
th = timehands;
gen = atomic_load_acq_int(&th->th_generation);
fbi->th_scale = th->th_scale;
+ fbi->th_tai_offset = th->th_tai_offset;
fbi->tick_time = th->th_offset;
#ifdef FFCLOCK
ffth = fftimehands;
@@ -1139,6 +1141,11 @@
getboottimebin(&boottimebin);
bintime_add(bt, &boottimebin);
}
+ if (!(flags & FBCLOCK_LEAPSEC)) {
+ if (cs->fb_info.th_tai_offset == 0)
+ return (EINVAL);
+ bt->sec += cs->fb_info.th_tai_offset;
+ }
break;
#ifdef FFCLOCK
case SYSCLOCK_FFWD:
@@ -1433,7 +1440,8 @@
do {
t = bt.sec;
- ntp_update_second(&th->th_adjustment, &bt.sec);
+ ntp_update_second(&th->th_adjustment, &bt.sec,
+ &th->th_tai_offset);
if (bt.sec != t)
th->th_boottime.sec += bt.sec - t;
--i;
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 <sys/proc.h>
#include <sys/posix4.h>
#include <sys/time.h>
+#include <sys/timeffc.h>
#include <sys/timers.h>
#include <sys/timetc.h>
#include <sys/vnode.h>
@@ -60,7 +61,7 @@
#include <vm/vm_extern.h>
#include <vm/uma.h>
-#define MAX_CLOCKS (CLOCK_MONOTONIC+1)
+#define MAX_CLOCKS (CLOCK_TAI+1)
#define CPUCLOCK_BIT 0x80000000
#define CPUCLOCK_PROCESS_BIT 0x40000000
#define CPUCLOCK_ID_MASK (~(CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT))
@@ -101,7 +102,6 @@
static int realtimer_settime(struct itimer *, int,
struct itimerspec *, struct itimerspec *);
static int realtimer_delete(struct itimer *);
-static void realtimer_clocktime(clockid_t, struct timespec *);
static void realtimer_expire(void *);
static void realtimer_expire_l(struct itimer *it, bool proc_locked);
@@ -318,7 +318,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 +332,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);
@@ -451,6 +462,7 @@
case CLOCK_REALTIME:
case CLOCK_REALTIME_FAST:
case CLOCK_REALTIME_PRECISE:
+ case CLOCK_TAI:
case CLOCK_MONOTONIC:
case CLOCK_MONOTONIC_FAST:
case CLOCK_MONOTONIC_PRECISE:
@@ -516,6 +528,7 @@
return (EINVAL);
switch (clock_id) {
case CLOCK_REALTIME:
+ case CLOCK_TAI:
precise = nanosleep_precise;
is_abs_real = (flags & TIMER_ABSTIME) != 0;
break;
@@ -1167,6 +1180,7 @@
NULL, NULL, itimer_init, itimer_fini, UMA_ALIGN_PTR, 0);
register_posix_clock(CLOCK_REALTIME, &rt_clock);
register_posix_clock(CLOCK_MONOTONIC, &rt_clock);
+ register_posix_clock(CLOCK_TAI, &rt_clock);
p31b_setcfg(CTL_P1003_1B_TIMERS, 200112L);
p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, INT_MAX);
p31b_setcfg(CTL_P1003_1B_TIMER_MAX, TIMER_MAX);
@@ -1327,6 +1341,7 @@
switch (clock_id) {
default:
case CLOCK_REALTIME:
+ case CLOCK_TAI:
it->it_sigev.sigev_signo = SIGALRM;
break;
case CLOCK_VIRTUAL:
@@ -1570,10 +1585,14 @@
realtimer_gettime(struct itimer *it, struct itimerspec *ovalue)
{
struct timespec cts;
+ int err;
mtx_assert(&it->it_mtx, MA_OWNED);
- realtimer_clocktime(it->it_clockid, &cts);
+ err = kern_clock_gettime(curthread, it->it_clockid, &cts);
+ if (err)
+ return (err);
+
*ovalue = it->it_time;
if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_nsec != 0) {
timespecsub(&ovalue->it_value, &cts, &ovalue->it_value);
@@ -1594,6 +1613,7 @@
struct timespec cts, ts;
struct timeval tv;
struct itimerspec val;
+ int err;
mtx_assert(&it->it_mtx, MA_OWNED);
@@ -1613,7 +1633,10 @@
it->it_time = val;
if (timespecisset(&val.it_value)) {
- realtimer_clocktime(it->it_clockid, &cts);
+ err = kern_clock_gettime(curthread, it->it_clockid, &cts);
+ if (err)
+ return (err);
+
ts = val.it_value;
if ((flags & TIMER_ABSTIME) == 0) {
/* Convert to absolute time. */
@@ -1636,15 +1659,6 @@
return (0);
}
-static void
-realtimer_clocktime(clockid_t id, struct timespec *ts)
-{
- if (id == CLOCK_REALTIME)
- getnanotime(ts);
- else /* CLOCK_MONOTONIC */
- getnanouptime(ts);
-}
-
int
itimer_accept(struct proc *p, int timerid, ksiginfo_t *ksi)
{
@@ -1689,10 +1703,12 @@
struct timeval tv;
struct proc *p;
uint64_t interval, now, overruns, value;
+ int err;
+
+ err = kern_clock_gettime(curthread, it->it_clockid, &cts);
- realtimer_clocktime(it->it_clockid, &cts);
/* Only fire if time is reached. */
- if (timespeccmp(&cts, &it->it_time.it_value, >=)) {
+ if (err == 0 && timespeccmp(&cts, &it->it_time.it_value, >=)) {
if (timespecisset(&it->it_time.it_interval)) {
timespecadd(&it->it_time.it_value,
&it->it_time.it_interval,
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -693,6 +693,7 @@
timo->is_abs_real = clockid == CLOCK_REALTIME ||
clockid == CLOCK_REALTIME_FAST ||
clockid == CLOCK_REALTIME_PRECISE ||
+ clockid == CLOCK_TAI ||
clockid == CLOCK_SECOND;
}
}
@@ -787,6 +788,7 @@
case CLOCK_PROF:
case CLOCK_THREAD_CPUTIME_ID:
case CLOCK_PROCESS_CPUTIME_ID:
+ case CLOCK_TAI: /* Boot time is not necessarily stable in TAI */
default:
kern_clock_gettime(curthread, timo->clockid, &timo->cur);
if (timespeccmp(&timo->end, &timo->cur, <=))
@@ -2953,8 +2955,9 @@
umtx_key_release(&uq->uq_key);
return (EFAULT);
}
- if (clockid < CLOCK_REALTIME ||
- clockid >= CLOCK_THREAD_CPUTIME_ID) {
+ if ((clockid < CLOCK_REALTIME ||
+ clockid >= CLOCK_THREAD_CPUTIME_ID) &&
+ clockid != CLOCK_TAI) {
/* hmm, only HW clock id will work. */
umtx_key_release(&uq->uq_key);
return (EINVAL);
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
/*
@@ -111,6 +112,7 @@
struct bintime error;
struct bintime tick_time;
uint64_t th_scale;
+ long th_tai_offset;
int status;
};
diff --git a/sys/sys/timex.h b/sys/sys/timex.h
--- a/sys/sys/timex.h
+++ b/sys/sys/timex.h
@@ -154,7 +154,7 @@
#ifdef __FreeBSD__
#ifdef _KERNEL
-void ntp_update_second(int64_t *adjustment, time_t *newsec);
+void ntp_update_second(int64_t *adjustment, time_t *newsec, long *tai_off);
#else /* !_KERNEL */
#include <sys/cdefs.h>

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 15, 6:18 PM (10 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28751686
Default Alt Text
D46268.diff (10 KB)

Event Timeline