Don't restart a timeout wait in kern_sigtimedwait, also allow it

to wait longer than a single integer can represent.
This commit is contained in:
davidxu 2005-02-19 06:05:49 +00:00
parent f6b334da2c
commit 699536634e

View File

@ -846,10 +846,9 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
struct sigacts *ps; struct sigacts *ps;
sigset_t savedmask, sigset; sigset_t savedmask, sigset;
struct proc *p; struct proc *p;
int error; int error, sig, hz, i, timevalid = 0;
int sig; struct timespec rts, ets, ts;
int hz; struct timeval tv;
int i;
p = td->td_proc; p = td->td_proc;
error = 0; error = 0;
@ -859,6 +858,14 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
PROC_LOCK(p); PROC_LOCK(p);
ps = p->p_sigacts; ps = p->p_sigacts;
savedmask = td->td_sigmask; savedmask = td->td_sigmask;
if (timeout) {
if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) {
timevalid = 1;
getnanouptime(&rts);
ets = rts;
timespecadd(&ets, timeout);
}
}
again: again:
for (i = 1; i <= _SIG_MAXSIG; ++i) { for (i = 1; i <= _SIG_MAXSIG; ++i) {
@ -909,17 +916,18 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
* signals. * signals.
*/ */
if (timeout) { if (timeout) {
struct timeval tv; if (!timevalid) {
if (timeout->tv_nsec < 0 || timeout->tv_nsec > 1000000000) {
error = EINVAL; error = EINVAL;
goto out; goto out;
} }
if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) { getnanouptime(&rts);
if (timespeccmp(&rts, &ets, >=)) {
error = EAGAIN; error = EAGAIN;
goto out; goto out;
} }
TIMESPEC_TO_TIMEVAL(&tv, timeout); ts = ets;
timespecsub(&ts, &rts);
TIMESPEC_TO_TIMEVAL(&tv, &ts);
hz = tvtohz(&tv); hz = tvtohz(&tv);
} else } else
hz = 0; hz = 0;
@ -927,8 +935,15 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
td->td_waitset = &waitset; td->td_waitset = &waitset;
error = msleep(&ps, &p->p_mtx, PPAUSE|PCATCH, "sigwait", hz); error = msleep(&ps, &p->p_mtx, PPAUSE|PCATCH, "sigwait", hz);
td->td_waitset = NULL; td->td_waitset = NULL;
if (error == 0) /* surplus wakeup ? */ if (timeout) {
error = EINTR; if (error == ERESTART) {
/* timeout can not be restarted. */
error = EINTR;
} else if (error == EAGAIN) {
/* will calculate timeout by ourself. */
error = 0;
}
}
goto again; goto again;
out: out:
@ -946,6 +961,7 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info,
_STOPEVENT(p, S_SIG, sig); _STOPEVENT(p, S_SIG, sig);
SIGDELSET(td->td_siglist, sig); SIGDELSET(td->td_siglist, sig);
bzero(info, sizeof(*info));
info->si_signo = sig; info->si_signo = sig;
info->si_code = 0; info->si_code = 0;
} }