Currently both ntptime code and resettodr() are Giant-locked. In particular, the Giant is supposed to protect against parallel ntp_adjtime(2) invocations. But, for instance, sys_ntp_adjtime() does copyout(9) under Giant and then examines time_status to return syscall result. Since copyout(9) could sleep, the syscall result might be
inconsistent.
Another and bigger issue is that if PPS is configured, hardpps() is executed without any protection against the parallel syscall invocation. Potentially, this may result in the inconsistent state of the ntptime state variables, but I cannot say how serious such distortion is. The non-functional splclock() call in sys_ntp_adjtime() protected against clock interrupts calling hardpps() in the pre-SMP era.
The patch modernizes the locking. A mutex protects ntptime data. Due to the hardpps() KPI legitimately serving from the interrupt filters (and e.g. uart(4) does call it from filter), the lock cannot be sleepable mutex if PPS_SYNC is defined.
The ntp_is_time_error() interface was changed to make the calls outside the ntpadj_lock at least self-consistent. Potentially callout could act upon stale state of the ntptime machinery still, but this is true for the current code in more ugly ways, and probably should be fine due to both low quality and long time of update for typical RTC.
For resettodr(), I just added an internal mutex and removed (non-enforced) requirement of owning Giant around the call. Since resettodr() is callable from the clock swi, MD CLOCK_SETTIME() implementations must not sleep anyway. The lock ensures that the callout to write-out the clock does not interfere with the machdep.adjkerntz sysctl and shutdown. I believe, but did not verified, that this is enough for all drivers (due to non-sleepable statement).