Bypass itimerfix 100000000 limit in nanosleep1 using loop through timeouts
This commit is contained in:
parent
ccbdaeb2aa
commit
17e05ba7e2
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)kern_time.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: kern_time.c,v 1.29 1997/06/24 18:20:50 jhay Exp $
|
||||
* $Id: kern_time.c,v 1.30 1997/08/03 07:26:50 bde Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -210,59 +210,77 @@ nanosleep1(p, rqt, rmt)
|
||||
struct proc *p;
|
||||
struct timespec *rqt, *rmt;
|
||||
{
|
||||
struct timeval atv, utv;
|
||||
int error, s, timo;
|
||||
struct timeval atv, utv, rtv;
|
||||
int error, s, timo, i, n;
|
||||
|
||||
if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
|
||||
if (rqt->tv_sec < 0 || rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
|
||||
return (EINVAL);
|
||||
TIMESPEC_TO_TIMEVAL(&atv, rqt)
|
||||
if (itimerfix(&atv))
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* XXX this is not as careful as settimeofday() about minimising
|
||||
* interrupt latency. The hzto() interface is inconvenient as usual.
|
||||
*/
|
||||
s = splclock();
|
||||
timevaladd(&atv, &time);
|
||||
timo = hzto(&atv);
|
||||
splx(s);
|
||||
if (itimerfix(&atv)) {
|
||||
n = atv.tv_sec / 100000000;
|
||||
rtv = atv;
|
||||
rtv.tv_sec %= 100000000;
|
||||
(void)itimerfix(&rtv);
|
||||
} else
|
||||
n = 0;
|
||||
|
||||
p->p_sleepend = &atv;
|
||||
error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", timo);
|
||||
p->p_sleepend = NULL;
|
||||
|
||||
if (error == ERESTART)
|
||||
error = EINTR;
|
||||
if (error == EWOULDBLOCK)
|
||||
error = 0;
|
||||
if (rmt != NULL) {
|
||||
/*-
|
||||
* XXX this is unnecessary and possibly wrong if the timeout
|
||||
* expired. Then the remaining time should be zero. If the
|
||||
* calculation gives a nonzero value, then we have a bug.
|
||||
* (1) if settimeofday() was called, then the calculation is
|
||||
* probably wrong, since `time' has probably become
|
||||
* inconsistent with the ending time `atv'.
|
||||
* XXX (1) should be fixed now with p->p_sleepend;
|
||||
* (2) otherwise, our calculation of `timo' was wrong, perhaps
|
||||
* due to `tick' being wrong when hzto() was called or
|
||||
* changing afterwards (it can be wrong or change due to
|
||||
* hzto() not knowing about adjtime(2) or tickadj(8)).
|
||||
* Then we should be sleeping again instead instead of
|
||||
* returning. Rounding up in hzto() probably fixes this
|
||||
* problem for small timeouts, but the absolute error may
|
||||
* be large for large timeouts.
|
||||
for (i = 0, error = EWOULDBLOCK;
|
||||
i <= n && error == EWOULDBLOCK;
|
||||
i++) {
|
||||
if (n > 0) {
|
||||
if (i == n)
|
||||
atv = rtv;
|
||||
else {
|
||||
atv.tv_sec = 100000000;
|
||||
atv.tv_usec = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* XXX this is not as careful as settimeofday() about minimising
|
||||
* interrupt latency. The hzto() interface is inconvenient as usual.
|
||||
*/
|
||||
s = splclock();
|
||||
utv = time;
|
||||
timevaladd(&atv, &time);
|
||||
timo = hzto(&atv);
|
||||
splx(s);
|
||||
timevalsub(&atv, &utv);
|
||||
if (atv.tv_sec < 0)
|
||||
timerclear(&atv);
|
||||
TIMEVAL_TO_TIMESPEC(&atv, rmt);
|
||||
|
||||
p->p_sleepend = &atv;
|
||||
error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", timo);
|
||||
p->p_sleepend = NULL;
|
||||
|
||||
if (error == ERESTART)
|
||||
error = EINTR;
|
||||
if (rmt != NULL && (i == n || error != EWOULDBLOCK)) {
|
||||
/*-
|
||||
* XXX this is unnecessary and possibly wrong if the timeout
|
||||
* expired. Then the remaining time should be zero. If the
|
||||
* calculation gives a nonzero value, then we have a bug.
|
||||
* (1) if settimeofday() was called, then the calculation is
|
||||
* probably wrong, since `time' has probably become
|
||||
* inconsistent with the ending time `atv'.
|
||||
* XXX (1) should be fixed now with p->p_sleepend;
|
||||
* (2) otherwise, our calculation of `timo' was wrong, perhaps
|
||||
* due to `tick' being wrong when hzto() was called or
|
||||
* changing afterwards (it can be wrong or change due to
|
||||
* hzto() not knowing about adjtime(2) or tickadj(8)).
|
||||
* Then we should be sleeping again instead instead of
|
||||
* returning. Rounding up in hzto() probably fixes this
|
||||
* problem for small timeouts, but the absolute error may
|
||||
* be large for large timeouts.
|
||||
*/
|
||||
s = splclock();
|
||||
utv = time;
|
||||
splx(s);
|
||||
timevalsub(&atv, &utv);
|
||||
if (atv.tv_sec < 0)
|
||||
timerclear(&atv);
|
||||
if (n > 0)
|
||||
atv.tv_sec += (n - i) * 100000000;
|
||||
TIMEVAL_TO_TIMESPEC(&atv, rmt);
|
||||
}
|
||||
}
|
||||
return (error);
|
||||
return (error == EWOULDBLOCK ? 0 : error);
|
||||
}
|
||||
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
|
Loading…
Reference in New Issue
Block a user