nanosleep() replacement Take 2

Darren Tucker dtucker at zip.com.au
Tue Mar 18 11:51:29 EST 2003


Tim Rice wrote:

Combining replies here,

[about my modified nanosleep]
> Something isn't quite right with this version.
> When I try this I get
> scp -l 512 openssh/sshd.o uw711:/tmp
> sshd.o             100%   84KB  84.1KB/s   00:01
> scp -l 256 openssh/sshd.o uw711:/tmp
> sshd.o             100%   84KB  42.0KB/s   00:02
> scp -l 128 openssh/sshd.o uw711:/tmp
> sshd.o             100%   84KB  42.0KB/s   00:02
> scp -l 64 openssh/sshd.o uw711:/tmp
> sshd.o             100%   84KB  42.0KB/s   00:02
> scp -l 8 openssh/sshd.o uw711:/tmp
> sshd.o             100%   84KB  42.0KB/s   00:02
> scp -l 1 openssh/sshd.o uw711:/tmp
> sshd               100%   84KB  42.0KB/s   00:02

Difference in select() behaviour between patforms?  Here's what I get
from the same function on Solaris 8:

$ for bw in 512 256 128 64 8 1; do scp -l $bw testfile localhost:/tmp/;
done
+ scp -l 512 testfile localhost:/tmp/
testfile            100%   84KB  80.6KB/s   00:01
+ scp -l 256 testfile localhost:/tmp/
testfile            100%   84KB  41.0KB/s   00:02
+ scp -l 128 testfile localhost:/tmp/
testfile            100%   84KB  20.7KB/s   00:04
+ scp -l 64 testfile localhost:/tmp/
testfile            100%   84KB   9.2KB/s   00:09
+ scp -l 8 testfile localhost:/tmp/
testfile            100%   84KB   1.1KB/s   01:16
+ scp -l 1 testfile localhost:/tmp/
testfile             57%   48KB   0.1KB/s - stalled

[snip]

About the original function:

> +int nanosleep(const struct timespec *req, struct timespec *rem)
> +{
> +       int rc, saverrno;
> +       extern int errno;
> +       struct timeval tsave, ttmp, time2wait;
> +
> +       TIMESPEC_TO_TIMEVAL(&time2wait, req)
> +
> +       gettimeofday(&tsave, NULL);
> +       rc = select(0, NULL, NULL, NULL, &time2wait);
> +       if (rc == -1) {
> +               saverrno = errno;
> +               gettimeofday (&ttmp, NULL);
> +               errno = saverrno;

The following can sometimes end up with a tv_usec above 1,000,000 (not
sure if that matters). Consider this example:

tsave: tv_sec=100, tv_usec=999999
ttmp: tv_sec=101, tv_usec=1
time2wait: tv_sec=2, tv_usec=999999

> +               ttmp.tv_sec -= tsave.tv_sec;
> +               ttmp.tv_usec -= tsave.tv_usec;
	-> ttmp.tv_usec = -999,998

> +               tsave.tv_sec = (time2wait.tv_sec - ttmp.tv_sec);
> +               tsave.tv_usec = (time2wait.tv_usec - ttmp.tv_usec);
	-> tsave.tv_usec = 999,999 - -999,998
			 = 1,999,997

> +               if(tsave.tv_sec < 0){
> +                       tsave.tv_sec = 0;
> +                       tsave.tv_usec += 1000000L;
> +               }

How about something like:
if (rc == -1) {
	tsave.tv_sec = ttmp.tv_sec - tsave.tv_sec - time2wait.tv_sec;
	tsave.tv_usec = ttmp.tv_usec - tsave.tv_usec - time2wait.tv_usec;
	tsave.tv_sec += tsave.tv_usec / 1000000L;
	tsave.tv_usec %= 1000000L;
} else {
	tsave.tv_sec = 0;
	tsave.tv_usec = 0;
}

> +       }
> +       else {

" } else {" ?

> +               tsave.tv_sec = 0;
> +               tsave.tv_usec = 0;
> +       }
> +       TIMEVAL_TO_TIMESPEC(&tsave, rem)
> +
> +       return(rc);
> +}

-- 
Darren Tucker (dtucker at zip.com.au)
GPG Fingerprint D9A3 86E9 7EEE AF4B B2D4  37C9 C982 80C7 8FF4 FA69
    Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.




More information about the openssh-unix-dev mailing list