diff --git a/src/coio.cc b/src/coio.cc
index 48fca73e42246acf6205c6a595c8113fb4476de5..09a3f18cf29adde151fe5cf4f81e424dd6d67cba 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -442,13 +442,14 @@ coio_flush(int fd, struct iovec *iov, ssize_t offset, int iovcnt)
 }
 
 ssize_t
-coio_writev(struct ev_io *coio, struct iovec *iov, int iovcnt,
-	    size_t size_hint)
+coio_writev_timeout(struct ev_io *coio, struct iovec *iov, int iovcnt,
+		    size_t size_hint, ev_tstamp timeout)
 {
 	ssize_t total = 0;
 	size_t iov_len = 0;
 	struct iovec *end = iov + iovcnt;
-
+	ev_tstamp start, delay;
+	coio_timeout_init(&start, &delay, timeout);
 	CoioGuard coio_guard(coio);
 
 	/* Avoid a syscall in case of 0 iovcnt. */
@@ -476,8 +477,20 @@ coio_writev(struct ev_io *coio, struct iovec *iov, int iovcnt,
 			ev_io_start(loop(), coio);
 		}
 		/* Yield control to other fibers. */
-		coio_fiber_yield(coio);
 		fiber_testcancel();
+		/*
+		 * Yield control to other fibers until the
+		 * timeout is reached or the socket is
+		 * ready.
+		 */
+		bool is_timedout = coio_fiber_yield_timeout(coio, delay);
+		fiber_testcancel();
+
+		if (is_timedout) {
+			errno = ETIMEDOUT;
+			return total;
+		}
+		coio_timeout_update(start, &delay);
 	}
 	return total;
 }
diff --git a/src/coio.h b/src/coio.h
index 702602ca126b29990d91a829a9b269dce20c0bac..46edc8a8e712298d729fad0aa321baeb0903d30b 100644
--- a/src/coio.h
+++ b/src/coio.h
@@ -132,7 +132,14 @@ coio_write(struct ev_io *coio, const void *buf, size_t sz)
 }
 
 ssize_t
-coio_writev(struct ev_io *coio, struct iovec *iov, int iovcnt, size_t size);
+coio_writev_timeout(struct ev_io *coio, struct iovec *iov, int iovcnt,
+		    size_t size, ev_tstamp timeout);
+
+static inline ssize_t
+coio_writev(struct ev_io *coio, struct iovec *iov, int iovcnt, size_t size)
+{
+	return coio_writev_timeout(coio, iov, iovcnt, size, TIMEOUT_INFINITY);
+}
 
 ssize_t
 coio_sendto_timeout(struct ev_io *coio, const void *buf, size_t sz, int flags,