summaryrefslogtreecommitdiffstats
path: root/lib/libkse
diff options
context:
space:
mode:
authorjb <jb@FreeBSD.org>1998-05-25 21:45:52 +0000
committerjb <jb@FreeBSD.org>1998-05-25 21:45:52 +0000
commitba8f020407e5e217f39a38087c3a46f8d5c06663 (patch)
tree1dd612d4d3864e4c526e91d87945e185ffef8ddb /lib/libkse
parent54a1a03bbacad3589402df31156cbf1f19bb1236 (diff)
downloadFreeBSD-src-ba8f020407e5e217f39a38087c3a46f8d5c06663.zip
FreeBSD-src-ba8f020407e5e217f39a38087c3a46f8d5c06663.tar.gz
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.
Diffstat (limited to 'lib/libkse')
-rw-r--r--lib/libkse/thread/thr_write.c58
-rw-r--r--lib/libkse/thread/thr_writev.c68
2 files changed, 106 insertions, 20 deletions
diff --git a/lib/libkse/thread/thr_write.c b/lib/libkse/thread/thr_write.c
index f8be7da..773f615 100644
--- a/lib/libkse/thread/thr_write.c
+++ b/lib/libkse/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/libkse/thread/thr_writev.c b/lib/libkse/thread/thr_writev.c
index f3badec..23667be 100644
--- a/lib/libkse/thread/thr_writev.c
+++ b/lib/libkse/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);
}
OpenPOWER on IntegriCloud