diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -175,7 +175,8 @@ static inline void umtx_abs_timeout_init2(struct umtx_abs_timeout *timo, const struct _umtx_time *umtxtime); -static int umtx_abs_timeout_gethz(struct umtx_abs_timeout *timo); +static int umtx_abs_timeout_getsbt(struct umtx_abs_timeout *timo, + sbintime_t *sbt, int *flags); static inline void umtx_abs_timeout_update(struct umtx_abs_timeout *timo); static void umtx_shm_init(void); @@ -717,14 +718,33 @@ } static int -umtx_abs_timeout_gethz(struct umtx_abs_timeout *timo) +umtx_abs_timeout_getsbt(struct umtx_abs_timeout *timo, sbintime_t *sbt, + int *flags) { struct timespec tts; if (timespeccmp(&timo->end, &timo->cur, <=)) - return (-1); + return (ETIMEDOUT); timespecsub(&timo->end, &timo->cur, &tts); - return (tstohz(&tts)); + switch (timo->clockid) { + case CLOCK_REALTIME: + case CLOCK_REALTIME_PRECISE: + case CLOCK_MONOTONIC: + case CLOCK_MONOTONIC_PRECISE: + case CLOCK_UPTIME: + case CLOCK_UPTIME_PRECISE: + if (tts.tv_sec >= (SBT_MAX >> 32)) + *sbt = SBT_MAX; + else + *sbt = tstosbt(tts); + *flags = 0; + break; + default: + *sbt = tick_sbt * tstohz(&tts); + *flags = C_HARDCLOCK; + break; + } + return (0); } static uint32_t @@ -749,7 +769,8 @@ struct umtx_abs_timeout *abstime) { struct umtxq_chain *uc; - int error, timo; + sbintime_t sbt = 0; + int error, flags = 0; if (abstime != NULL && abstime->is_abs_real) { curthread->td_rtcgen = atomic_load_acq_int(&rtc_generation); @@ -764,14 +785,12 @@ break; } if (abstime != NULL) { - timo = umtx_abs_timeout_gethz(abstime); - if (timo < 0) { - error = ETIMEDOUT; + error = umtx_abs_timeout_getsbt(abstime, &sbt, &flags); + if (error != 0) break; - } - } else - timo = 0; - error = msleep(uq, &uc->uc_lock, PCATCH | PDROP, wmesg, timo); + } + error = msleep_sbt(uq, &uc->uc_lock, PCATCH | PDROP, wmesg, + sbt, 0, flags); if (error == EINTR || error == ERESTART) { umtxq_lock(&uq->uq_key); break;