diff options
Diffstat (limited to 'lib/libc_r/uthread/uthread_writev.c')
-rw-r--r-- | lib/libc_r/uthread/uthread_writev.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/lib/libc_r/uthread/uthread_writev.c b/lib/libc_r/uthread/uthread_writev.c index f40e611..2a3c0c8 100644 --- a/lib/libc_r/uthread/uthread_writev.c +++ b/lib/libc_r/uthread/uthread_writev.c @@ -42,22 +42,31 @@ ssize_t writev(int fd, const struct iovec * iov, int iovcnt) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read and write: */ + if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking writev syscall: */ while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDW_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ writev(int fd, const struct iovec * iov, int iovcnt) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_RDWR); - } + _thread_fd_unlock(fd, FD_RDWR); } return (ret); } |