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 | |
| parent | de285a13cc4e014d903ebd93769d8a50b446c9f4 (diff) | |
Notes
Diffstat (limited to 'lib/libpthread')
| -rw-r--r-- | lib/libpthread/thread/thr_write.c | 58 | ||||
| -rw-r--r-- | lib/libpthread/thread/thr_writev.c | 68 | 
2 files changed, 106 insertions, 20 deletions
| diff --git a/lib/libpthread/thread/thr_write.c b/lib/libpthread/thread/thr_write.c index f8be7da47450..773f61546f26 100644 --- a/lib/libpthread/thread/thr_write.c +++ b/lib/libpthread/thread/thr_write.c @@ -29,7 +29,7 @@   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF   * SUCH DAMAGE.   * - * $Id: uthread_write.c,v 1.4 1998/02/13 01:27:33 julian Exp $ + * $Id: uthread_write.c,v 1.5 1998/04/29 09:59:33 jb Exp $   *   */  #include <sys/types.h> @@ -44,15 +44,42 @@  ssize_t  write(int fd, const void *buf, size_t nbytes)  { -	int	ret; +	int	blocking; +	int	status; +	ssize_t n; +	ssize_t num = 0; +	ssize_t	ret;  	/* Lock the file descriptor for write: */  	if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL,  	    __FILE__, __LINE__)) == 0) { -		/* Perform a non-blocking write syscall: */ -		while ((ret = _thread_sys_write(fd, buf, nbytes)) < 0) { -			if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && -			    (errno == EWOULDBLOCK || errno == EAGAIN)) { +		/* 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_write(fd, buf + num, nbytes - num); + +			/* Check if one or more bytes were written: */ +			if (n > 0) +				/* +				 * 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 < nbytes)) {  				_thread_run->data.fd.fd = fd;  				_thread_kern_set_timeout(NULL); @@ -67,13 +94,24 @@ write(int fd, const void *buf, size_t nbytes)  				 * 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 >= nbytes) +				/* Return the number of bytes written: */ +				ret = num;  		}  		_thread_fd_unlock(fd, FD_RDWR);  	} 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);  	} | 
