summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2006-10-30 20:19:34 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2006-10-30 20:19:34 +0000
commit0eb59e835bf1485b257d8544f2cbdd5d903f159c (patch)
tree95041ce9006d30192cc08d000490a8315f9d9cc8
parent23c7d2e7742edb7f7d49bbf29ee8d93c39b9922c (diff)
Timecounter based implementation of adjfreq(2). Largely from art@
Tested by various using not (yet) committed amd64 timecounter code. ok deraadt@
-rw-r--r--sys/kern/kern_tc.c15
-rw-r--r--sys/kern/kern_time.c16
-rw-r--r--sys/sys/timetc.h5
3 files changed, 30 insertions, 6 deletions
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 52094aa620c..2a7d7d3efee 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
- * $OpenBSD: kern_tc.c,v 1.5 2005/05/03 11:10:56 hshoexer Exp $
+ * $OpenBSD: kern_tc.c,v 1.6 2006/10/30 20:19:33 otto Exp $
* $FreeBSD: src/sys/kern/kern_tc.c,v 1.148 2003/03/18 08:45:23 phk Exp $
*/
@@ -600,5 +600,18 @@ ntp_update_second(int64_t *adjust, time_t *sec)
adj.tv_usec = MAX(-500, adjtimedelta.tv_usec - 1000000);
timersub(&adjtimedelta, &adj, &adjtimedelta);
*adjust = ((int64_t)adj.tv_usec * 1000) << 32;
+ *adjust += timecounter->tc_freq_adj;
+}
+
+int
+tc_adjfreq(int64_t *old, int64_t *new)
+{
+ if (old != NULL) {
+ *old = timecounter->tc_freq_adj;
+ }
+ if (new != NULL) {
+ timecounter->tc_freq_adj = *new;
+ }
+ return 0;
}
#endif /* __HAVE_TIMECOUNTER */
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 3f1e10b57dd..a0933e65577 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_time.c,v 1.59 2006/06/29 19:52:47 kettenis Exp $ */
+/* $OpenBSD: kern_time.c,v 1.60 2006/10/30 20:19:33 otto Exp $ */
/* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */
/*
@@ -389,9 +389,17 @@ sys_adjfreq(struct proc *p, void *v, register_t *retval)
}
#else
if (SCARG(uap, oldfreq)) {
- f = 0;
- if ((error = copyout((void *)&f, (void *)SCARG(uap, oldfreq),
- sizeof(int64_t))))
+ if ((error = tc_adjfreq(&f, NULL)) != 0)
+ return (error);
+ if ((error = copyout(&f, SCARG(uap, oldfreq), sizeof(f))) != 0)
+ return (error);
+ }
+ if (SCARG(uap, freq)) {
+ if ((error = suser(p, 0)))
+ return (error);
+ if ((error = copyin(SCARG(uap, freq), &f, sizeof(f))) != 0)
+ return (error);
+ if ((error = tc_adjfreq(NULL, &f)) != 0)
return (error);
}
#endif
diff --git a/sys/sys/timetc.h b/sys/sys/timetc.h
index bbc532aec3e..54daeeea88a 100644
--- a/sys/sys/timetc.h
+++ b/sys/sys/timetc.h
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
- * $OpenBSD: timetc.h,v 1.1 2004/07/28 17:15:12 tholo Exp $
+ * $OpenBSD: timetc.h,v 1.2 2006/10/30 20:19:33 otto Exp $
* $FreeBSD: src/sys/sys/timetc.h,v 1.57 2003/04/10 23:07:24 des Exp $
*/
@@ -62,6 +62,8 @@ struct timecounter {
/* Pointer to the timecounter's private parts. */
struct timecounter *tc_next;
/* Pointer to the next timecounter. */
+ int64_t tc_freq_adj;
+ /* Current frequency adjustment. */
};
extern struct timecounter *timecounter;
@@ -72,5 +74,6 @@ void tc_setclock(struct timespec *ts);
void tc_ticktock(void);
void inittimecounter(void);
int sysctl_tc(int *, u_int, void *, size_t *, void *, size_t);
+int tc_adjfreq(int64_t *, int64_t *);
#endif /* !_SYS_TIMETC_H_ */