diff options
| author | John Birrell <jb@FreeBSD.org> | 1998-05-25 21:45:52 +0000 |
|---|---|---|
| committer | John Birrell <jb@FreeBSD.org> | 1998-05-25 21:45:52 +0000 |
| commit | e5a8a007e163e2dc2dcba9cabcabc1279f351686 (patch) | |
| tree | d645d6ba4e750cb620fae54b9eada4eb93d7be32 /lib/libpthread/thread/thr_writev.c | |
| parent | de285a13cc4e014d903ebd93769d8a50b446c9f4 (diff) | |
Notes
Diffstat (limited to 'lib/libpthread/thread/thr_writev.c')
| -rw-r--r-- | lib/libpthread/thread/thr_writev.c | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/lib/libpthread/thread/thr_writev.c b/lib/libpthread/thread/thr_writev.c index f3badecb7aa5..23667bed8fcb 100644 --- a/lib/libpthread/thread/thr_writev.c +++ b/lib/libpthread/thread/thr_writev.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: uthread_writev.c,v 1.4 1998/02/13 01:27:34 julian Exp $ + * $Id: uthread_writev.c,v 1.5 1998/04/29 09:59:34 jb Exp $ * */ #include <sys/types.h> @@ -44,15 +44,52 @@ ssize_t writev(int fd, const struct iovec * iov, int iovcnt) { - int ret; + int blocking; + int status; + ssize_t n; + ssize_t num = 0; + ssize_t ret; + struct iovec liov; /* Lock the file descriptor for write: */ if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL, __FILE__, __LINE__)) == 0) { - /* Perform a non-blocking writev syscall: */ - while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) { - if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && - (errno == EWOULDBLOCK || errno == EAGAIN)) { + /* Make a local copy of the caller's iov: */ + liov.iov_base = iov->iov_base; + liov.iov_len = iov->iov_len; + + /* Check if file operations are to block */ + blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0); + + /* + * Loop while no error occurs and until the expected number + * of bytes are written if performing a blocking write: + */ + while (ret == 0) { + /* Perform a non-blocking write syscall: */ + n = _thread_sys_writev(fd, &liov, iovcnt - num); + + /* Check if one or more bytes were written: */ + if (n > 0) { + /* Update the local iov: */ + liov.iov_base += n; + liov.iov_len += n; + + /* + * Keep a count of the number of bytes + * written: + */ + num += n; + } + + /* + * If performing a blocking write, check if the + * write would have blocked or if some bytes + * were written but there are still more to + * write: + */ + if (blocking && ((n < 0 && (errno == EWOULDBLOCK || + errno == EAGAIN)) || num < iovcnt)) { _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); @@ -67,13 +104,24 @@ writev(int fd, const struct iovec * iov, int iovcnt) * interrupted by a signal */ if (_thread_run->interrupted) { - errno = EINTR; + /* Return an error: */ ret = -1; - break; } - } else { + + /* + * If performing a non-blocking write or if an + * error occurred, just return whatever the write + * syscall did: + */ + } else if (!blocking || n < 0) { + /* A non-blocking call might return zero: */ + ret = n; break; - } + + /* Check if the write has completed: */ + } else if (num >= iovcnt) + /* Return the number of bytes written: */ + ret = num; } _thread_fd_unlock(fd, FD_RDWR); } |
