When doing a blocking write, keep looping until all the bytes are

written without returning to the caller. This only occurs on pipes
where either the number of bytes written is greater than the pipe
buffer or if there is insufficient space in the pipe buffer because the
reader is reading slower than the writer is writing.
This commit is contained in:
jb 1998-05-25 21:45:52 +00:00
parent 54a1a03bba
commit ba8f020407
6 changed files with 318 additions and 60 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}