changeset 397:9fc33f5be435

Add support for readv()/writev()
author gthomas
date Sun, 03 Nov 2002 19:49:23 +0000
parents 256f9ccc0c3c
children a3b06a9328a7
files packages/io/fileio/current/ChangeLog packages/io/fileio/current/cdl/fileio.cdl packages/io/fileio/current/src/io.cxx
diffstat 3 files changed, 68 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/packages/io/fileio/current/ChangeLog
+++ b/packages/io/fileio/current/ChangeLog
@@ -1,3 +1,8 @@
+2002-11-03  Gary Thomas  <gthomas@ecoscentric.com>
+
+	* src/io.cxx: 
+	* cdl/fileio.cdl: Add readv()/writev() support.
+
 2002-08-08  Nick Garnett  <nickg@calivar.demon.co.uk>
 
 	* src/select.cxx (select): Changed mechanism for calculating
--- a/packages/io/fileio/current/cdl/fileio.cdl
+++ b/packages/io/fileio/current/cdl/fileio.cdl
@@ -198,6 +198,21 @@ cdl_package CYGPKG_IO_FILEIO {
         }
     }
 
+    cdl_option CYGNUM_FILEIO_IOVEC_MAX {
+	display          "Maximum size of iovec used by readv/writev"
+	flavor           data
+	default_value    16
+	legal_values     1 to 9999999
+	description      "This option controls the maximum size of the iovec
+                          structure that can be used by readv()/writev().  This
+                          limit is required because the iovec structure must be
+                          invariant (to the user), thus a copy needs to be made
+                          by the interface routines.  The limit is merely a 
+                          control over the amount of stack space used by the
+                          readv()/writev() functions."
+
+    }
+
     # ----------------------------------------------------------------
     # Tests
 
--- a/packages/io/fileio/current/src/io.cxx
+++ b/packages/io/fileio/current/src/io.cxx
@@ -9,6 +9,7 @@
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Gary Thomas
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
@@ -75,21 +76,34 @@
 #define UNLOCK_FILE( fp ) cyg_file_unlock( fp, fp->f_syncmode )
 
 //==========================================================================
-// Read from or write to a file
-// This is a common routine for doing both read and write
-// operations. The direction argument controls slight the differences
-// between them.
+// Common wrapper for read/write using an iovec descriptor 
+// 'direction' should be O_RDONLY for readv, O_WRONLY for writev
 
-static ssize_t readwrite( int fd, void *buf, size_t len, int direction )
+static ssize_t 
+readwritev( int fd, const cyg_iovec *_iov, int iov_len, int direction )
 {
     FILEIO_ENTRY();
 
     CYG_CANCELLATION_POINT;
     
-    ssize_t cnt;
-    int ret;
+    ssize_t cnt, len;
+    int ret, _idx;
     cyg_file *fp;
+    cyg_iovec iov[CYGNUM_FILEIO_IOVEC_MAX];
     
+    if( iov_len > CYGNUM_FILEIO_IOVEC_MAX )
+        FILEIO_RETURN(EINVAL);
+
+    // Copy 'iovec' structure since it's supposed to be "const"
+    // and some lower level routines might want to change it.
+    // Also accumulate the length of the total I/O request
+    len = 0;
+    for (_idx = 0;  _idx < iov_len;  _idx++) {
+        len += _iov[_idx].iov_len;
+        iov[_idx].iov_base = _iov[_idx].iov_base;
+        iov[_idx].iov_len = _iov[_idx].iov_len;
+    }
+
     if( len > SSIZE_MAX )
         FILEIO_RETURN(EINVAL);
     
@@ -105,13 +119,10 @@ static ssize_t readwrite( int fd, void *
     }
 
     cyg_uio uio;
-    cyg_iovec iov;
     cyg_fileop_readwrite *op;
     
-    iov.iov_base        = buf;
-    iov.iov_len         = len;
-    uio.uio_iov         = &iov;
-    uio.uio_iovcnt      = 1;
+    uio.uio_iov         = iov;
+    uio.uio_iovcnt      = iov_len;
     uio.uio_resid       = len;
     uio.uio_segflg      = UIO_USERSPACE;
 
@@ -121,7 +132,6 @@ static ssize_t readwrite( int fd, void *
         uio.uio_rw = UIO_READ, op = fp->f_ops->fo_read;
     else
         uio.uio_rw = UIO_WRITE, op = fp->f_ops->fo_write;
-
         
     LOCK_FILE( fp );
     
@@ -146,7 +156,11 @@ static ssize_t readwrite( int fd, void *
 
 __externC ssize_t read( int fd, void *buf, size_t len )
 {
-    return readwrite( fd, buf, len, O_RDONLY );
+    cyg_iovec _iov;
+
+    _iov.iov_base = buf;
+    _iov.iov_len = len;
+    return readwritev(fd, &_iov, 1, O_RDONLY);
 }
 
 //==========================================================================
@@ -154,10 +168,29 @@ static ssize_t readwrite( int fd, void *
 
 __externC ssize_t write( int fd, const void *buf, size_t len )
 {
-    return readwrite( fd, (void *)buf, len, O_WRONLY );
+    cyg_iovec _iov;
+
+    _iov.iov_base = (void *)buf;
+    _iov.iov_len = len;
+    return readwritev(fd, &_iov, 1, O_WRONLY);
 }
 
 //==========================================================================
+// Read via an iovec
+__externC ssize_t readv( int fd, const cyg_iovec *_iov, int iov_len )
+{
+    return readwritev(fd, _iov, iov_len, O_RDONLY);
+}
+
+//==========================================================================
+// Write via an iovec
+__externC ssize_t writev( int fd, const cyg_iovec *_iov, int iov_len )
+{
+    return readwritev(fd, _iov, iov_len, O_WRONLY);
+}
+
+
+//==========================================================================
 // Close a file
 
 __externC int close( int fd )