From f9a0273cd8017d27e81e314f067b0d5197918d68 Mon Sep 17 00:00:00 2001 From: simonmar Date: Fri, 10 Mar 2000 15:23:40 +0000 Subject: [PATCH] [project @ 2000-03-10 15:23:40 by simonmar] Fix h{Fill,Put}Buf(BA)?. They now work in the presence of partial/blocking reads and writes, and hPutBuf now doesn't hold on to the handle while it's blocking. --- ghc/lib/std/cbits/readFile.c | 43 ++++++++++++++++++++++++++--------------- ghc/lib/std/cbits/stgio.h | 8 ++++---- ghc/lib/std/cbits/writeFile.c | 37 +++++++++++++++++++++++------------ 3 files changed, 56 insertions(+), 32 deletions(-) diff --git a/ghc/lib/std/cbits/readFile.c b/ghc/lib/std/cbits/readFile.c index 432a738..a68f3aa 100644 --- a/ghc/lib/std/cbits/readFile.c +++ b/ghc/lib/std/cbits/readFile.c @@ -1,7 +1,7 @@ /* * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998 * - * $Id: readFile.c,v 1.10 2000/01/18 12:42:12 simonmar Exp $ + * $Id: readFile.c,v 1.11 2000/03/10 15:23:40 simonmar Exp $ * * hGetContents Runtime Support */ @@ -105,8 +105,19 @@ readBlock(StgForeignPtr ptr) } /* Filling up a (block-buffered) buffer of length len */ + +/* readChunk(FileObjet *, void *, int) + * returns: + * -1 error + * -2 object closed + * FILEOBJ_BLOCKED_CONN_WRITE blocking while flushing + * buffer of connected handle. + * FILEOBJ_BLOCKED_READ didn't read anything; would block + * n, where n > 0 read n bytes into buffer. + */ + StgInt -readChunk(StgForeignPtr ptr, StgAddr buf, StgInt len) +readChunk(StgForeignPtr ptr, StgAddr buf, StgInt off, StgInt len) { IOFileObject* fo = (IOFileObject*)ptr; int count=0,rc=0, total_count; @@ -159,7 +170,7 @@ readChunk(StgForeignPtr ptr, StgAddr buf, StgInt len) return count; len -= count; - p = buf; + p = buf+off; p += count; total_count = count; @@ -172,28 +183,28 @@ readChunk(StgForeignPtr ptr, StgAddr buf, StgInt len) #else read(fd, p, len))) <= 0 ) { #endif - if ( count == 0 ) { /* EOF */ - break; + /* EOF */ + if ( count == 0 ) { + FILEOBJ_SET_EOF(fo); + return total_count; + + /* Blocking */ } else if ( count == -1 && errno == EAGAIN) { - /* ToDo: partial/blocked reads?????? Looks like we don't recover - * from this properly. - */ errno = 0; - return FILEOBJ_BLOCKED_READ; + if (total_count > 0) + return total_count; /* partial read */ + else + return FILEOBJ_BLOCKED_READ; + + /* Error */ } else if ( count == -1 && errno != EINTR) { cvtErrno(); stdErrno(); return -1; - } - total_count += count; - len -= count; - p += count; + } } total_count += count; - /* ToDo: might point beyond the end of the buffer??? */ - fo->bufWPtr = total_count; - fo->bufRPtr = 0; return total_count; } diff --git a/ghc/lib/std/cbits/stgio.h b/ghc/lib/std/cbits/stgio.h index fcda181..5203040 100644 --- a/ghc/lib/std/cbits/stgio.h +++ b/ghc/lib/std/cbits/stgio.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: stgio.h,v 1.16 1999/12/08 15:47:08 simonmar Exp $ + * $Id: stgio.h,v 1.17 2000/03/10 15:23:40 simonmar Exp $ * * (c) The GRASP/AQUA Project, Glasgow University, 1994-1999 * @@ -161,7 +161,7 @@ StgInt get_prog_argc(void); /* readFile.c */ StgInt readBlock (StgForeignPtr); -StgInt readChunk (StgForeignPtr,StgAddr,StgInt); +StgInt readChunk (StgForeignPtr,StgAddr,StgInt,StgInt); StgInt readLine (StgForeignPtr); StgInt readChar (StgForeignPtr); @@ -230,8 +230,8 @@ StgInt toClockSec (StgInt, StgInt, StgInt, StgInt, StgInt, StgInt, StgInt, StgBy /* writeError.c */ void writeErrString__ (StgAddr, StgByteArray, StgInt); /* writeFile.c */ -StgInt writeBuf (StgForeignPtr, StgAddr, StgInt); -StgInt writeBufBA (StgForeignPtr, StgByteArray, StgInt); +StgInt writeBuf (StgForeignPtr, StgAddr, StgInt, StgInt); +StgInt writeBufBA (StgForeignPtr, StgByteArray, StgInt, StgInt); StgInt writeFileObject (StgForeignPtr, StgInt); StgInt writeBuffer (StgForeignPtr, StgInt); diff --git a/ghc/lib/std/cbits/writeFile.c b/ghc/lib/std/cbits/writeFile.c index 5255ea9..eed60e9 100644 --- a/ghc/lib/std/cbits/writeFile.c +++ b/ghc/lib/std/cbits/writeFile.c @@ -1,7 +1,7 @@ /* * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998 * - * $Id: writeFile.c,v 1.12 1999/12/08 15:47:08 simonmar Exp $ + * $Id: writeFile.c,v 1.13 2000/03/10 15:23:40 simonmar Exp $ * * hPutStr Runtime Support */ @@ -82,15 +82,21 @@ writeBuffer(StgForeignPtr ptr, StgInt bytes) } +/* ToDo: there's currently no way for writeBuf to return both a + * partial write and an indication that the write blocked. It needs + * two calls: one to get the partial result, and the next one to block. + * This matches Unix write/2, but is rather a waste. + */ + StgInt -writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len) +writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt off, StgInt len) { IOFileObject* fo = (IOFileObject*)ptr; - int count; + int count, total_count; int rc = 0; - char *pBuf = (char *) buf; + char *pBuf = (char *) buf+off; - if (len == 0 ) + if (len == 0) return 0; /* First of all, check if we do need to flush the buffer .. */ @@ -100,10 +106,10 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len) if ( fo->buf != NULL && /* buffered and */ (fo->bufWPtr + len < (fo->bufSize)) /* there's room */ ) { - /* Block copying is likely to be cheaper than, flush, followed by write */ - memcpy(((char*)fo->buf + fo->bufWPtr), buf, len); + /* Block copying is likely to be cheaper than flush, followed by write */ + memcpy(((char*)fo->buf + fo->bufWPtr), pBuf, len); fo->bufWPtr += len; - return 0; + return len; } /* If we do overflow, flush current contents of the buffer and directly output the chunk. @@ -120,6 +126,8 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len) } } + total_count = 0; + while ((count = ( #ifdef USE_WINSOCK @@ -132,10 +140,14 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len) if ( count >= 0 ) { len -= count; pBuf += count; + total_count += count; continue; } else if ( errno == EAGAIN ) { errno = 0; - return FILEOBJ_BLOCKED_WRITE; + if (total_count > 0) + return total_count; /* partial write */ + else + return FILEOBJ_BLOCKED_WRITE; } else if ( errno != EINTR ) { cvtErrno(); stdErrno(); @@ -143,11 +155,12 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len) } } - return 0; + total_count += count; + return total_count; } StgInt -writeBufBA(StgForeignPtr ptr, StgByteArray buf, StgInt len) +writeBufBA(StgForeignPtr ptr, StgByteArray buf, StgInt off, StgInt len) { - return (writeBuf(ptr,(StgAddr)buf, len)); + return (writeBuf(ptr,(StgAddr)buf, off, len)); } -- 1.7.10.4