From 9c4dcffca5c7b31d7ff4ce77146ad87559bf70ef Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 13 Jun 2013 14:26:09 +0200 Subject: [PATCH] iochannel: Avoid unnecessary wakeup after successful write To save some CPU (in low latency scenarios), don't re-enable the "writable" event after it has succeeded. It is very likely the next write will succeed right away too. This means that we always need to handle EAGAIN/EWOULDBLOCK as a successful write of 0 bytes, so I also verified that all callers to pa_iochannel_write handled this correctly. Signed-off-by: David Henningsson --- src/modules/module-esound-sink.c | 2 +- src/pulsecore/iochannel.c | 17 ++++++++++++++--- src/pulsecore/ioline.c | 7 ++----- src/pulsecore/protocol-esound.c | 4 ---- src/pulsecore/protocol-http.c | 4 ---- src/pulsecore/protocol-simple.c | 4 ---- 6 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 40ef5bc1d..9cb7a717f 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -345,7 +345,7 @@ static int do_write(struct userdata *u) { if (u->write_data) { pa_assert(u->write_index < u->write_length); - if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) { + if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) < 0) { pa_log("write() failed: %s", pa_cstrerror(errno)); return -1; } diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index fa3d76770..ed8be239d 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -223,11 +223,22 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { pa_assert(l); pa_assert(io->ofd >= 0); - if ((r = pa_write(io->ofd, data, l, &io->ofd_type)) >= 0) { - io->writable = io->hungup = FALSE; - enable_events(io); + r = pa_write(io->ofd, data, l, &io->ofd_type); + + if ((size_t) r == l) + return r; /* Fast path - we almost always successfully write everything */ + + if (r < 0) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) + r = 0; + else + return r; } + /* Partial write - let's get a notification when we can write more */ + io->writable = io->hungup = FALSE; + enable_events(io); + return r; } diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c index a18188df3..a5572e9f7 100644 --- a/src/pulsecore/ioline.c +++ b/src/pulsecore/ioline.c @@ -351,12 +351,9 @@ static int do_write(pa_ioline *l) { while (l->io && !l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length > 0) { - if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) <= 0) { + if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) { - if (r < 0 && errno == EAGAIN) - break; - - if (r < 0 && errno != EPIPE) + if (errno != EPIPE) pa_log("write(): %s", pa_cstrerror(errno)); failure(l, FALSE); diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 52aa2c507..ff4afc6df 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -1226,10 +1226,6 @@ static int do_write(connection *c) { pa_memblock_unref(chunk.memblock); if (r < 0) { - - if (r < 0 && (errno == EINTR || errno == EAGAIN)) - return 0; - pa_log("write(): %s", pa_cstrerror(errno)); return -1; } diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c index 400150fb4..52571d3bb 100644 --- a/src/pulsecore/protocol-http.c +++ b/src/pulsecore/protocol-http.c @@ -162,10 +162,6 @@ static int do_write(struct connection *c) { pa_memblock_unref(chunk.memblock); if (r < 0) { - - if (errno == EINTR || errno == EAGAIN) - return 0; - pa_log("write(): %s", pa_cstrerror(errno)); return -1; } diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 9242e68d8..0e7c6e0a7 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -229,10 +229,6 @@ static int do_write(connection *c) { pa_memblock_unref(chunk.memblock); if (r < 0) { - - if (errno == EINTR || errno == EAGAIN) - return 0; - pa_log("write(): %s", pa_cstrerror(errno)); return -1; }