libc: add adjtime() system call.

Implement the adjtime() system call and add a test for it to test69.
Additionally, install the adjtime.2 and clock_*.2 man pages.
This commit is contained in:
Thomas Cort 2013-03-31 01:24:24 +00:00 committed by Ben Gras
parent 516fec97d9
commit 15b3d77268
13 changed files with 136 additions and 14 deletions

View file

@ -1455,6 +1455,7 @@
./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
@ -1463,6 +1464,9 @@
./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

View 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 *
*===========================================================================*/

View 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);

View file

@ -17,12 +17,20 @@
*===========================================================================*/
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);
}

View file

@ -1,6 +1,5 @@
_lwp_*
acct
adjtime
lchmod
lchown
clone

View 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 \

View file

@ -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;
}

View 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;

View 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 \

View 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

View 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:

View 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 */

View 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);