From owner-freebsd-hackers Fri Jan 23 17:46:12 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id RAA09606 for hackers-outgoing; Fri, 23 Jan 1998 17:46:12 -0800 (PST) (envelope-from owner-freebsd-hackers@FreeBSD.ORG) Received: from word.smith.net.au (ppp7.portal.net.au [202.12.71.107]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id RAA09556 for ; Fri, 23 Jan 1998 17:46:00 -0800 (PST) (envelope-from mike@word.smith.net.au) Received: from word (localhost [127.0.0.1]) by word.smith.net.au (8.8.8/8.8.5) with ESMTP id MAA00419; Sat, 24 Jan 1998 12:08:20 +1030 (CST) Message-Id: <199801240138.MAA00419@word.smith.net.au> X-Mailer: exmh version 2.0zeta 7/24/97 To: daniel_sobral@voga.com.br cc: mike@smith.net.au, hackers@FreeBSD.ORG Subject: Re: uiomove() In-reply-to: Your message of "Fri, 23 Jan 1998 16:19:36 -0300." <83256595.006A05B5.00@papagaio.voga.com.br> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Sat, 24 Jan 1998 12:08:19 +1030 From: Mike Smith Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk > > > 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. \\