From 860be2e70b33ff5eeb9130f80c4b1c096a2a8f27 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 22:42:01 +0000 Subject: try to use send(,,MSG_NOSIGNAL) instead of write() wherever possible (which will allow us to drop the SIGPIPE check). Cache the results of the last write()/send() to make sure that we do not issue more than necessary system calls. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1083 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/authkey.c | 6 ++-- src/pulsecore/core-util.c | 83 +++++++++++++++++++++++++++++++++-------------- src/pulsecore/core-util.h | 8 ++--- src/pulsecore/iochannel.c | 6 ++-- src/pulsecore/pid.c | 4 +-- src/pulsecore/random.c | 2 +- 6 files changed, 72 insertions(+), 37 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c index 064209d9..a5df3ed1 100644 --- a/src/pulsecore/authkey.c +++ b/src/pulsecore/authkey.c @@ -53,7 +53,7 @@ static int generate(int fd, void *ret_data, size_t length) { lseek(fd, 0, SEEK_SET); ftruncate(fd, 0); - if ((r = pa_loop_write(fd, ret_data, length)) < 0 || (size_t) r != length) { + if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) { pa_log(__FILE__": failed to write cookie file: %s", pa_cstrerror(errno)); return -1; } @@ -84,7 +84,7 @@ static int load(const char *fn, void *data, size_t length) { unlock = pa_lock_fd(fd, 1) >= 0; - if ((r = pa_loop_read(fd, data, length)) < 0) { + if ((r = pa_loop_read(fd, data, length, NULL)) < 0) { pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } @@ -188,7 +188,7 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) { unlock = pa_lock_fd(fd, 1) >= 0; - if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { + if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) { pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 9d694da5..16c3631f 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -201,57 +201,81 @@ finish: return ret; } -/** Platform independent read function. Necessary since not all systems - * treat all file descriptors equal. */ -ssize_t pa_read(int fd, void *buf, size_t count) { - ssize_t r; +/** Platform independent read function. Necessary since not all + * systems treat all file descriptors equal. If type is + * non-NULL it is used to cache the type of the fd. This is + * useful for making sure that only a single syscall is executed per + * function call. The variable pointed to should be initialized to 0 + * by the caller. */ +ssize_t pa_read(int fd, void *buf, size_t count, int *type) { #ifdef OS_IS_WIN32 - r = recv(fd, buf, count, 0); - if (r < 0) { + + if (!type || *type == 0) { + ssize_t r; + + if ((r = recv(fd, buf, count, 0)) >= 0) + return r; + if (WSAGetLastError() != WSAENOTSOCK) { errno = WSAGetLastError(); return r; } + + if (type) + *type = 1; } - if (r < 0) #endif - r = read(fd, buf, count); - - return r; + + return read(fd, buf, count); } /** Similar to pa_read(), but handles writes */ -ssize_t pa_write(int fd, const void *buf, size_t count) { - ssize_t r; +ssize_t pa_write(int fd, const void *buf, size_t count, int *type) { + + if (!type || *type == 0) { + ssize_t r; + if ((r = send(fd, buf, count, MSG_NOSIGNAL)) >= 0) + return r; + #ifdef OS_IS_WIN32 - r = send(fd, buf, count, 0); - if (r < 0) { if (WSAGetLastError() != WSAENOTSOCK) { errno = WSAGetLastError(); return r; } - } - - if (r < 0) +#else + if (errno != ENOTSOCK) + return r; #endif - r = write(fd, buf, count); - return r; + if (type) + *type = 1; + } + + return write(fd, buf, count); } /** Calls read() in a loop. Makes sure that as much as 'size' bytes, * unless EOF is reached or an error occured */ -ssize_t pa_loop_read(int fd, void*data, size_t size) { +ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) { ssize_t ret = 0; - assert(fd >= 0 && data && size); + int _type; + + assert(fd >= 0); + assert(data); + assert(size); + + if (!type) { + _type = 0; + type = &_type; + } while (size > 0) { ssize_t r; - if ((r = pa_read(fd, data, size)) < 0) + if ((r = pa_read(fd, data, size, type)) < 0) return r; if (r == 0) @@ -266,14 +290,23 @@ ssize_t pa_loop_read(int fd, void*data, size_t size) { } /** Similar to pa_loop_read(), but wraps write() */ -ssize_t pa_loop_write(int fd, const void*data, size_t size) { +ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) { ssize_t ret = 0; - assert(fd >= 0 && data && size); + int _type; + + assert(fd >= 0); + assert(data); + assert(size); + + if (!type) { + _type = 0; + type = &_type; + } while (size > 0) { ssize_t r; - if ((r = pa_write(fd, data, size)) < 0) + if ((r = pa_write(fd, data, size, type)) < 0) return r; if (r == 0) diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 0012afc6..864a96ec 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -36,10 +36,10 @@ void pa_make_nonblock_fd(int fd); int pa_make_secure_dir(const char* dir); int pa_make_secure_parent_dir(const char *fn); -ssize_t pa_read(int fd, void *buf, size_t count); -ssize_t pa_write(int fd, const void *buf, size_t count); -ssize_t pa_loop_read(int fd, void*data, size_t size); -ssize_t pa_loop_write(int fd, const void*data, size_t size); +ssize_t pa_read(int fd, void *buf, size_t count, int *type); +ssize_t pa_write(int fd, const void *buf, size_t count, int *type); +ssize_t pa_loop_read(int fd, void*data, size_t size, int *type); +ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type); void pa_check_signal_is_blocked(int sig); diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 8a19094a..842c0e6a 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -49,6 +49,7 @@ struct pa_iochannel { int ifd, ofd; + int ifd_type, ofd_type; pa_mainloop_api* mainloop; pa_iochannel_cb_t callback; @@ -127,6 +128,7 @@ pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) { io = pa_xnew(pa_iochannel, 1); io->ifd = ifd; io->ofd = ofd; + io->ifd_type = io->ofd_type = 0; io->mainloop = m; io->userdata = NULL; @@ -204,7 +206,7 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { assert(l); assert(io->ofd >= 0); - r = pa_write(io->ofd, data, l); + r = pa_write(io->ofd, data, l, &io->ofd_type); if (r >= 0) { io->writable = 0; enable_mainloop_sources(io); @@ -220,7 +222,7 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { assert(data); assert(io->ifd >= 0); - r = pa_read(io->ifd, data, l); + r = pa_read(io->ifd, data, l, &io->ifd_type); if (r >= 0) { io->readable = 0; enable_mainloop_sources(io); diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index b8972866..0ad76a6e 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -56,7 +56,7 @@ static pid_t read_pid(const char *fn, int fd) { assert(fn && fd >= 0); - if ((r = pa_loop_read(fd, t, sizeof(t)-1)) < 0) { + if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) { pa_log_warn(__FILE__": WARNING: failed to read PID file '%s': %s", fn, pa_cstrerror(errno)); return (pid_t) -1; @@ -177,7 +177,7 @@ int pa_pid_file_create(void) { snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid()); l = strlen(t); - if (pa_loop_write(fd, t, l) != (ssize_t) l) { + if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) { pa_log(__FILE__": failed to write PID file."); goto fail; } diff --git a/src/pulsecore/random.c b/src/pulsecore/random.c index 3d3357a5..684ead71 100644 --- a/src/pulsecore/random.c +++ b/src/pulsecore/random.c @@ -61,7 +61,7 @@ static int random_proper(void *ret_data, size_t length) { if ((fd = open(*device, O_RDONLY)) >= 0) { - if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length) + if ((r = pa_loop_read(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) ret = -1; close(fd); -- cgit