Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Jan 1998 12:08:19 +1030
From:      Mike Smith <mike@smith.net.au>
To:        daniel_sobral@voga.com.br
Cc:        mike@smith.net.au, hackers@FreeBSD.ORG
Subject:   Re: uiomove() 
Message-ID:  <199801240138.MAA00419@word.smith.net.au>
In-Reply-To: Your message of "Fri, 23 Jan 1998 16:19:36 -0300." <83256595.006A05B5.00@papagaio.voga.com.br> 

next in thread | previous in thread | raw e-mail | index | archive | help
> 
> > There are a few other things I left out, particularly the correct
> > handling of returns from tsleep() when PCATCH is specified.
> 
> Yup... I forgot to bother you about that... Currently, I'm not PCATCHing
> and what the hell, but I intend to be more politically correct. I just have
> not figured exactly what I'm supposed to do at ERESTART.

OK.  Here's a more "politically correct" read() routine.  You should be 
able to mirror this into a write() fairly easily.


foo_read()
{
	int	s, result, hmany, got;
	struct foo_softc *sc = ...

	got = 0;

	while (uio->uio_resid > 0) {
		s = splfoo();
		while (!result && (sc->ready == 0)) {
			if (flags & F_NONBLOCK)
				result = EWOUDLBLOCK;
			else
				result = tsleep(&sc->ready, PRIFOO | PCATCH,
						"fooread", 0);
			if (result = ERESTART)
				if (got == 0)
					result = 0;
				else
					result = EINTR;
		}
		splx(s);
		if (result)
			return(result);
		hmany = min(sc->ready, uio->uio_resid);
		result = uiomove(sc->buf, hmany, uio);
		if (result)
			return(result);
		s = splfoo();
		if (hmany < sc->ready)
			bcopy(sc->buf + hmany, sc->buf, sc->ready - hmany);
		sc->ready -= hmany;
		splx(s);
		got += hmany;
	}
	return(0);
}

This implements the policy "If a signal is received we will return a 
short read count, except where that count would be zero" (because 
returning EOF tends to upset some people 8).

You might want to always convert ERESTART to EINTR (always error on 
interrupt), but that becomes more complex as you may already have 
consumed data from the read buffer, which may throw your caller out of 
sync.

Another approach is to ignore ERESTART, ie. never return a short count.
That's also quite legitimate with the above code, ie. 

	if (result == ERESTART) 
		result = 0;

-- 
\\  Sometimes you're ahead,       \\  Mike Smith
\\  sometimes you're behind.      \\  mike@smith.net.au
\\  The race is long, and in the  \\  msmith@freebsd.org
\\  end it's only with yourself.  \\ 





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199801240138.MAA00419>