-#define NCALLS 116 /* number of system calls allowed */
+#define NCALLS 117 /* number of system calls allowed */
/* In case it isn't obvious enough: this list is sorted numerically. */
#define EXIT 1
#define PM_GETSID 113 /* PM getsid() */
#define CLOCK_GETRES 114 /* clock_getres() */
#define CLOCK_GETTIME 115 /* clock_gettime() */
+#define CLOCK_SETTIME 116 /* clock_settime() */
#define TASK_REPLY 121 /* to VFS: reply code from drivers, not
* really a standalone call.
# define SYS_PROFBUF (KERNEL_CALL + 38) /* sys_profbuf() */
# define SYS_STIME (KERNEL_CALL + 39) /* sys_stime() */
+# define SYS_SETTIME (KERNEL_CALL + 40) /* sys_settime() */
# define SYS_VMCTL (KERNEL_CALL + 43) /* sys_vmctl() */
# define SYS_SYSCTL (KERNEL_CALL + 44) /* sys_sysctl() */
#define T_REAL_TICKS m4_l4 /* number of wall clock ticks since boottime */
#define T_BOOT_TICKS m4_l5 /* number of hard clock ticks since boottime */
+/* Field names for SYS_SETTIME. */
+#define T_SETTIME_NOW m4_l2 /* non-zero for immediate, 0 for adjtime */
+#define T_CLOCK_ID m4_l3 /* clock to adjust */
+#define T_TIME_SEC m4_l4 /* time in seconds since 1970 */
+#define T_TIME_NSEC m4_l5 /* number of nano seconds */
+
/* Field names for SYS_TRACE, SYS_PRIVCTL, SYS_STATECTL. */
#define CTL_ENDPT m2_i1 /* process number of the caller */
#define CTL_REQUEST m2_i2 /* server control request */
int sys_vmctl_enable_paging(void * data);
int sys_readbios(phys_bytes address, void *buf, size_t size);
+int sys_settime(int now, clockid_t clk_id, time_t sec, long nsec);
int sys_stime(time_t boottime);
int sys_sysctl(int ctl, char *arg1, int arg2);
int sys_sysctl_stacktrace(endpoint_t who);
__RENAME(__clock_getres50);
int clock_gettime(clockid_t, struct timespec *)
__RENAME(__clock_gettime50);
-#ifndef __minix
int clock_settime(clockid_t, const struct timespec *)
__RENAME(__clock_settime50);
-#endif /* !__minix */
int nanosleep(const struct timespec *, struct timespec *)
__RENAME(__nanosleep50);
#ifndef __minix
* loop, there are several other minor entry points:
* 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
* get_monotonic: get monotonic time since boot in clock ticks
* set_timer: set a watchdog timer (+)
* reset_timer: reset a watchdog timer (+)
return(realtime);
}
+/*===========================================================================*
+ * set_realtime *
+ *===========================================================================*/
+void set_realtime(clock_t newrealtime)
+{
+ realtime = newrealtime;
+}
/*===========================================================================*
* get_monotonic *
/* clock.c */
clock_t get_realtime(void);
+void set_realtime(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);
map(SYS_TIMES, do_times); /* get uptime and process times */
map(SYS_SETALARM, do_setalarm); /* schedule a synchronous alarm */
map(SYS_STIME, do_stime); /* set the boottime */
+ map(SYS_SETTIME, do_settime); /* set the system time (realtime) */
map(SYS_VTIMER, do_vtimer); /* set or retrieve a virtual timer */
/* System control. */
#endif
int do_stime(struct proc * caller, message *m_ptr);
+int do_settime(struct proc * caller, message *m_ptr);
int do_vtimer(struct proc * caller, message *m_ptr);
#if ! USE_VTIMER
do_times.c \
do_setalarm.c \
do_stime.c \
+ do_settime.c \
do_vtimer.c \
do_irqctl.c \
do_copy.c \
--- /dev/null
+/* The kernel call implemented in this file:
+ * m_type: SYS_SETTIME
+ *
+ * The parameters for this kernel call are:
+ * m4_l2: T_SETTIME_NOW
+ * m4_l3: T_CLOCK_ID
+ * m4_l4: T_TIME_SEC
+ * m4_l5: T_TIME_NSEC
+ */
+
+#include "kernel/system.h"
+#include <minix/endpoint.h>
+#include <time.h>
+
+/*===========================================================================*
+ * do_settime *
+ *===========================================================================*/
+int do_settime(struct proc * caller, message * m_ptr)
+{
+ clock_t newclock;
+ time_t timediff;
+
+ if (m_ptr->T_CLOCK_ID != CLOCK_REALTIME) /* only realtime can change */
+ return EINVAL;
+
+ /* prevent a negative value for realtime */
+ if (m_ptr->T_TIME_SEC <= boottime) {
+ /* boottime was likely wrong, try to correct it. */
+ boottime = m_ptr->T_TIME_SEC;
+ set_realtime(1);
+ return(OK);
+ }
+
+ /* calculate the new value of realtime in ticks */
+ 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);
+}
lchmod
lchown
clone
-clock_settime
extattr_*
fhopen
fhstat
SRCS+= accept.c access.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_getres.c clock_gettime.c clock_settime.c \
connect.c dup.c dup2.c execve.c fcntl.c flock.c fpathconf.c fork.c \
fstatfs.c fstatvfs.c fsync.c ftruncate.c getdents.c getegid.c getgid.c \
getgroups.c getitimer.c setitimer.c __getlogin.c getpeername.c \
{
message m;
- m.m2_l1 = (clockid_t) clock_id;
+ m.m2_i1 = (clockid_t) clock_id;
if (_syscall(PM_PROC_NR, CLOCK_GETRES, &m) < 0)
return -1;
{
message m;
- m.m2_l1 = (clockid_t) clock_id;
+ m.m2_i1 = (clockid_t) clock_id;
if (_syscall(PM_PROC_NR, CLOCK_GETTIME, &m) < 0)
return -1;
--- /dev/null
+#include <sys/cdefs.h>
+#include <lib.h>
+#include "namespace.h"
+
+#include <time.h>
+
+#ifdef __weak_alias
+__weak_alias(clock_settime, __clock_settime50);
+#endif
+
+int clock_settime(clockid_t clock_id, const struct timespec *ts)
+{
+ message m;
+
+ m.m2_i1 = (clockid_t) clock_id;
+ m.m2_l1 = (time_t) ts->tv_sec;
+ m.m2_l2 = (long) ts->tv_nsec;
+
+ if (_syscall(PM_PROC_NR, CLOCK_SETTIME, &m) < 0)
+ return -1;
+
+ return 0;
+}
+
int settimeofday(const struct timeval *tp, const void *tzp)
{
- /* Use intermediate variable because stime param is not const */
- time_t sec = tp->tv_sec;
+ struct timespec ts;
+
+ ts.tv_sec = tp->tv_sec;
+ ts.tv_nsec = tp->tv_usec * 1000;
/* Ignore time zones */
- return stime(&sec);
+ return clock_settime(CLOCK_REALTIME, &ts);
}
#if defined(__minix) && defined(__weak_alias)
sys_schedule.c \
sys_setalarm.c \
sys_setgrant.c \
+ sys_settime.c \
sys_sigreturn.c \
sys_sigsend.c \
sys_sprof.c \
--- /dev/null
+#include "syslib.h"
+#include <time.h>
+
+int sys_settime(now, clk_id, sec, nsec)
+int now;
+clockid_t clk_id;
+time_t sec;
+long nsec;
+{
+ message m;
+ int r;
+
+ m.T_SETTIME_NOW = now;
+ m.T_CLOCK_ID = clk_id;
+ m.T_TIME_SEC = sec;
+ m.T_TIME_NSEC = nsec;
+
+ r = _kernel_call(SYS_SETTIME, &m);
+ return(r);
+}
#define svrctl_req m2_i1
#define svrctl_argp m2_p1
#define stime m2_l1
-#define clk_id m2_l1
+#define clk_id m2_i1
+#define time_sec m2_l1
+#define time_nsec m2_l2
#define memsize m4_l1
#define membase m4_l2
#define sysuname_req m1_i1
int do_times(void);
int do_getres(void);
int do_gettime(void);
+int do_settime(void);
/* trace.c */
int do_trace(void);
do_get, /* 113 = getsid */
do_getres, /* 114 = clock_getres */
do_gettime, /* 115 = clock_gettime */
+ do_settime, /* 116 = clock_settime */
};
/* This should not fail with "array size is negative": */
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
* The entry points into this file are
* do_getres: perform the CLOCK_GETRES system call
* do_gettime: perform the CLOCK_GETTIME system call
+ * do_settime: perform the CLOCK_SETTIME system call
* do_time: perform the TIME system call
* do_stime: perform the STIME system call
* do_times: perform the TIMES system call
}
}
+/*===========================================================================*
+ * do_settime *
+ *===========================================================================*/
+int do_settime()
+{
+ int s;
+
+ if (mp->mp_effuid != SUPER_USER) {
+ return(EPERM);
+ }
+
+ switch (m_in.clk_id) {
+ case CLOCK_REALTIME:
+ s= sys_settime(1, m_in.clk_id, m_in.time_sec, m_in.time_nsec);
+ return(s);
+ case CLOCK_MONOTONIC: /* monotonic cannot be changed */
+ default:
+ return EINVAL; /* invalid/unsupported clock_id */
+ }
+}
+
/*===========================================================================*
* do_time *
*===========================================================================*/
no_sys, /* 113 = (getsid) */
no_sys, /* 114 = (clock_getres) */
no_sys, /* 115 = (clock_gettime) */
+ no_sys, /* 116 = (clock_settime) */
};
/* This should not fail with "array size is negative": */
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
void quit(void);
static void test_clock_getres();
static void test_clock_gettime();
+static void test_clock_settime();
static void show_timespec(char *msg, struct timespec *ts);
static void test_clock_getres()
if (clock_gettime(-1, &ts) == 0) e(31);
}
+static void test_clock_settime(void)
+{
+ struct timespec ts;
+ struct timespec ts2;
+
+ /* shouldn't be able to set MONOTONIC */
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) e(50);
+ if (clock_settime(CLOCK_MONOTONIC, &ts) == 0) e(51);
+ if (errno != EINVAL) e(52); /* reponse should be EINVAL */
+
+ /* set the time of REALTIME to that of MONOTONIC */
+ if (clock_settime(CLOCK_REALTIME, &ts) == -1) e(53);
+
+ ts.tv_sec += 600; /* time travel 10 minutes into the future */
+ if (clock_gettime(CLOCK_REALTIME, &ts2) == -1) e(54);
+ if (clock_settime(CLOCK_REALTIME, &ts) == -1) e(55);
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) e(56);
+
+ /* get the value we set, if it's not about 10 minutes ahead, it failed */
+ if (ts.tv_sec - ts2.tv_sec < 500 ||
+ ts.tv_sec - ts2.tv_sec > 700) e(57);
+
+ /* back to current time - don't leave the system time 10 ahead */
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) e(58);
+ ts.tv_sec -= 600;
+ if (clock_settime(CLOCK_REALTIME, &ts) == -1) e(59);
+
+ /* Test with an invalid clock */
+ if (clock_settime(-1, &ts) == 0) e(60);
+}
+
static void show_timespec(char *msg, struct timespec *ts)
{
#if DEBUG == 1
test_clock_getres();
test_clock_gettime();
+ test_clock_settime();
/* get test end time */
if (clock_gettime(CLOCK_MONOTONIC, &endtime) == -1) e(2);