]> Zhao Yanbai Git Server - minix.git/commitdiff
libc: add adjtime() system call. 70/470/1
authorThomas Cort <tcort@minix3.org>
Sun, 31 Mar 2013 01:24:24 +0000 (01:24 +0000)
committerBen Gras <ben@minix3.org>
Thu, 4 Apr 2013 13:04:54 +0000 (15:04 +0200)
Implement the adjtime() system call and add a test for it to test69.
Additionally, install the adjtime.2 and clock_*.2 man pages.

13 files changed:
distrib/sets/lists/minix/mi
kernel/clock.c
kernel/proto.h
kernel/system/do_settime.c
lib/libc/sys-minix/MISSING_SYSCALLS
lib/libc/sys-minix/Makefile.inc
lib/libc/sys-minix/adjtime.c [new file with mode: 0644]
lib/libc/sys-minix/clock_settime.c
lib/libc/sys/Makefile.inc
servers/pm/param.h
servers/pm/time.c
sys/sys/time.h
test/test69.c

index 33c4e431f3786e85ded2c6e900a3f704c0e7880e..6414f674c1406ef5c7c17930b6bc5d10774eaada 100644 (file)
 ./usr/man/man1/znew.1                  minix-sys
 ./usr/man/man2/accept.2                        minix-sys
 ./usr/man/man2/access.2                        minix-sys
+./usr/man/man2/adjtime.2               minix-sys
 ./usr/man/man2/alarm.2                 minix-sys
 ./usr/man/man2/bind.2                  minix-sys
 ./usr/man/man2/brk.2                   minix-sys
 ./usr/man/man2/chown.2                 minix-sys
 ./usr/man/man2/chroot.2                        minix-sys
 ./usr/man/man2/close.2                 minix-sys
+./usr/man/man2/clock_getres.2          minix-sys
+./usr/man/man2/clock_gettime.2         minix-sys
+./usr/man/man2/clock_settime.2         minix-sys
 ./usr/man/man2/connect.2               minix-sys
 ./usr/man/man2/creat.2                 minix-sys
 ./usr/man/man2/dup.2                   minix-sys
index 688ab6695901279e8ffee740e53a2af6fdceb5bb..be6cfa572e643c51eeae84b75ef969e981a0a1e0 100644 (file)
@@ -20,6 +20,7 @@
  *   clock_stop:       called just before MINIX shutdown
  *   get_realtime:     get wall time since boot in clock ticks
  *   set_realtime:     set wall time since boot in clock ticks
+ *   set_adjtime_delta:        set the number of ticks to adjust realtime
  *   get_monotonic:    get monotonic time since boot in clock ticks
  *   set_timer:                set a watchdog timer (+)
  *   reset_timer:      reset a watchdog timer (+)
@@ -63,6 +64,11 @@ static clock_t monotonic = 0;
  */
 static clock_t realtime = 0;
 
+/* Number of ticks to adjust realtime by. A negative value implies slowing
+ * down realtime, a positive value implies speeding it up.
+ */
+static clock_t adjtime_delta = 0;
+
 /*
  * The boot processor's timer interrupt handler. In addition to non-boot cpus
  * it keeps real time and notifies the clock task if need be.
@@ -90,7 +96,17 @@ int timer_int_handler(void)
 
        if (cpu_is_bsp(cpuid)) {
                monotonic++;
-               realtime++;
+
+               /* if adjtime_delta has ticks remaining, apply one to realtime.
+                * limit changes to every other interrupt.
+                */
+               if (adjtime_delta != 0 && monotonic & 0x1) {
+                       /* go forward or stay behind */
+                       realtime += (adjtime_delta > 0) ? 2 : 0;
+                       adjtime_delta += (adjtime_delta > 0) ? -1 : +1;
+               } else {
+                       realtime++;
+               }
        }
 
        /* Update user and system accounting times. Charge the current process
@@ -176,6 +192,14 @@ void set_realtime(clock_t newrealtime)
   realtime = newrealtime;
 }
 
+/*===========================================================================*
+ *                             set_adjtime_delta                            *
+ *===========================================================================*/
+void set_adjtime_delta(clock_t ticks)
+{
+  adjtime_delta = ticks;
+}
+
 /*===========================================================================*
  *                             get_monotonic                                *
  *===========================================================================*/
index 120c620519ae3f5f9648d571ae20ff6045f3cd73..7952922ddb4ff5469ea5e63b34de0a587ea39ade 100644 (file)
@@ -17,6 +17,7 @@ struct timer;
 /* clock.c */
 clock_t get_realtime(void);
 void set_realtime(clock_t);
+void set_adjtime_delta(clock_t);
 clock_t get_monotonic(void);
 void set_timer(struct timer *tp, clock_t t, tmr_func_t f);
 void reset_timer(struct timer *tp);
index 7c106dd50802b49eb1cfc6e4735e9cf48f74f1ff..bf408ce6994e8f94cfca83e20534b18362d7ec06 100644 (file)
  *===========================================================================*/
 int do_settime(struct proc * caller, message * m_ptr)
 {
-  clock_t newclock;
+  clock_t newclock, ticks;
   time_t timediff;
 
   if (m_ptr->T_CLOCK_ID != CLOCK_REALTIME) /* only realtime can change */
        return EINVAL;
 
+  if (m_ptr->T_SETTIME_NOW == 0) { /* user just wants to adjtime() */
+       /* convert delta value from seconds and nseconds to ticks */
+       ticks = (m_ptr->T_TIME_SEC * system_hz) +
+                               (m_ptr->T_TIME_NSEC/(1000000000/system_hz));
+       set_adjtime_delta(ticks);
+       return(OK);
+  } /* else user wants to set the time */
+
   /* prevent a negative value for realtime */
   if (m_ptr->T_TIME_SEC <= boottime) {
        /* boottime was likely wrong, try to correct it. */
@@ -35,9 +43,7 @@ int do_settime(struct proc * caller, message * m_ptr)
   timediff = m_ptr->T_TIME_SEC - boottime;
   newclock = (timediff*system_hz) + (m_ptr->T_TIME_NSEC/(1000000000/system_hz));
 
-  if (m_ptr->T_SETTIME_NOW) {
-       set_realtime(newclock);
-  } /* else used adjtime() method (to be implemented) */
+  set_realtime(newclock);
 
   return(OK);
 }
index 440ab35b5c0907d4c681ff18e86d341840fe4a9c..dc75c0669c6a4ee7f2100ec35aad473fc7091bd4 100644 (file)
@@ -1,6 +1,5 @@
 _lwp_*
 acct
-adjtime
 lchmod
 lchown
 clone
index 211545599dab4b1cc7ec6a7d0afddf929936f0a7..542197c7d8867d81f00221639c78bb23b4c6d168 100644 (file)
@@ -1,6 +1,6 @@
 .PATH: ${.CURDIR}/sys-minix
 
-SRCS+=         accept.c access.c bind.c brk.c sbrk.c m_closefrom.c getsid.c \
+SRCS+=         accept.c access.c adjtime.c bind.c brk.c sbrk.c m_closefrom.c getsid.c \
        chdir.c chmod.c fchmod.c chown.c fchown.c chroot.c close.c \
        clock_getres.c clock_gettime.c clock_settime.c \
        connect.c dup.c dup2.c execve.c fcntl.c flock.c fpathconf.c fork.c \
diff --git a/lib/libc/sys-minix/adjtime.c b/lib/libc/sys-minix/adjtime.c
new file mode 100644 (file)
index 0000000..b38d884
--- /dev/null
@@ -0,0 +1,36 @@
+#include <sys/cdefs.h>
+#include <lib.h>
+#include "namespace.h"
+
+#include <sys/time.h>
+#include <time.h>
+
+#ifdef __weak_alias
+__weak_alias(adjtime, __adjtime50);
+#endif
+
+int adjtime(const struct timeval *delta, struct timeval *olddelta)
+{
+  message m;
+
+  m.m2_i2 = 0; /* use adjtime() method to slowly adjust the clock. */
+  m.m2_i1 = (clockid_t) CLOCK_REALTIME;
+  m.m2_l1 = (time_t) delta->tv_sec;
+  m.m2_l2 = (long) delta->tv_usec * 1000; /* convert usec to nsec */
+
+  if (_syscall(PM_PROC_NR, CLOCK_SETTIME, &m) < 0)
+       return -1;
+
+  if (olddelta != NULL) {
+       /* the kernel returns immediately and the adjustment happens in the 
+        * background. Also, any currently running adjustment is stopped by 
+        * another call to adjtime(2), so the only values possible on Minix
+        * for olddelta are those of delta.
+        */
+       olddelta->tv_sec = delta->tv_sec;
+       olddelta->tv_usec = delta->tv_usec;
+  }
+
+  return 0;
+}
+
index 28d5187783e00c28ce9f05ae503377bf45df938c..d608ef66f21e7ae3f40771a30d061af6c530636a 100644 (file)
@@ -12,6 +12,7 @@ int clock_settime(clockid_t clock_id, const struct timespec *ts)
 {
   message m;
 
+  m.m2_i2 = 1; /* set time immediately. don't use adjtime() method. */
   m.m2_i1 = (clockid_t) clock_id;
   m.m2_l1 = (time_t) ts->tv_sec;
   m.m2_l2 = (long) ts->tv_nsec;
index 3d6d088eefa7d92d809285164a55a7095676c9fb..b20b7ea66afc706d448258e2831dea830b109bb5 100644 (file)
@@ -221,8 +221,8 @@ LintSysPseudoNoerr.c: ${LIBCDIR}/sys/makelintstub \
 .endif # !defined(__MINIX)
 
 .if !defined(__MINIX)
-MAN+=  accept.2 access.2 acct.2 adjtime.2 bind.2 brk.2 chdir.2 \
-       chflags.2 chmod.2 chown.2 chroot.2 clock_settime.2 clone.2 close.2 \
+MAN+=  accept.2 access.2 acct.2 bind.2 brk.2 chdir.2 \
+       chflags.2 chmod.2 chown.2 chroot.2 clone.2 close.2 \
        connect.2 dup.2 execve.2 _exit.2 extattr_get_file.2 \
        fcntl.2 fdatasync.2 fhopen.2 \
        flock.2 fork.2 fsync.2 getcontext.2 getdents.2 \
@@ -244,7 +244,7 @@ MAN+=       accept.2 access.2 acct.2 adjtime.2 bind.2 brk.2 chdir.2 \
        mprotect.2 mremap.2 msgctl.2 msgget.2 msgrcv.2 msgsnd.2 msync.2 \
        munmap.2 nanosleep.2 nfssvc.2 ntp_adjtime.2 open.2 pathconf.2 pipe.2 
 .else
-MAN+=  pipe.2 
+MAN+=  adjtime.2 clock_settime.2 pipe.2 
 .endif # !defined(__MINIX)
 .if !defined(__MINIX)
 MAN+=  pmc_control.2 poll.2 posix_fadvise.2 profil.2 ptrace.2 __quotactl.2 \
@@ -271,8 +271,11 @@ MLINKS+=chflags.2 fchflags.2 chflags.2 lchflags.2
 MLINKS+=chmod.2 fchmod.2 chmod.2 lchmod.2
 MLINKS+=chown.2 fchown.2 chown.2 lchown.2
 MLINKS+=chroot.2 fchroot.2
+.else
 MLINKS+=clock_settime.2 clock_gettime.2
 MLINKS+=clock_settime.2 clock_getres.2
+.endif # !defined(__MINIX)
+.if !defined(__MINIX)
 MLINKS+=extattr_get_file.2 extattr_set_file.2 \
        extattr_get_file.2 extattr_delete_file.2 \
        extattr_get_file.2 extattr_list_file.2 \
index 260910fbde3150d00eb1f4361c9b98119803d981..3bdb266aa0176cffe743b312c5bfae4bddf3aab9 100644 (file)
@@ -31,6 +31,7 @@
 #define svrctl_argp    m2_p1
 #define stime          m2_l1
 #define clk_id         m2_i1
+#define settime_now    m2_i2
 #define time_sec       m2_l1
 #define time_nsec      m2_l2
 #define memsize        m4_l1
index aea2e421b48f5a6c364ff0608d66411050c31d14..40a73e00dd94b7a21d6637fb97e43a2e7c48078b 100644 (file)
@@ -76,7 +76,8 @@ int do_settime()
 
   switch (m_in.clk_id) {
        case CLOCK_REALTIME:
-               s= sys_settime(1, m_in.clk_id, m_in.time_sec, m_in.time_nsec);
+               s= sys_settime(m_in.settime_now, m_in.clk_id, m_in.time_sec,
+                                                       m_in.time_nsec);
                return(s);
        case CLOCK_MONOTONIC: /* monotonic cannot be changed */
        default:
index 6cda042ff5f26481f9c0aa54ed4eadc2d9057db6..b4f809e4002b2fe5066a063b86448e70954ec0bc 100644 (file)
@@ -285,8 +285,8 @@ int setitimer(int, const struct itimerval * __restrict,
 #endif /* _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE || _NETBSD_SOURCE */
 
 #if defined(_NETBSD_SOURCE) || defined(HAVE_NBTOOL_CONFIG_H)
-#ifndef __minix
 int    adjtime(const struct timeval *, struct timeval *) __RENAME(__adjtime50);
+#ifndef __minix
 int    futimes(int, const struct timeval [2]) __RENAME(__futimes50);
 int    lutimes(const char *, const struct timeval [2]) __RENAME(__lutimes50);
 #endif /* !__minix */
index 0282f60bb781b0b2a7556701ff082e5f4fd162d7..7c1a6e631b8b40e88ad9cd952f065682f18b2c8e 100644 (file)
@@ -1,4 +1,8 @@
-/* Test 69. clock_getres(), clock_gettime(). */
+/* Test 69. clock_getres(), clock_gettime(), clock_settime(), adjtime().
+ *
+ * Note, any type of ntpd or software that calls adjtime() or settimeofday()
+ * should be disabled while running this test. This test takes ~40s to run.
+ */
 
 #include <time.h>
 #include <sys/types.h>
@@ -10,7 +14,9 @@
 
 #define TRIALS 100
 #define MAX_ERROR 4
+#ifndef DEBUG
 #define DEBUG 0
+#endif
 
 int subtest = 1;
 
@@ -21,6 +27,7 @@ void quit(void);
 static void test_clock_getres();
 static void test_clock_gettime();
 static void test_clock_settime();
+static void test_adjtime();
 static void show_timespec(char *msg, struct timespec *ts);
 
 static void test_clock_getres()
@@ -60,7 +67,6 @@ static void test_clock_gettime()
   if (ts2.tv_sec < 0 || ts2.tv_nsec < 0) e(29);
   if (ts2.tv_sec <= ts.tv_sec) e(30);
 
-
   if (clock_gettime(-1, &ts) == 0) e(31);
 }
 
@@ -95,6 +101,45 @@ static void test_clock_settime(void)
   if (clock_settime(-1, &ts) == 0) e(60);
 }
 
+static void test_adjtime(void)
+{
+  struct timeval delta, olddelta;
+  struct timespec rt, mt;
+
+  /* set the realtime clock to the same value as the monotonic clock */
+  if (clock_gettime(CLOCK_MONOTONIC, &mt) == -1) e(65);
+  if (clock_settime(CLOCK_REALTIME, &mt) == -1) e(66);
+
+  delta.tv_sec = 7;
+  delta.tv_usec = 0;
+
+  if (adjtime(&delta, &olddelta) != 0) e(70);  /* adjust +7 seconds */
+  sleep(15);   /* should take 14 seconds to adjust the clock */
+
+  /* check that the 7 second adjustment puts us between 5 and 10 seconds
+   * ahead of the monotonic clock.
+   */
+  if (clock_gettime(CLOCK_MONOTONIC, &mt) == -1) e(71);
+  if (clock_gettime(CLOCK_REALTIME, &rt) == -1) e(72);
+  show_timespec("Monotonic", &mt);
+  show_timespec("Realtime (+7)", &rt);
+  if (rt.tv_sec - 5 < mt.tv_sec || rt.tv_sec - 10 > mt.tv_sec) e(73);
+
+  delta.tv_sec = -7;
+  if (adjtime(&delta, &olddelta) != 0) e(73);  /* adjust -7 seconds */
+  sleep(15);   /* should take 14 seconds to adjust the clock */
+
+  /* check that the 7 second adjustment puts us close to even with
+   * the monotonic clock.
+   */
+  if (clock_gettime(CLOCK_MONOTONIC, &mt) == -1) e(74);
+  if (clock_gettime(CLOCK_REALTIME, &rt) == -1) e(75);
+  show_timespec("Monotonic", &mt);
+  show_timespec("Realtime (-7)", &rt);
+  if (abs(rt.tv_sec - mt.tv_sec) > 5) e(76);
+
+}
+
 static void show_timespec(char *msg, struct timespec *ts)
 {
 #if DEBUG == 1
@@ -113,6 +158,7 @@ int main()
   test_clock_getres();
   test_clock_gettime();
   test_clock_settime();
+  test_adjtime();
 
   /* get test end time */
   if (clock_gettime(CLOCK_MONOTONIC, &endtime) == -1) e(2);