Bug #1351 ยป kern_time.patch
sys/kern/kern_time.c | ||
---|---|---|
* timers when they expire.
|
||
*/
|
||
static int nanosleep1 (struct timespec *rqt,
|
||
struct timespec *rmt);
|
||
static int settime (struct timeval *);
|
||
static void timevalfix (struct timeval *);
|
||
static int nanosleep1(struct timespec *rqt, struct timespec *rmt);
|
||
static int settime(struct timeval *);
|
||
static void timevalfix(struct timeval *);
|
||
static int sleep_hard_us = 100;
|
||
SYSCTL_INT(_kern, OID_AUTO, sleep_hard_us, CTLFLAG_RW, &sleep_hard_us, 0, "")
|
||
... | ... | |
return (0);
|
||
}
|
||
/* ARGSUSED */
|
||
int
|
||
sys_clock_gettime(struct clock_gettime_args *uap)
|
||
kern_clock_gettime(clockid_t clock_id, struct timespec *ats)
|
||
{
|
||
struct timespec ats;
|
||
switch(uap->clock_id) {
|
||
switch(clock_id) {
|
||
case CLOCK_REALTIME:
|
||
nanotime(&ats);
|
||
return (copyout(&ats, uap->tp, sizeof(ats)));
|
||
nanotime(ats);
|
||
case CLOCK_MONOTONIC:
|
||
nanouptime(&ats);
|
||
return (copyout(&ats, uap->tp, sizeof(ats)));
|
||
nanouptime(ats);
|
||
default:
|
||
return (EINVAL);
|
||
}
|
||
return (0);
|
||
}
|
||
/* ARGSUSED */
|
||
int
|
||
sys_clock_settime(struct clock_settime_args *uap)
|
||
sys_clock_gettime(struct clock_gettime_args *uap)
|
||
{
|
||
struct timespec ats;
|
||
int error;
|
||
error = kern_clock_gettime(uap->clock_id, &ats);
|
||
if (error == 0)
|
||
error = copyout(&ats, uap->tp, sizeof(ats))
|
||
|
||
return (error);
|
||
}
|
||
int
|
||
kern_clock_settime(clockid_t clock_id, struct timespec *ats)
|
||
{
|
||
struct thread *td = curthread;
|
||
struct timeval atv;
|
||
struct timespec ats;
|
||
int error;
|
||
if ((error = priv_check(td, PRIV_ROOT)) != 0)
|
||
return (error);
|
||
switch(uap->clock_id) {
|
||
case CLOCK_REALTIME:
|
||
if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0)
|
||
return (error);
|
||
if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000)
|
||
return (EINVAL);
|
||
/* XXX Don't convert nsec->usec and back */
|
||
TIMESPEC_TO_TIMEVAL(&atv, &ats);
|
||
error = settime(&atv);
|
||
return (error);
|
||
default:
|
||
if (clock_id != CLOCK_REALTIME)
|
||
return (EINVAL);
|
||
}
|
||
if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000)
|
||
return (EINVAL);
|
||
TIMESPEC_TO_TIMEVAL(&atv, ats);
|
||
error = settime(&atv);
|
||
return (error);
|
||
}
|
||
/* ARGSUSED */
|
||
int
|
||
sys_clock_getres(struct clock_getres_args *uap)
|
||
sys_clock_settime(struct clock_settime_args *uap)
|
||
{
|
||
struct timespec ts;
|
||
struct timespec ats;
|
||
int error;
|
||
if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0)
|
||
return (error);
|
||
|
||
return (kern_clock_settime(uap->clock_id, &ats));
|
||
}
|
||
switch(uap->clock_id) {
|
||
int
|
||
kern_clock_getres(clockid_t clock_id, struct timespec *ts)
|
||
{
|
||
switch(clock_id) {
|
||
case CLOCK_REALTIME:
|
||
case CLOCK_MONOTONIC:
|
||
/*
|
||
... | ... | |
* if rounding down would give 0. Perfect rounding
|
||
* is unimportant.
|
||
*/
|
||
ts.tv_sec = 0;
|
||
ts.tv_nsec = 1000000000 / sys_cputimer->freq + 1;
|
||
return(copyout(&ts, uap->tp, sizeof(ts)));
|
||
ts->tv_sec = 0;
|
||
ts->tv_nsec = 1000000000 / sys_cputimer->freq + 1;
|
||
default:
|
||
return(EINVAL);
|
||
}
|
||
return (0);
|
||
}
|
||
int
|
||
sys_clock_getres(struct clock_getres_args *uap)
|
||
{
|
||
int error;
|
||
struct timespec ts;
|
||
error = kern_clock_getres(uap->clock_id, &ts);
|
||
if (error == 0)
|
||
error = copyout(&ts, uap->tp, sizeof(ts));
|
||
|
||
return (error);
|
||
}
|
||
/*
|
sys/sys/time.h | ||
---|---|---|
void set_timeofday(struct timespec *ts);
|
||
void kern_adjtime(int64_t, int64_t *);
|
||
void kern_reladjtime(int64_t);
|
||
int kern_clock_gettime(clockid_t, struct timespec *);
|
||
int kern_clock_settime(clockid_t, struct timespec *);
|
||
int kern_clock_getres(clockid_t, struct timespec *);
|
||
void timevaladd (struct timeval *, const struct timeval *);
|
||
void timevalsub (struct timeval *, const struct timeval *);
|
||
int tvtohz_high (struct timeval *);
|