Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144985173
D46268.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D46268.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D46268: Implement CLOCK_TAI
Attached
Detach File
Event Timeline
Log In to Comment