Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_time.c
Show First 20 Lines • Show All 537 Lines • ▼ Show 20 Lines | kern_clock_nanosleep(struct thread *td, clockid_t clock_id, int flags, | ||||
do { | do { | ||||
ts = *rqt; | ts = *rqt; | ||||
if ((flags & TIMER_ABSTIME) != 0) { | if ((flags & TIMER_ABSTIME) != 0) { | ||||
if (is_abs_real) | if (is_abs_real) | ||||
td->td_rtcgen = | td->td_rtcgen = | ||||
atomic_load_acq_int(&rtc_generation); | atomic_load_acq_int(&rtc_generation); | ||||
error = kern_clock_gettime(td, clock_id, &now); | error = kern_clock_gettime(td, clock_id, &now); | ||||
KASSERT(error == 0, ("kern_clock_gettime: %d", error)); | KASSERT(error == 0, ("kern_clock_gettime: %d", error)); | ||||
timespecsub(&ts, &now); | timespecsub(&ts, &now, &ts); | ||||
} | } | ||||
if (ts.tv_sec < 0 || (ts.tv_sec == 0 && ts.tv_nsec == 0)) { | if (ts.tv_sec < 0 || (ts.tv_sec == 0 && ts.tv_nsec == 0)) { | ||||
error = EWOULDBLOCK; | error = EWOULDBLOCK; | ||||
break; | break; | ||||
} | } | ||||
if (ts.tv_sec > INT32_MAX / 2) { | if (ts.tv_sec > INT32_MAX / 2) { | ||||
over = ts.tv_sec - INT32_MAX / 2; | over = ts.tv_sec - INT32_MAX / 2; | ||||
ts.tv_sec -= over; | ts.tv_sec -= over; | ||||
▲ Show 20 Lines • Show All 960 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct timespec cts; | struct timespec cts; | ||||
mtx_assert(&it->it_mtx, MA_OWNED); | mtx_assert(&it->it_mtx, MA_OWNED); | ||||
realtimer_clocktime(it->it_clockid, &cts); | realtimer_clocktime(it->it_clockid, &cts); | ||||
*ovalue = it->it_time; | *ovalue = it->it_time; | ||||
if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_nsec != 0) { | if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_nsec != 0) { | ||||
timespecsub(&ovalue->it_value, &cts); | timespecsub(&ovalue->it_value, &cts, &ovalue->it_value); | ||||
if (ovalue->it_value.tv_sec < 0 || | if (ovalue->it_value.tv_sec < 0 || | ||||
(ovalue->it_value.tv_sec == 0 && | (ovalue->it_value.tv_sec == 0 && | ||||
ovalue->it_value.tv_nsec == 0)) { | ovalue->it_value.tv_nsec == 0)) { | ||||
ovalue->it_value.tv_sec = 0; | ovalue->it_value.tv_sec = 0; | ||||
ovalue->it_value.tv_nsec = 1; | ovalue->it_value.tv_nsec = 1; | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
Show All 24 Lines | if (ovalue != NULL) | ||||
realtimer_gettime(it, ovalue); | realtimer_gettime(it, ovalue); | ||||
it->it_time = val; | it->it_time = val; | ||||
if (timespecisset(&val.it_value)) { | if (timespecisset(&val.it_value)) { | ||||
realtimer_clocktime(it->it_clockid, &cts); | realtimer_clocktime(it->it_clockid, &cts); | ||||
ts = val.it_value; | ts = val.it_value; | ||||
if ((flags & TIMER_ABSTIME) == 0) { | if ((flags & TIMER_ABSTIME) == 0) { | ||||
/* Convert to absolute time. */ | /* Convert to absolute time. */ | ||||
timespecadd(&it->it_time.it_value, &cts); | timespecadd(&it->it_time.it_value, &cts, | ||||
&it->it_time.it_value); | |||||
} else { | } else { | ||||
timespecsub(&ts, &cts); | timespecsub(&ts, &cts, &ts); | ||||
/* | /* | ||||
* We don't care if ts is negative, tztohz will | * We don't care if ts is negative, tztohz will | ||||
* fix it. | * fix it. | ||||
*/ | */ | ||||
} | } | ||||
TIMESPEC_TO_TIMEVAL(&tv, &ts); | TIMESPEC_TO_TIMEVAL(&tv, &ts); | ||||
callout_reset(&it->it_callout, tvtohz(&tv), | callout_reset(&it->it_callout, tvtohz(&tv), | ||||
realtimer_expire, it); | realtimer_expire, it); | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | realtimer_expire(void *arg) | ||||
it = (struct itimer *)arg; | it = (struct itimer *)arg; | ||||
realtimer_clocktime(it->it_clockid, &cts); | realtimer_clocktime(it->it_clockid, &cts); | ||||
/* Only fire if time is reached. */ | /* Only fire if time is reached. */ | ||||
if (timespeccmp(&cts, &it->it_time.it_value, >=)) { | if (timespeccmp(&cts, &it->it_time.it_value, >=)) { | ||||
if (timespecisset(&it->it_time.it_interval)) { | if (timespecisset(&it->it_time.it_interval)) { | ||||
timespecadd(&it->it_time.it_value, | timespecadd(&it->it_time.it_value, | ||||
&it->it_time.it_interval); | &it->it_time.it_interval, | ||||
&it->it_time.it_value); | |||||
while (timespeccmp(&cts, &it->it_time.it_value, >=)) { | while (timespeccmp(&cts, &it->it_time.it_value, >=)) { | ||||
if (it->it_overrun < INT_MAX) | if (it->it_overrun < INT_MAX) | ||||
it->it_overrun++; | it->it_overrun++; | ||||
else | else | ||||
it->it_ksi.ksi_errno = ERANGE; | it->it_ksi.ksi_errno = ERANGE; | ||||
timespecadd(&it->it_time.it_value, | timespecadd(&it->it_time.it_value, | ||||
&it->it_time.it_interval); | &it->it_time.it_interval, | ||||
&it->it_time.it_value); | |||||
} | } | ||||
} else { | } else { | ||||
/* single shot timer ? */ | /* single shot timer ? */ | ||||
timespecclear(&it->it_time.it_value); | timespecclear(&it->it_time.it_value); | ||||
} | } | ||||
if (timespecisset(&it->it_time.it_value)) { | if (timespecisset(&it->it_time.it_value)) { | ||||
ts = it->it_time.it_value; | timespecsub(&it->it_time.it_value, &cts, &ts); | ||||
timespecsub(&ts, &cts); | |||||
TIMESPEC_TO_TIMEVAL(&tv, &ts); | TIMESPEC_TO_TIMEVAL(&tv, &ts); | ||||
callout_reset(&it->it_callout, tvtohz(&tv), | callout_reset(&it->it_callout, tvtohz(&tv), | ||||
realtimer_expire, it); | realtimer_expire, it); | ||||
} | } | ||||
itimer_enter(it); | itimer_enter(it); | ||||
ITIMER_UNLOCK(it); | ITIMER_UNLOCK(it); | ||||
itimer_fire(it); | itimer_fire(it); | ||||
ITIMER_LOCK(it); | ITIMER_LOCK(it); | ||||
itimer_leave(it); | itimer_leave(it); | ||||
} else if (timespecisset(&it->it_time.it_value)) { | } else if (timespecisset(&it->it_time.it_value)) { | ||||
ts = it->it_time.it_value; | ts = it->it_time.it_value; | ||||
timespecsub(&ts, &cts); | timespecsub(&ts, &cts, &ts); | ||||
TIMESPEC_TO_TIMEVAL(&tv, &ts); | TIMESPEC_TO_TIMEVAL(&tv, &ts); | ||||
callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire, | callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire, | ||||
it); | it); | ||||
} | } | ||||
} | } | ||||
void | void | ||||
itimer_fire(struct itimer *it) | itimer_fire(struct itimer *it) | ||||
▲ Show 20 Lines • Show All 94 Lines • Show Last 20 Lines |