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:
parent
516fec97d9
commit
15b3d77268
13 changed files with 136 additions and 14 deletions
|
@ -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
|
||||
|
|
|
@ -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,8 +96,18 @@ int timer_int_handler(void)
|
|||
|
||||
if (cpu_is_bsp(cpuid)) {
|
||||
monotonic++;
|
||||
|
||||
/* 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
|
||||
* for user time. If the current process is not billable, that is, if a
|
||||
|
@ -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 *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) */
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
_lwp_*
|
||||
acct
|
||||
adjtime
|
||||
lchmod
|
||||
lchown
|
||||
clone
|
||||
|
|
|
@ -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 \
|
||||
|
|
36
lib/libc/sys-minix/adjtime.c
Normal file
36
lib/libc/sys-minix/adjtime.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue